3 #include "cetlib_except/exception.h"
4 #include "artdaq-core/Core/SharedMemoryManager.hh"
5 #include "artdaq-core/Utilities/TraceLock.hh"
15 requested_shm_parameters_.buffer_count = buffer_count;
16 requested_shm_parameters_.buffer_size = buffer_size;
17 requested_shm_parameters_.buffer_timeout_us = buffer_timeout_us;
18 requested_shm_parameters_.destructive_read_mode = destructive_read_mode;
25 TLOG_ARB(5,
"SharedMemoryManager") <<
"~SharedMemoryManager called" << TLOG_ENDL;
27 TLOG_ARB(5,
"SharedMemoryManager") <<
"~SharedMemoryManager done" << TLOG_ENDL;
34 if (manager_id_ == 0)
return;
37 auto start_time = std::chrono::steady_clock::now();
39 size_t shmSize = requested_shm_parameters_.buffer_count * (requested_shm_parameters_.buffer_size +
sizeof(ShmBuffer)) +
sizeof(ShmStruct);
41 shm_segment_id_ = shmget(shm_key_, shmSize, 0666);
42 if (shm_segment_id_ == -1 && requested_shm_parameters_.buffer_count > 0 && manager_id_ <= 0)
44 TLOG_DEBUG(
"SharedMemoryManager") <<
"Creating shared memory segment with key 0x" << std::hex << shm_key_ << TLOG_ENDL;
45 shm_segment_id_ = shmget(shm_key_, shmSize, IPC_CREAT | 0666);
51 shm_segment_id_ = shmget(shm_key_, shmSize, 0666);
54 TLOG_DEBUG(
"SharedMemoryManager") <<
"shm_key == 0x" << std::hex << shm_key_ <<
", shm_segment_id == " << shm_segment_id_ << TLOG_ENDL;
56 if (shm_segment_id_ > -1)
58 TLOG_DEBUG(
"SharedMemoryManager")
59 <<
"Attached to shared memory segment with ID = " << shm_segment_id_
60 <<
" and size " << shmSize
61 <<
" bytes" << TLOG_ENDL;
62 shm_ptr_ = (ShmStruct*)shmat(shm_segment_id_, 0, 0);
63 TLOG_DEBUG(
"SharedMemoryManager")
64 <<
"Attached to shared memory segment at address "
65 << std::hex << (
void*)shm_ptr_ << std::dec << TLOG_ENDL;
66 if (shm_ptr_ && shm_ptr_ != (
void *)-1)
70 if (shm_ptr_->ready_magic == 0xCAFE1111)
72 TLOG_ERROR(
"SharedMemoryManager") <<
"Owner encountered already-initialized Shared Memory!" << TLOG_ENDL;
75 TLOG_DEBUG(
"SharedMemoryManager") <<
"Owner initializing Shared Memory" << TLOG_ENDL;
76 shm_ptr_->next_id = 1;
77 shm_ptr_->next_sequence_id = 0;
78 shm_ptr_->reader_pos = 0;
79 shm_ptr_->writer_pos = 0;
80 shm_ptr_->buffer_size = requested_shm_parameters_.buffer_size;
81 shm_ptr_->buffer_count = requested_shm_parameters_.buffer_count;
82 shm_ptr_->buffer_timeout_us = requested_shm_parameters_.buffer_timeout_us;
83 shm_ptr_->destructive_read_mode = requested_shm_parameters_.destructive_read_mode;
85 for (
int ii = 0; ii < static_cast<int>(requested_shm_parameters_.buffer_count); ++ii)
87 getBufferInfo_(ii)->writePos = 0;
88 getBufferInfo_(ii)->readPos = 0;
89 getBufferInfo_(ii)->sem = BufferSemaphoreFlags::Empty;
90 getBufferInfo_(ii)->sem_id = -1;
93 shm_ptr_->ready_magic = 0xCAFE1111;
97 TLOG_DEBUG(
"SharedMemoryManager") <<
"Waiting for owner to initalize Shared Memory" << TLOG_ENDL;
98 while (shm_ptr_->ready_magic != 0xCAFE1111) { usleep(1000); }
99 TLOG_DEBUG(
"SharedMemoryManager") <<
"Getting ID from Shared Memory" << TLOG_ENDL;
101 shm_ptr_->lowest_seq_id_read = 0;
102 TLOG_DEBUG(
"SharedMemoryManager") <<
"Getting Shared Memory Size parameters" << TLOG_ENDL;
105 TLOG_DEBUG(
"SharedMemoryManager") <<
"Initialization Complete: "
106 <<
"key: 0x" << std::hex << shm_key_
107 <<
", manager ID: " << manager_id_
108 <<
", Buffer size: " << std::to_string(shm_ptr_->buffer_size)
109 <<
", Buffer count: " << std::to_string(shm_ptr_->buffer_count) << TLOG_ENDL;
114 TLOG_ERROR(
"SharedMemoryManager") <<
"Failed to attach to shared memory segment "
115 << shm_segment_id_ << TLOG_ENDL;
120 TLOG_ERROR(
"SharedMemoryManager") <<
"Failed to connect to shared memory segment"
121 <<
", errno = " << errno <<
". Please check "
122 <<
"if a stale shared memory segment needs to "
123 <<
"be cleaned up. (ipcs, ipcrm -m <segId>)" << TLOG_ENDL;
130 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForReading BEGIN" << TLOG_ENDL;
133 TraceLock lk(search_mutex_, 11,
"GetBufferForReadingSearch");
134 auto rp = shm_ptr_->reader_pos.load();
136 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForReading lock acquired, scanning buffers" << TLOG_ENDL;
141 ShmBuffer* buffer_ptr =
nullptr;
143 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
145 auto buffer = (ii + rp) % shm_ptr_->buffer_count;
148 TLOG_ARB(14,
"SharedMemoryManager") <<
"GetBufferForReading Checking if buffer " << buffer <<
" is stale" << TLOG_ENDL;
151 auto buf = getBufferInfo_(buffer);
152 TLOG_ARB(14,
"SharedMemoryManager") <<
"GetBufferForReading: Buffer " << buffer <<
": sem=" << FlagToString(buf->sem) <<
" (expected " << FlagToString(BufferSemaphoreFlags::Full) <<
"), sem_id=" << buf->sem_id <<
" (" << manager_id_ <<
" or -1), seqid=" << buf->sequence_id <<
" (> " << last_seen_id_ <<
")" << TLOG_ENDL;
153 if (buf->sem == BufferSemaphoreFlags::Full && (buf->sem_id == -1 || buf->sem_id == manager_id_) && buf->sequence_id > last_seen_id_)
155 if (buf->sequence_id < seqID)
158 seqID = buf->sequence_id;
164 if (!buffer_ptr || (buffer_ptr && buffer_ptr->sem_id != -1 && buffer_ptr->sem_id != manager_id_))
171 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForReading Found buffer " << buffer_num << TLOG_ENDL;
172 buffer_ptr->sem_id = manager_id_;
173 buffer_ptr->sem = BufferSemaphoreFlags::Reading;
174 if (buffer_ptr->sem_id != manager_id_) {
continue; }
175 buffer_ptr->readPos = 0;
176 touchBuffer_(buffer_ptr);
177 if (buffer_ptr->sem_id != manager_id_) {
continue; }
178 if (shm_ptr_->destructive_read_mode && shm_ptr_->lowest_seq_id_read == last_seen_id_)
180 shm_ptr_->lowest_seq_id_read = seqID;
182 last_seen_id_ = seqID;
183 if (shm_ptr_->destructive_read_mode) shm_ptr_->reader_pos = (buffer_num + 1) % shm_ptr_->buffer_count;
188 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForReading returning -1 because no buffers are ready" << TLOG_ENDL;
194 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForWriting BEGIN" << TLOG_ENDL;
196 TraceLock lk(search_mutex_, 12,
"GetBufferForWritingSearch");
197 auto wp = shm_ptr_->writer_pos.load();
200 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
202 auto buffer = (ii + wp) % shm_ptr_->buffer_count;
206 auto buf = getBufferInfo_(buffer);
207 if (buf->sem == BufferSemaphoreFlags::Empty)
209 buf->sem_id = manager_id_;
210 buf->sem = BufferSemaphoreFlags::Writing;
211 if (buf->sem_id != manager_id_)
continue;
212 buf->sequence_id = ++shm_ptr_->next_sequence_id;
214 shm_ptr_->writer_pos = (buffer + 1) % shm_ptr_->buffer_count;
216 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForWriting returning " << buffer << TLOG_ENDL;
224 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
226 auto buffer = (ii + wp) % shm_ptr_->buffer_count;
230 auto buf = getBufferInfo_(buffer);
231 if (buf->sem == BufferSemaphoreFlags::Full)
233 buf->sem_id = manager_id_;
234 buf->sem = BufferSemaphoreFlags::Writing;
235 if (buf->sem_id != manager_id_)
continue;
236 buf->sequence_id = ++shm_ptr_->next_sequence_id;
238 shm_ptr_->writer_pos = (buffer + 1) % shm_ptr_->buffer_count;
240 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForWriting returning " << buffer << TLOG_ENDL;
246 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
248 auto buffer = (ii + wp) % shm_ptr_->buffer_count;
252 auto buf = getBufferInfo_(buffer);
253 if (buf->sem == BufferSemaphoreFlags::Reading)
255 buf->sem_id = manager_id_;
256 buf->sem = BufferSemaphoreFlags::Writing;
257 if (buf->sem_id != manager_id_)
continue;
258 buf->sequence_id = ++shm_ptr_->next_sequence_id;
260 shm_ptr_->writer_pos = (buffer + 1) % shm_ptr_->buffer_count;
261 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForWriting returning " << buffer << TLOG_ENDL;
268 TLOG_ARB(13,
"SharedMemoryManager") <<
"GetBufferForWriting Returning -1 because no buffers are ready" << TLOG_ENDL;
274 if (!IsValid())
return 0;
275 TLOG_ARB(23,
"SharedMemoryManager") <<
"ReadReadyCount BEGIN" << TLOG_ENDL;
277 TraceLock lk(search_mutex_, 14,
"ReadReadyCountSearch");
279 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
281 TLOG_ARB(24,
"SharedMemoryManager") <<
"ReadReadyCount: Checking if buffer " << ii <<
" is stale." << TLOG_ENDL;
283 auto buf = getBufferInfo_(ii);
284 TLOG_ARB(24,
"SharedMemoryManager") <<
"ReadReadyCount: Buffer " << ii <<
": sem=" << FlagToString(buf->sem) <<
" (expected " << FlagToString(BufferSemaphoreFlags::Full) <<
"), sem_id=" << buf->sem_id <<
" (" << manager_id_ <<
" or -1), seqid=" << buf->sequence_id <<
" (> " << last_seen_id_ <<
")" << TLOG_ENDL;
285 if (buf->sem == BufferSemaphoreFlags::Full && (buf->sem_id == -1 || buf->sem_id == manager_id_) && buf->sequence_id > last_seen_id_)
287 TLOG_ARB(24,
"SharedMemoryManager") <<
"ReadReadyCount: Buffer " << ii <<
" is either unowned or owned by this manager, and is marked full." << TLOG_ENDL;
292 TLOG_ARB(23,
"SharedMemoryManager") <<
"ReadReadyCount returning " << std::to_string(count) << TLOG_ENDL;
298 if (!IsValid())
return 0;
300 TraceLock lk(search_mutex_, 15,
"WriteReadyCountSearch");
302 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
305 auto buf = getBufferInfo_(ii);
306 if ((buf->sem == BufferSemaphoreFlags::Empty && buf->sem_id == -1)
307 || (overwrite && buf->sem != BufferSemaphoreFlags::Writing))
318 std::deque<int> output;
319 if (!IsValid())
return output;
320 TraceLock lk(search_mutex_, 16,
"GetOwnedSearch");
321 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
323 auto buf = getBufferInfo_(ii);
324 if (buf->sem_id == manager_id_)
326 output.push_back(ii);
336 TraceLock lk(buffer_mutexes_[buffer], 17,
"DataSizeBuffer" + std::to_string(buffer));
337 auto buf = getBufferInfo_(buffer);
339 return buf->writePos;
346 TraceLock lk(buffer_mutexes_[buffer], 18,
"ResetReadPosBuffer" + std::to_string(buffer));
347 auto buf = getBufferInfo_(buffer);
355 TraceLock lk(buffer_mutexes_[buffer], 18,
"ResetWritePosBuffer" + std::to_string(buffer));
356 auto buf = getBufferInfo_(buffer);
357 checkBuffer_(buf, BufferSemaphoreFlags::Writing);
365 TraceLock lk(buffer_mutexes_[buffer], 19,
"IncReadPosBuffer" + std::to_string(buffer));
366 auto buf = getBufferInfo_(buffer);
368 TLOG_ARB(13,
"SharedMemoryManager") <<
"IncrementReadPos: buffer= " << buffer <<
", readPos=" << std::to_string(buf->readPos) <<
", bytes read=" << std::to_string(read) << TLOG_ENDL;
369 buf->readPos = buf->readPos + read;
370 TLOG_ARB(13,
"SharedMemoryManager") <<
"IncrementReadPos: buffer= " << buffer <<
", New readPos is " << std::to_string(buf->readPos) << TLOG_ENDL;
372 Detach(
true,
"LogicError",
"Cannot increment Read pos by 0! (buffer=" + std::to_string(buffer) +
", readPos=" + std::to_string(buf->readPos) +
", writePos=" + std::to_string(buf->writePos) +
")");
378 TraceLock lk(buffer_mutexes_[buffer], 20,
"IncWritePosBuffer" + std::to_string(buffer));
379 auto buf = getBufferInfo_(buffer);
381 TLOG_ARB(13,
"SharedMemoryManager") <<
"IncrementWritePos: buffer= " << buffer <<
", writePos=" << std::to_string(buf->writePos) <<
", bytes written=" << std::to_string(written) << TLOG_ENDL;
382 buf->writePos += written;
383 TLOG_ARB(13,
"SharedMemoryManager") <<
"IncrementWritePos: buffer= " << buffer <<
", New writePos is " << std::to_string(buf->writePos) << TLOG_ENDL;
384 if (written == 0) Detach(
true,
"LogicError",
"Cannot increment Write pos by 0!");
390 TraceLock lk(buffer_mutexes_[buffer], 21,
"MoreDataInBuffer" + std::to_string(buffer));
391 auto buf = getBufferInfo_(buffer);
392 TLOG_ARB(13,
"SharedMemoryManager") <<
"MoreDataInBuffer: buffer= " << buffer <<
", readPos=" << std::to_string(buf->readPos) <<
", writePos=" << std::to_string(buf->writePos) << TLOG_ENDL;
393 return buf->readPos < buf->writePos;
399 TraceLock lk(buffer_mutexes_[buffer], 22,
"CheckBuffer" + std::to_string(buffer));
400 return checkBuffer_(getBufferInfo_(buffer), flags,
false);
406 TraceLock lk(buffer_mutexes_[buffer], 23,
"FillBuffer" + std::to_string(buffer));
407 auto shmBuf = getBufferInfo_(buffer);
408 touchBuffer_(shmBuf);
409 if (shmBuf->sem_id == manager_id_)
411 if (shmBuf->sem != BufferSemaphoreFlags::Full)
412 shmBuf->sem = BufferSemaphoreFlags::Full;
414 shmBuf->sem_id = destination;
420 TLOG_ARB(13,
"SharedMemoryManager") <<
"MarkBufferEmpty BEGIN" << TLOG_ENDL;
422 TraceLock lk(buffer_mutexes_[buffer], 24,
"EmptyBuffer" + std::to_string(buffer));
423 auto shmBuf = getBufferInfo_(buffer);
426 checkBuffer_(shmBuf, BufferSemaphoreFlags::Reading,
true);
428 touchBuffer_(shmBuf);
431 shmBuf->sem = BufferSemaphoreFlags::Full;
433 if ((force && (manager_id_ == 0 || manager_id_ == shmBuf->sem_id)) || (!force && shm_ptr_->destructive_read_mode))
435 TLOG_ARB(13,
"SharedMemoryManager") <<
"MarkBufferEmpty Resetting buffer to Empty state" << TLOG_ENDL;
436 shmBuf->writePos = 0;
437 shmBuf->sem = BufferSemaphoreFlags::Empty;
438 if (shm_ptr_->reader_pos == static_cast<unsigned>(buffer) && !shm_ptr_->destructive_read_mode)
440 TLOG_ARB(13,
"SharedMemoryManager") <<
"MarkBufferEmpty Broadcast mode; incrementing reader_pos" << TLOG_ENDL;
441 shm_ptr_->reader_pos = (buffer + 1) % shm_ptr_->buffer_count;
445 TLOG_ARB(13,
"SharedMemoryManager") <<
"MarkBufferEmpty END" << TLOG_ENDL;
451 TraceLock lk(buffer_mutexes_[buffer], 25,
"ResetBuffer" + std::to_string(buffer));
452 auto shmBuf = getBufferInfo_(buffer);
465 if (shmBuf->sem_id == manager_id_ && shmBuf->sem == BufferSemaphoreFlags::Writing)
469 if (!shm_ptr_->destructive_read_mode && shmBuf->sem == BufferSemaphoreFlags::Full)
471 TLOG_DEBUG(
"SharedMemoryManager") <<
"Resetting old broadcast mode buffer" << TLOG_ENDL;
472 shmBuf->writePos = 0;
473 shmBuf->sem = BufferSemaphoreFlags::Empty;
475 if (shm_ptr_->reader_pos = buffer)shm_ptr_->reader_pos = (buffer + 1) % shm_ptr_->buffer_count;
479 if (shmBuf->sem_id != manager_id_ && shmBuf->sem == BufferSemaphoreFlags::Reading)
481 TLOG_WARNING(
"SharedMemoryManager") <<
"Stale Read buffer ( " << std::to_string(
TimeUtils::gettimeofday_us() - shmBuf->last_touch_time) <<
" / " << std::to_string(shm_ptr_->buffer_timeout_us) <<
" us ) detected! Resetting..." << TLOG_ENDL;
483 shmBuf->sem = BufferSemaphoreFlags::Full;
492 TLOG_ARB(13,
"SharedMemoryManager") <<
"Write BEGIN" << TLOG_ENDL;
494 TraceLock lk(buffer_mutexes_[buffer], 26,
"WriteBuffer" + std::to_string(buffer));
495 auto shmBuf = getBufferInfo_(buffer);
496 checkBuffer_(shmBuf, BufferSemaphoreFlags::Writing);
497 touchBuffer_(shmBuf);
498 TLOG_ARB(13,
"SharedMemoryManager") <<
"Buffer Write Pos is " << std::to_string(shmBuf->writePos) <<
", write size is " << std::to_string(size) << TLOG_ENDL;
499 if (shmBuf->writePos + size > shm_ptr_->buffer_size) Detach(
true,
"SharedMemoryWrite",
"Attempted to write more data than fits into Shared Memory! \nRe-run with a larger buffer size!");
501 auto pos = GetWritePos(buffer);
502 memcpy(pos, data, size);
503 shmBuf->writePos = shmBuf->writePos + size;
504 if (shmBuf->sequence_id > last_seen_id_)
506 last_seen_id_ = shmBuf->sequence_id;
508 TLOG_ARB(13,
"SharedMemoryManager") <<
"Write END" << TLOG_ENDL;
515 TraceLock lk(buffer_mutexes_[buffer], 27,
"ReadBuffer" + std::to_string(buffer));
516 auto shmBuf = getBufferInfo_(buffer);
517 checkBuffer_(shmBuf, BufferSemaphoreFlags::Reading);
518 touchBuffer_(shmBuf);
519 if (shmBuf->readPos + size > shm_ptr_->buffer_size) Detach(
true,
"SharedMemoryRead",
"Attempted to read more data than exists in Shared Memory!");
521 auto pos = GetReadPos(buffer);
522 memcpy(data, pos, size);
523 shmBuf->readPos += size;
524 return checkBuffer_(shmBuf, BufferSemaphoreFlags::Reading,
false);
529 std::ostringstream ostr;
530 ostr <<
"ShmStruct: " << std::endl
531 <<
"Reader Position: " << shm_ptr_->reader_pos << std::endl
532 <<
"Writer Position: " << shm_ptr_->writer_pos << std::endl
533 <<
"Next ID Number: " << shm_ptr_->next_id << std::endl
534 <<
"Buffer Count: " << shm_ptr_->buffer_count << std::endl
535 <<
"Buffer Size: " << std::to_string(shm_ptr_->buffer_size) <<
" bytes" << std::endl
536 <<
"Buffers Written: " << std::to_string(shm_ptr_->next_sequence_id) << std::endl
537 <<
"Rank of Writer: " << shm_ptr_->rank << std::endl
538 <<
"Ready Magic Bytes: 0x" << std::hex << shm_ptr_->ready_magic << std::endl << std::endl;
540 for (
auto ii = 0; ii < shm_ptr_->buffer_count; ++ii)
542 auto buf = getBufferInfo_(ii);
543 ostr <<
"ShmBuffer " << std::dec << ii << std::endl
544 <<
"sequenceID: " << std::to_string(buf->sequence_id) << std::endl
545 <<
"writePos: " << std::to_string(buf->writePos) << std::endl
546 <<
"readPos: " << std::to_string(buf->readPos) << std::endl
547 <<
"sem: " << FlagToString(buf->sem) << std::endl
548 <<
"Owner: " << std::to_string(buf->sem_id.load()) << std::endl
549 <<
"Last Touch Time: " << std::to_string(buf->last_touch_time / 1000000.0) << std::endl << std::endl;
557 auto buf = getBufferInfo_(buffer);
558 return bufferStart_(buffer) + buf->readPos;
562 auto buf = getBufferInfo_(buffer);
563 return bufferStart_(buffer) + buf->writePos;
568 return bufferStart_(buffer);
571 uint8_t* artdaq::SharedMemoryManager::dataStart_()
const
573 return reinterpret_cast<uint8_t*
>(shm_ptr_ + 1) + shm_ptr_->buffer_count *
sizeof(ShmBuffer);
576 uint8_t* artdaq::SharedMemoryManager::bufferStart_(
int buffer)
578 if (buffer >= shm_ptr_->buffer_count) Detach(
true,
"ArgumentOutOfRange",
"The specified buffer does not exist!");
579 return dataStart_() + buffer * shm_ptr_->buffer_size;
582 artdaq::SharedMemoryManager::ShmBuffer* artdaq::SharedMemoryManager::getBufferInfo_(
int buffer)
584 if (buffer >= shm_ptr_->buffer_count) Detach(
true,
"ArgumentOutOfRange",
"The specified buffer does not exist!");
585 return reinterpret_cast<ShmBuffer*
>(
reinterpret_cast<uint8_t*
>(shm_ptr_ + 1) + buffer *
sizeof(ShmBuffer));
588 bool artdaq::SharedMemoryManager::checkBuffer_(ShmBuffer* buffer, BufferSemaphoreFlags flags,
bool exceptions)
592 if (buffer->sem != flags) Detach(
true,
"StateAccessViolation",
"Shared Memory buffer is not in the correct state! (expected " + FlagToString(flags) +
", actual " + FlagToString(buffer->sem) +
")");
593 if (buffer->sem_id != manager_id_) Detach(
true,
"OwnerAccessViolation",
"Shared Memory buffer is not owned by this manager instance!");
595 bool ret = (buffer->sem_id == manager_id_ || (buffer->sem_id == -1 && (flags == BufferSemaphoreFlags::Full || flags == BufferSemaphoreFlags::Empty))) && buffer->sem == flags;
599 TLOG_WARNING(
"SharedMemoryManager") <<
"CheckBuffer detected issue with buffer " << std::to_string(buffer->sequence_id) <<
"!"
600 <<
" ID: " << buffer->sem_id <<
" (" << manager_id_ <<
"), Flag: " << FlagToString(buffer->sem) <<
" (" << FlagToString(flags) <<
"). "
601 <<
"ID -1 is okay if desired flag is \"Full\" or \"Empty\"." << TLOG_ENDL;
607 void artdaq::SharedMemoryManager::touchBuffer_(ShmBuffer* buffer)
609 if (buffer->sem_id != manager_id_)
return;
610 TLOG_TRACE(
"SharedMemoryManager") <<
"touchBuffer_: Touching buffer with sequence_id " << std::to_string(buffer->sequence_id) << TLOG_ENDL;
618 auto bufs = GetBuffersOwnedByManager();
619 for (
auto buf : bufs)
621 auto shmBuf = getBufferInfo_(buf);
622 if (shmBuf->sem == BufferSemaphoreFlags::Writing)
624 shmBuf->sem = BufferSemaphoreFlags::Empty;
626 else if (shmBuf->sem == BufferSemaphoreFlags::Reading)
628 shmBuf->sem = BufferSemaphoreFlags::Full;
640 if (manager_id_ == 0 && shm_segment_id_ > -1)
642 shmctl(shm_segment_id_, IPC_RMID, NULL);
645 if (category.size() > 0 && message.size() > 0)
647 TLOG_ERROR(
"SharedMemoryManager") << category <<
": " << message << TLOG_ENDL;
651 throw cet::exception(category) << message;
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.
constexpr size_t GetElapsedTimeMilliseconds(std::chrono::steady_clock::time_point then, std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now())
Gets the number of milliseconds in the given time interval
void ResetReadPos(int buffer)
Set the read position of the given buffer to the beginning of the buffer.
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.
BufferSemaphoreFlags
The BufferSemaphoreFlags enumeration represents the different possible "states" of a given shared mem...
size_t BufferDataSize(int buffer)
Get the current size of the buffer's data.
void Attach()
Reconnect to the shared memory segment.
virtual ~SharedMemoryManager() noexcept
SharedMemoryManager Destructor.
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...
bool CheckBuffer(int buffer, BufferSemaphoreFlags flags)
Check both semaphore conditions (Mode flag and manager ID) for a given buffer.
void IncrementWritePos(int buffer, size_t written)
Increment the write position for a given buffer.
The TraceLock class allows a user to debug the acquisition and releasing of locks, by wrapping the unique_lock<std::mutex> API with TRACE calls.
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.
void ResetWritePos(int buffer)
Set the write position of the given buffer to the beginning of the buffer.
std::deque< int > GetBuffersOwnedByManager()
Get the list of all buffers currently owned by this manager instance.
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.
int GetBufferForWriting(bool overwrite)
Finds a buffer that is ready to be written to, and reserves it for the calling manager.
size_t WriteReadyCount(bool overwrite)
Count the number of buffers that are ready for writing.
uint64_t gettimeofday_us()
Get the current time of day in microseconds (from gettimeofday system call)
int GetBufferForReading()
Finds a buffer that is ready to be read, and reserves it for the calling manager. ...