Synchronizer.cpp 2.93 KB
/*
 * Synchronizer.cpp
 *
 *  Created on: 15 gru 2018
 *      Author: mariuszo
 */

#include <sys/mman.h>
#include "Synchronizer.h"
#include "MemoryManager.h"

std::map<std::string, SynchronizerBase*> SynchronizerBase::synchronizersMap;
std::mutex SynchronizerBase::synchronizersMapLock;

SynchronizerBase::SynchronizerBase(const std::string& name) : m_name(name), m_slotsRingBufferSize(0), m_syncSlotsRingBuffer(NULL), m_synchronizerData(NULL) {
}

SynchronizerBase::~SynchronizerBase() {
}

void SynchronizerBase::create(){
	synchronizersMapLock.lock();
	try {
		if (synchronizersMap.find(m_name)!=synchronizersMap.end()){
			synchronizersMapLock.unlock();
			throw std::logic_error("Process data memory\""+m_name+"\" already exists");
		}

		MemoryManager<access_type::access_slave> memoryManagerData(m_name);
		memoryManagerData.attach();

		m_slotsRingBufferSize = memoryManagerData.dataSlotsRingBufferSize();

		m_synchronizerData=new synchronizerData;
		m_synchronizerData->writeSlotID=0;
		sem_init(&(m_synchronizerData->lock),0,0);
		m_synchronizerData->consumersLock=PTHREAD_RWLOCK_INITIALIZER;
		mlock(m_synchronizerData,sizeof(*m_synchronizerData));

		m_syncSlotsRingBuffer=new syncSlot[m_slotsRingBufferSize];
		mlock(m_syncSlotsRingBuffer,sizeof(m_slotsRingBufferSize*sizeof(*m_syncSlotsRingBuffer)));
		for (size_t i = 0; i < m_slotsRingBufferSize; ++i) {
			if (wrflock_init(&(m_syncSlotsRingBuffer[i].lock), WRFLOCK_FWAITYIELD, 0)!=0)
				throw std::logic_error("WRF lock init error");
			m_syncSlotsRingBuffer[i].dataSlotID=static_cast<off_t>(specialid_type::specialid_empty);
		}
		synchronizersMap[m_name]=this;
	}
	catch (...) {
		synchronizersMapLock.unlock();
		throw;
	}
	synchronizersMapLock.unlock();
}

void SynchronizerBase::attach(){
	synchronizersMapLock.lock();
	try {
		if (synchronizersMap.find(m_name)==synchronizersMap.end()){
			synchronizersMapLock.unlock();
			throw std::logic_error("Synchronizer data \""+m_name+"\" does not exists");
		}

		MemoryManager<access_type::access_slave> ringbufferData(m_name);
		ringbufferData.attach();

		m_slotsRingBufferSize = ringbufferData.dataSlotsRingBufferSize();

		m_synchronizerData=synchronizersMap[m_name]->m_synchronizerData;
		m_syncSlotsRingBuffer=synchronizersMap[m_name]->m_syncSlotsRingBuffer;
	}
	catch (...) {
		synchronizersMapLock.unlock();
		throw;
	}
	synchronizersMapLock.unlock();
}

void SynchronizerBase::destroy(){
	synchronizersMapLock.lock();
	if (m_syncSlotsRingBuffer){
		for (size_t i=0;i<m_slotsRingBufferSize;i++){
			wrflock_destroy(&(m_syncSlotsRingBuffer[i].lock));
		}
		munlock(m_syncSlotsRingBuffer,m_slotsRingBufferSize*sizeof(*m_syncSlotsRingBuffer));
		delete [] m_syncSlotsRingBuffer;
	}
	if (m_synchronizerData){
		sem_destroy(&(m_synchronizerData->lock));
		munlock(m_synchronizerData,sizeof(*m_synchronizerData));
		delete m_synchronizerData;
	}
	assert (synchronizersMap.find(m_name)!=synchronizersMap.end());
	synchronizersMap.erase(m_name);
	synchronizersMapLock.unlock();
}