artdaq_core  v3_01_04
SharedMemoryManager.hh
1 #ifndef artdaq_core_Core_SharedMemoryManager_hh
2 #define artdaq_core_Core_SharedMemoryManager_hh 1
3 
4 #include <atomic>
5 #include <string>
6 #include <deque>
7 #include "artdaq-core/Utilities/TimeUtils.hh"
8 #include <mutex>
9 #include <unordered_map>
10 #include <set>
11 
12 namespace artdaq
13 {
19  {
20  public:
21 
26  {
27  Empty,
28  Writing,
29  Full,
30  Reading
31  };
32 
38  static std::string FlagToString(BufferSemaphoreFlags flag)
39  {
40  switch (flag)
41  {
43  return "Empty";
45  return "Writing";
47  return "Full";
49  return "Reading";
50  }
51  return "Unknown";
52  }
53 
63  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);
64 
68  virtual ~SharedMemoryManager() noexcept;
69 
70 
74  void Attach();
75 
80  int GetBufferForReading();
81 
87  int GetBufferForWriting(bool overwrite);
88 
93  bool ReadyForRead() { return ReadReadyCount() > 0; }
94 
100  bool ReadyForWrite(bool overwrite) { return WriteReadyCount(overwrite) > 0; }
101 
106  size_t ReadReadyCount();
107 
113  size_t WriteReadyCount(bool overwrite);
114 
119  std::deque<int> GetBuffersOwnedByManager();
120 
126  size_t BufferDataSize(int buffer);
127 
132  void ResetReadPos(int buffer);
133 
138  void ResetWritePos(int buffer);
144  void IncrementReadPos(int buffer, size_t read);
145 
151  void IncrementWritePos(int buffer, size_t written);
152 
158  bool MoreDataInBuffer(int buffer);
159 
166  bool CheckBuffer(int buffer, BufferSemaphoreFlags flags);
167 
173  void MarkBufferFull(int buffer, int destination = -1);
174 
180  void MarkBufferEmpty(int buffer, bool force = false);
181 
188  bool ResetBuffer(int buffer);
189 
193  void GetNewId() { if (manager_id_ < 0 && IsValid()) manager_id_ = shm_ptr_->next_id.fetch_add(1); }
194 
199  uint16_t GetAttachedCount() const { return IsValid() ? shm_ptr_->next_id.load() - 1 : -1; }
200 
204  void ResetAttachedCount() const { if (manager_id_ == 0 && IsValid()) shm_ptr_->next_id = 1; }
205 
210  int GetMyId() const { return manager_id_; }
211 
216  int GetRank()const { return IsValid() ? shm_ptr_->rank : -1; }
217 
222  void SetRank(int rank) { if (manager_id_ == 0 && IsValid()) shm_ptr_->rank = rank; }
223 
228  bool IsValid() const { return shm_ptr_ ? true : false; }
229 
234  size_t size() const { return IsValid() ? shm_ptr_->buffer_count : 0; }
235 
243  size_t Write(int buffer, void* data, size_t size);
244 
252  bool Read(int buffer, void* data, size_t size);
253 
258  virtual std::string toString();
259 
264  uint32_t GetKey() const { return shm_key_; }
265 
271  void* GetReadPos(int buffer);
272 
278  void* GetWritePos(int buffer);
279 
285  void* GetBufferStart(int buffer);
286 
293  void Detach(bool throwException = false, std::string category = "", std::string message = "");
294 
299  uint64_t GetBufferTimeout() const { return IsValid() ? shm_ptr_->buffer_timeout_us : 0; }
300 
305  size_t GetBufferCount() const { return IsValid() ? shm_ptr_->next_sequence_id : 0; }
306 
311  size_t GetLastSeenBufferID() const { return last_seen_id_; }
312 
316  size_t GetLowestSeqIDRead() const { return IsValid() ? shm_ptr_->lowest_seq_id_read : 0; }
317 
322  void SetMinWriteSize(size_t size) { min_write_size_ = size; }
323  private:
324  struct ShmBuffer
325  {
326  size_t writePos;
327  size_t readPos;
328  std::atomic<BufferSemaphoreFlags> sem;
329  std::atomic<int16_t> sem_id;
330  std::atomic<size_t> sequence_id;
331  std::atomic<uint64_t> last_touch_time;
332  };
333 
334  struct ShmStruct
335  {
336  std::atomic<unsigned int> reader_pos;
337  std::atomic<unsigned int> writer_pos;
338  int buffer_count;
339  size_t buffer_size;
340  size_t buffer_timeout_us;
341  size_t next_sequence_id;
342  size_t lowest_seq_id_read;
343  bool destructive_read_mode;
344 
345  std::atomic<int> next_id;
346  int rank;
347  unsigned ready_magic;
348  };
349 
350  uint8_t* dataStart_() const;
351  uint8_t* bufferStart_(int buffer);
352  ShmBuffer* getBufferInfo_(int buffer);
353  bool checkBuffer_(ShmBuffer* buffer, BufferSemaphoreFlags flags, bool exceptions = true);
354  void touchBuffer_(ShmBuffer* buffer);
355 
356  ShmStruct requested_shm_parameters_;
357 
358  int shm_segment_id_;
359  ShmStruct* shm_ptr_;
360  uint32_t shm_key_;
361  int manager_id_;
362  mutable std::unordered_map<int, std::mutex> buffer_mutexes_;
363  mutable std::mutex search_mutex_;
364 
365  size_t last_seen_id_;
366  size_t min_write_size_;
367  };
368 
369 }
370 
371 #endif // artdaq_core_Core_SharedMemoryManager_hh
bool Read(int buffer, void *data, size_t size)
Read size bytes of data from buffer into the given pointer.
void IncrementReadPos(int buffer, size_t read)
Increment the read position for a given buffer.
void ResetAttachedCount() const
Reset the attached manager count to 0.
bool IsValid() const
Is the shared memory pointer valid?
void ResetReadPos(int buffer)
Set the read position of the given buffer to the beginning of the buffer.
static std::string FlagToString(BufferSemaphoreFlags flag)
Convert a BufferSemaphoreFlags variable to its string represenatation.
bool MoreDataInBuffer(int buffer)
Determine if more data is available to be read, based on the read position and data size...
virtual std::string toString()
Write information about the SharedMemory to a string.
void GetNewId()
Assign a new ID to the current SharedMemoryManager, if one has not yet been assigned.
The buffer is full, and waiting for a reader.
BufferSemaphoreFlags
The BufferSemaphoreFlags enumeration represents the different possible &quot;states&quot; of a given shared mem...
size_t BufferDataSize(int buffer)
Get the current size of the buffer&#39;s data.
void Attach()
Reconnect to the shared memory segment.
virtual ~SharedMemoryManager() noexcept
SharedMemoryManager Destructor.
The buffer is currently being read from.
The buffer is currently being written to.
The SharedMemoryManager creates a Shared Memory area which is divided into a number of fixed-size buf...
The buffer is empty, and waiting for a writer.
size_t ReadReadyCount()
Count the number of buffers that are ready for reading.
bool ResetBuffer(int buffer)
Resets the buffer from Reading to Full. This operation will only have an effect if performed by the o...
int GetRank() const
Get the rank of the owner of the Shared Memory (artdaq assigns rank to each artdaq process for data f...
size_t GetLowestSeqIDRead() const
Gets the lowest sequence ID that has been read by any reader, as reported by the readers.
size_t size() const
Get the number of buffers in the shared memory segment.
bool CheckBuffer(int buffer, BufferSemaphoreFlags flags)
Check both semaphore conditions (Mode flag and manager ID) for a given buffer.
size_t GetLastSeenBufferID() const
Gets the highest buffer number either written or read by this SharedMemoryManager.
uint32_t GetKey() const
Get the key of the shared memory attached to this SharedMemoryManager.
void IncrementWritePos(int buffer, size_t written)
Increment the write position for a given buffer.
void MarkBufferFull(int buffer, int destination=-1)
Release a buffer from a writer, marking it Full and ready for a reader.
void MarkBufferEmpty(int buffer, bool force=false)
Release a buffer from a reader, marking it Empty and ready to accept more data.
uint64_t GetBufferTimeout() const
Gets the configured timeout for buffers to be declared &quot;stale&quot;.
void ResetWritePos(int buffer)
Set the write position of the given buffer to the beginning of the buffer.
void SetMinWriteSize(size_t size)
Sets the threshold after which a buffer should be considered &quot;non-empty&quot; (in case of default headers)...
std::deque< int > GetBuffersOwnedByManager()
Get the list of all buffers currently owned by this manager instance.
size_t GetBufferCount() const
Gets the number of buffers which have been processed through the Shared Memory.
void * GetWritePos(int buffer)
Get a pointer to the current write position of the buffer.
size_t Write(int buffer, void *data, size_t size)
Write size bytes of data from the given pointer to a buffer.
void * GetReadPos(int buffer)
Get a pointer to the current read position of the buffer.
void * GetBufferStart(int buffer)
Get a pointer to the start position of the buffer.
void Detach(bool throwException=false, std::string category="", std::string message="")
Detach from the Shared Memory segment, optionally throwing a cet::exception with the specified proper...
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)
SharedMemoryManager Constructor.
bool ReadyForRead()
Whether any buffer is ready for read.
void SetRank(int rank)
Set the rank stored in the Shared Memory, if the current instance is the owner of the shared memory...
int GetBufferForWriting(bool overwrite)
Finds a buffer that is ready to be written to, and reserves it for the calling manager.
uint16_t GetAttachedCount() const
Get the number of attached SharedMemoryManagers.
size_t WriteReadyCount(bool overwrite)
Count the number of buffers that are ready for writing.
int GetMyId() const
Get the ID number of the current SharedMemoryManager.
int GetBufferForReading()
Finds a buffer that is ready to be read, and reserves it for the calling manager. ...
bool ReadyForWrite(bool overwrite)
Whether any buffer is available for write.