$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_05_04
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Core_SharedMemoryManager_hh 00002 #define artdaq_core_Core_SharedMemoryManager_hh 1 00003 00004 #include <atomic> 00005 #include <deque> 00006 #include <list> 00007 #include <mutex> 00008 #include <string> 00009 #include <vector> 00010 #include "artdaq-core/Utilities/TimeUtils.hh" 00011 00012 namespace artdaq { 00017 class SharedMemoryManager 00018 { 00019 public: 00023 enum class BufferSemaphoreFlags 00024 { 00025 Empty, 00026 Writing, 00027 Full, 00028 Reading 00029 }; 00030 00036 static inline std::string FlagToString(BufferSemaphoreFlags flag) 00037 { 00038 switch (flag) 00039 { 00040 case BufferSemaphoreFlags::Empty: 00041 return "Empty"; 00042 case BufferSemaphoreFlags::Writing: 00043 return "Writing"; 00044 case BufferSemaphoreFlags::Full: 00045 return "Full"; 00046 case BufferSemaphoreFlags::Reading: 00047 return "Reading"; 00048 } 00049 return "Unknown"; 00050 } 00051 00061 SharedMemoryManager(uint32_t shm_key, size_t buffer_count = 0, size_t buffer_size = 0, uint64_t buffer_timeout_us = 100 * 1000000, bool destructive_read_mode = true); 00062 00066 virtual ~SharedMemoryManager() noexcept; 00067 00071 bool Attach(size_t timeout_usec = 0); 00072 00077 int GetBufferForReading(); 00078 00084 int GetBufferForWriting(bool overwrite); 00085 00090 bool ReadyForRead(); 00091 00097 virtual bool ReadyForWrite(bool overwrite); 00098 00103 size_t ReadReadyCount(); 00104 00110 size_t WriteReadyCount(bool overwrite); 00111 00117 std::deque<int> GetBuffersOwnedByManager(bool locked = true); 00118 00124 size_t BufferDataSize(int buffer); 00125 00129 size_t BufferSize() { return (shm_ptr_ != nullptr ? shm_ptr_->buffer_size : 0); } 00130 00135 void ResetReadPos(int buffer); 00136 00141 void ResetWritePos(int buffer); 00147 void IncrementReadPos(int buffer, size_t read); 00148 00155 bool IncrementWritePos(int buffer, size_t written); 00156 00162 bool MoreDataInBuffer(int buffer); 00163 00170 bool CheckBuffer(int buffer, BufferSemaphoreFlags flags); 00171 00177 void MarkBufferFull(int buffer, int destination = -1); 00178 00184 void MarkBufferEmpty(int buffer, bool force = false); 00185 00192 bool ResetBuffer(int buffer); 00193 00197 void GetNewId() 00198 { 00199 if (manager_id_ < 0 && IsValid()) manager_id_ = shm_ptr_->next_id.fetch_add(1); 00200 } 00201 00206 uint16_t GetAttachedCount() const; 00207 00211 void ResetAttachedCount() const 00212 { 00213 if (manager_id_ == 0 && IsValid()) shm_ptr_->next_id = 1; 00214 } 00215 00220 int GetMyId() const { return manager_id_; } 00221 00226 int GetRank() const { return IsValid() ? shm_ptr_->rank : -1; } 00227 00232 void SetRank(int rank) 00233 { 00234 if (manager_id_ == 0 && IsValid()) shm_ptr_->rank = rank; 00235 } 00236 00241 bool IsValid() const { return shm_ptr_ ? true : false; } 00242 00246 bool IsEndOfData() const; 00247 00252 size_t size() const { return IsValid() ? shm_ptr_->buffer_count : 0; } 00253 00261 size_t Write(int buffer, void* data, size_t size); 00262 00270 bool Read(int buffer, void* data, size_t size); 00271 00276 virtual std::string toString(); 00277 00282 uint32_t GetKey() const { return shm_key_; } 00283 00289 void* GetReadPos(int buffer); 00290 00296 void* GetWritePos(int buffer); 00297 00303 void* GetBufferStart(int buffer); 00304 00312 void Detach(bool throwException = false, std::string category = "", std::string message = "", bool force = false); 00313 00318 uint64_t GetBufferTimeout() const { return IsValid() ? shm_ptr_->buffer_timeout_us : 0; } 00319 00324 size_t GetBufferCount() const { return IsValid() ? shm_ptr_->next_sequence_id : 0; } 00325 00330 size_t GetLastSeenBufferID() const { return last_seen_id_; } 00331 00335 size_t GetLowestSeqIDRead() const { return IsValid() ? shm_ptr_->lowest_seq_id_read : 0; } 00336 00341 void SetMinWriteSize(size_t size) { min_write_size_ = size; } 00342 00347 std::list<std::pair<int, BufferSemaphoreFlags>> GetBufferReport(); 00348 00352 void TouchBuffer(int buffer) { return touchBuffer_(getBufferInfo_(buffer)); } 00353 00354 private: 00355 struct ShmBuffer 00356 { 00357 size_t writePos; 00358 size_t readPos; 00359 std::atomic<BufferSemaphoreFlags> sem; 00360 std::atomic<int16_t> sem_id; 00361 std::atomic<size_t> sequence_id; 00362 std::atomic<uint64_t> last_touch_time; 00363 }; 00364 00365 struct ShmStruct 00366 { 00367 std::atomic<unsigned int> reader_pos; 00368 std::atomic<unsigned int> writer_pos; 00369 int buffer_count; 00370 size_t buffer_size; 00371 size_t buffer_timeout_us; 00372 size_t next_sequence_id; 00373 size_t lowest_seq_id_read; 00374 bool destructive_read_mode; 00375 00376 std::atomic<int> next_id; 00377 int rank; 00378 unsigned ready_magic; 00379 }; 00380 00381 uint8_t* dataStart_() const; 00382 uint8_t* bufferStart_(int buffer); 00383 ShmBuffer* getBufferInfo_(int buffer); 00384 bool checkBuffer_(ShmBuffer* buffer, BufferSemaphoreFlags flags, bool exceptions = true); 00385 void touchBuffer_(ShmBuffer* buffer); 00386 00387 ShmStruct requested_shm_parameters_; 00388 00389 int shm_segment_id_; 00390 ShmStruct* shm_ptr_; 00391 uint32_t shm_key_; 00392 int manager_id_; 00393 mutable std::vector<std::mutex> buffer_mutexes_; 00394 mutable std::mutex search_mutex_; 00395 00396 std::atomic<size_t> last_seen_id_; 00397 size_t min_write_size_; 00398 }; 00399 00400 } // namespace artdaq 00401 00402 #endif // artdaq_core_Core_SharedMemoryManager_hh