SharedMemoryBlock::SharedMemoryBlock(const std::string& filename, char character, size_t blockSize) : lock(filename), blockSize(blockSize) { key_t key = ftok(filename.c_str(), character); if (key > 0) { shmId = shmget(key, blockSize + sizeof(size_t), 0644 | IPC_CREAT); if (shmId > 0) { void* tmpPtr = shmat(shmId, NULL, 0); if (tmpPtr != (void*) -1) { ptrData = static_cast< byte_t* >(tmpPtr); } else { if (getAmountProcessesAttached() == 0) { shmctl(shmId, IPC_RMID, NULL); } throw SharedMemoryException(SharedMemoryException::shmat); } } else { throw SharedMemoryException(SharedMemoryException::shmget); } } else { throw SharedMemoryException(SharedMemoryException::ftok); } }
void SharedMemoryBlock::freeResources() const { if (shmdt(static_cast< void* >(ptrData)) != -1) { if (getAmountProcessesAttached() == 0) { if (shmctl(shmId, IPC_RMID, NULL) == -1) { throw SharedMemoryException(SharedMemoryException::shmctl); } } } else { throw SharedMemoryException(SharedMemoryException::shmdt); } }
//SM FUNCTIONS void DoomController::SMInit() { this->SMName = std::string(SM_NAME_BASE) + instanceId; //bip::shared_memory_object::remove(this->SMName.c_str()); try { this->SM = bip::shared_memory_object(bip::open_only, this->SMName.c_str(), bip::read_write); this->GameVariablesSMRegion = new bip::mapped_region(this->SM, bip::read_only, 0, sizeof(DoomController::GameVariablesStruct)); this->gameVariables = static_cast<DoomController::GameVariablesStruct *>(this->GameVariablesSMRegion->get_address()); this->InputSMRegion = new bip::mapped_region(this->SM, bip::read_write, sizeof(DoomController::GameVariablesStruct), sizeof(DoomController::InputStruct)); this->input = static_cast<DoomController::InputStruct *>(this->InputSMRegion->get_address()); this->screenWidth = this->gameVariables->SCREEN_WIDTH; this->screenHeight = this->gameVariables->SCREEN_HEIGHT; this->screenPitch = this->gameVariables->SCREEN_PITCH; this->screenSize = this->gameVariables->SCREEN_SIZE; this->screenFormat = (ScreenFormat)this->gameVariables->SCREEN_FORMAT; this->ScreenSMRegion = new bip::mapped_region(this->SM, bip::read_only, sizeof(DoomController::GameVariablesStruct) + sizeof(DoomController::InputStruct), this->screenSize); this->screen = static_cast<uint8_t *>(this->ScreenSMRegion->get_address()); } catch (bip::interprocess_exception &ex) { throw SharedMemoryException(); } }
size_t SharedMemoryBlock::write(const ByteStream& data) { size_t dataSize = data.getTamanioOcupado(); if (blockSize < dataSize) { throw SharedMemoryException(SharedMemoryException::write_size); } try { lock.seizeExclusiveLock(); memcpy(ptrData, &dataSize, sizeof(size_t)); memcpy(ptrData + sizeof(size_t), data.obtenerStream(), dataSize); lock.releaseLock(); } catch(const LockException &e) { throw SharedMemoryException(SharedMemoryException::write_lock); } return dataSize; }
size_t SharedMemoryBlock::read(ByteStream& data) const { size_t dataSize = 0; byte_t* buffer = NULL; try { lock.seizeSharedLock(); memcpy(&dataSize, ptrData, sizeof(size_t)); buffer = new byte_t[dataSize]; memcpy(buffer, ptrData + sizeof(size_t), dataSize); lock.releaseLock(); data.asignarStream(buffer, dataSize); } catch(const LockException &e) { delete[] buffer; throw SharedMemoryException(SharedMemoryException::read_lock); } delete[] buffer; return dataSize; }