artdaq_core  v3_01_05
SharedMemoryManager_t.cc
1 #include "artdaq-core/Core/SharedMemoryManager.hh"
2 #include "artdaq-core/Utilities/TimeUtils.hh"
3 #include "artdaq-core/Utilities/configureMessageFacility.hh"
4 
5 #define BOOST_TEST_MODULE SharedMemoryManager_t
6 #include "cetlib/quiet_unit_test.hpp"
7 #include "cetlib_except/exception.h"
8 
9 #include "tracemf.h"
10 
11 BOOST_AUTO_TEST_SUITE(SharedMemoryManager_test)
12 
13 BOOST_AUTO_TEST_CASE(Construct)
14 {
15  artdaq::configureMessageFacility("SharedMemoryManager_t", true, true);
16  TLOG_DEBUG("SharedMemoryManager_t") << "BEGIN TEST Construct" << TLOG_ENDL;
18  uint32_t key = 0x7357 + rand() % 0x10000000;
19  artdaq::SharedMemoryManager man(key, 10, 0x1000,0x10000);
20  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
21  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
22  BOOST_REQUIRE_EQUAL(man.size(), 10);
23  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 0);
24  BOOST_REQUIRE_EQUAL(man.GetKey(), key);
25  TLOG_DEBUG("SharedMemoryManager_t") << "END TEST Construct" << TLOG_ENDL;
26 }
27 
28 BOOST_AUTO_TEST_CASE(Attach)
29 {
30  TLOG_DEBUG("SharedMemoryManager_t") << "BEGIN TEST Attach" << TLOG_ENDL;
32  uint32_t key = 0x7357 + rand() % 0x10000000;
33  artdaq::SharedMemoryManager man(key, 10, 0x1000, 0x10000);
34  artdaq::SharedMemoryManager man2(key, 10, 0x1000, 0x10000);
35 
36  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
37  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
38  BOOST_REQUIRE_EQUAL(man.size(), 10);
39  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 1);
40  BOOST_REQUIRE_EQUAL(man.GetKey(), key);
41 
42  BOOST_REQUIRE_EQUAL(man2.IsValid(), true);
43  BOOST_REQUIRE_EQUAL(man2.GetMyId(), 1);
44  BOOST_REQUIRE_EQUAL(man2.size(), 10);
45  BOOST_REQUIRE_EQUAL(man2.GetAttachedCount(), 1);
46  BOOST_REQUIRE_EQUAL(man2.GetKey(), key);
47 
48  TLOG_DEBUG("SharedMemoryManager_t") << "END TEST Attach" << TLOG_ENDL;
49 }
50 
51 BOOST_AUTO_TEST_CASE(DataFlow)
52 {
53  TLOG_DEBUG("SharedMemoryManager_t") << "BEGIN TEST DataFlow" << TLOG_ENDL;
55  uint32_t key = 0x7357 + rand() % 0x10000000;
56  artdaq::SharedMemoryManager man(key, 10, 0x1000);
57  artdaq::SharedMemoryManager man2(key, 10, 0x1000);
58 
59  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
60  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
61  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
62  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
63 
64  int buf = man.GetBufferForWriting(false);
65  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
66  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
67  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
68  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(),0);
69  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
70 
71  uint8_t n = 0;
72  uint8_t data[0x1000];
73  std::generate_n(data, 0x1000, [&]() {return ++n; });
74  man.Write(buf, data, 0x1000);
75  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
76  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(buf), 0x1000);
77  man.MarkBufferFull(buf, 1);
78  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Full), true);
79  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
80  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
81 
82  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
83  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
84  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
85 
86  auto readbuf = man2.GetBufferForReading();
87  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
88  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
89  uint8_t byte;
90  auto sts = man2.Read(readbuf, &byte, 1);
91  BOOST_REQUIRE_EQUAL(sts, true);
92  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
93  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
94  sts = man2.Read(readbuf, &byte, 1);
95  BOOST_REQUIRE_EQUAL(sts, true);
96  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
97  man2.IncrementReadPos(readbuf, 0x10);
98  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
99  sts = man2.Read(readbuf, &byte, 1);
100  BOOST_REQUIRE_EQUAL(sts, true);
101  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
102  man2.ResetReadPos(readbuf);
103  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
104  sts = man2.Read(readbuf, &byte, 1);
105  BOOST_REQUIRE_EQUAL(sts, true);
106  BOOST_REQUIRE_EQUAL(byte, 1);
107  man2.IncrementReadPos(readbuf, 0xFFF);
108  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), false);
109  man2.MarkBufferEmpty(readbuf);
110 
111  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
112  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
113  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
114  TLOG_DEBUG("SharedMemoryManager_t") << "END TEST DataFlow" << TLOG_ENDL;
115 }
116 
117 BOOST_AUTO_TEST_CASE(Exceptions)
118 {
119  artdaq::configureMessageFacility("SharedMemoryManager_t", true, true);
120  TLOG_DEBUG("SharedMemoryManager_t") << "BEGIN TEST Exceptions" << TLOG_ENDL;
122  uint32_t key = 0x7357 + rand() % 0x10000000;
123  artdaq::SharedMemoryManager man(key, 10, 0x1000);
124  artdaq::SharedMemoryManager man2(key, 10, 0x1000);
125  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
126  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
127  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
128  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
129 
130  // Trying to get an invalid buffer is an exception
131  BOOST_REQUIRE_EXCEPTION(man.ResetReadPos(11), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
132  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
133 
134  man.Attach();
135  // Trying to access a buffer that is in the wrong state is an exception
136  BOOST_REQUIRE_EXCEPTION(man.MarkBufferEmpty(0),cet::exception, [&](cet::exception e) { return e.category() == "StateAccessViolation"; });
137  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
138 
139  man.Attach();
140 
141  // Writing too much data is an exception
142  int buf = man.GetBufferForWriting(false);
143  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
144  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
145  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
146  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
147 
148  uint8_t n = 0;
149  uint8_t data[0x2000];
150  std::generate_n(data, 0x2000, [&]() {return ++n; });
151  BOOST_REQUIRE_EXCEPTION(man.Write(buf, data, 0x2000), cet::exception, [&](cet::exception e) { return e.category() == "SharedMemoryWrite"; });
152  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
153 
154  man.Attach();
155  man2.Attach();
156  buf = man.GetBufferForWriting(false);
157  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
158  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
159  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
160  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
161  man.Write(buf, data, 0x1000);
162  man.MarkBufferFull(buf);
163 
164  // Reading too much data is an exception
165  BOOST_REQUIRE_EQUAL(man2.IsValid(), true);
166  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
167  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
168 
169  int readbuf = man2.GetBufferForReading();
170  BOOST_REQUIRE_EQUAL(readbuf, buf);
171  BOOST_REQUIRE_EXCEPTION(man2.Read(readbuf, data, 0x1001), cet::exception, [&](cet::exception e) { return e.category() == "SharedMemoryRead"; });
172  BOOST_REQUIRE_EQUAL(man2.IsValid(), false);
173 
174  man.Attach();
175  man2.Attach();
176 
177  man.MarkBufferEmpty(readbuf, true);
178  buf = man.GetBufferForWriting(false);
179  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
180  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
181  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
182  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
183  man.Write(buf, data, 0x1000);
184  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
185  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
186  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
187  man.MarkBufferFull(buf);
188  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
189  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
190 
191  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
192  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
193  readbuf = man2.GetBufferForReading();
194  BOOST_REQUIRE_EQUAL(readbuf, buf);
195  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
196  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager()[0], readbuf);
197  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(readbuf), 0x1000);
198  // Accessing a buffer that is not owned by the manager is an exception
199  BOOST_REQUIRE_EXCEPTION(man.MarkBufferEmpty(readbuf), cet::exception, [&](cet::exception e) { return e.category() == "OwnerAccessViolation"; });
200  BOOST_REQUIRE_EQUAL(man.IsValid(), false);
201 
202  TLOG_DEBUG("SharedMemoryManager_t") << "END TEST Exceptions" << TLOG_ENDL;
203 }
204 
205 BOOST_AUTO_TEST_CASE(Broadcast)
206 {
207  TLOG_DEBUG("SharedMemoryManager_t") << "BEGIN TEST Broadcast" << TLOG_ENDL;
209  uint32_t key = 0x7357 + rand() % 0x10000000;
210  artdaq::SharedMemoryManager man(key, 10, 0x1000, 0x10000, false);
211  artdaq::SharedMemoryManager man2(key, 10, 0x1000, 0x10000, false);
212  artdaq::SharedMemoryManager man3(key, 10, 0x1000, 0x10000, false);
213 
214  BOOST_REQUIRE_EQUAL(man.ReadyForWrite(false), true);
215  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
216  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
217  BOOST_REQUIRE_EQUAL(man.ReadReadyCount(), 0);
218 
219  int buf = man.GetBufferForWriting(false);
220  BOOST_REQUIRE_EQUAL(man.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Writing), true);
221  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 1);
222  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager()[0], buf);
223  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
224  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0);
225 
226  uint8_t n = 0;
227  uint8_t data[0x1000];
228  std::generate_n(data, 0x1000, [&]() {return ++n; });
229  man.Write(buf, data, 0x1000);
230  BOOST_REQUIRE_EQUAL(man.BufferDataSize(buf), 0x1000);
231  BOOST_REQUIRE_EQUAL(man2.BufferDataSize(buf), 0x1000);
232  man.MarkBufferFull(buf, -1);
233  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Full), true);
234  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
235 
236  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
237  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), true);
238  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 1);
239 
240  auto readbuf = man2.GetBufferForReading();
241  BOOST_REQUIRE_EQUAL(readbuf, buf);
242  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 1);
243  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
244  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), false);
245  BOOST_REQUIRE_EQUAL(man2.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
246  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
247  uint8_t byte;
248  auto sts = man2.Read(readbuf, &byte, 1);
249  BOOST_REQUIRE_EQUAL(sts, true);
250  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
251  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
252  sts = man2.Read(readbuf, &byte, 1);
253  BOOST_REQUIRE_EQUAL(sts, true);
254  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
255  man2.IncrementReadPos(readbuf, 0x10);
256  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
257  sts = man2.Read(readbuf, &byte, 1);
258  BOOST_REQUIRE_EQUAL(sts, true);
259  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
260  man2.ResetReadPos(readbuf);
261  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), true);
262  sts = man2.Read(readbuf, &byte, 1);
263  BOOST_REQUIRE_EQUAL(sts, true);
264  BOOST_REQUIRE_EQUAL(byte, 1);
265  man2.IncrementReadPos(readbuf, 0xFFF);
266  BOOST_REQUIRE_EQUAL(man2.MoreDataInBuffer(readbuf), false);
267  man2.MarkBufferEmpty(readbuf);
268  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), true);
269  BOOST_REQUIRE_EQUAL(man3.ReadReadyCount(), 1);
270  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), false);
271  BOOST_REQUIRE_EQUAL(man2.ReadReadyCount(), 0);
272  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
273 
274 
275  readbuf = man3.GetBufferForReading();
276  BOOST_REQUIRE_EQUAL(readbuf, buf);
277  BOOST_REQUIRE_EQUAL(man3.GetBuffersOwnedByManager().size(), 1);
278  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
279  BOOST_REQUIRE_EQUAL(man3.CheckBuffer(buf, artdaq::SharedMemoryManager::BufferSemaphoreFlags::Reading), true);
280  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
281  sts = man3.Read(readbuf, &byte, 1);
282  BOOST_REQUIRE_EQUAL(sts, true);
283  BOOST_REQUIRE_EQUAL(byte, 1); // ++n means that the first entry will be 1
284  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
285  sts = man3.Read(readbuf, &byte, 1);
286  BOOST_REQUIRE_EQUAL(sts, true);
287  BOOST_REQUIRE_EQUAL(byte, 2); // Second entry is 2
288  man3.IncrementReadPos(readbuf, 0x10);
289  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
290  sts = man3.Read(readbuf, &byte, 1);
291  BOOST_REQUIRE_EQUAL(sts, true);
292  BOOST_REQUIRE_EQUAL(byte, 0x13); // Read increments, so it would have read 3, but we added 0x10, so we expect 0x13.
293  man3.ResetReadPos(readbuf);
294  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), true);
295  sts = man3.Read(readbuf, &byte, 1);
296  BOOST_REQUIRE_EQUAL(sts, true);
297  BOOST_REQUIRE_EQUAL(byte, 1);
298  man3.IncrementReadPos(readbuf, 0xFFF);
299  BOOST_REQUIRE_EQUAL(man3.MoreDataInBuffer(readbuf), false);
300  man3.MarkBufferEmpty(readbuf);
301  BOOST_REQUIRE_EQUAL(man3.ReadyForRead(), false);
302  BOOST_REQUIRE_EQUAL(man2.ReadyForRead(), false);
303  BOOST_REQUIRE_EQUAL(man.ReadyForRead(), false);
304 
305  BOOST_REQUIRE_EQUAL(man2.GetBuffersOwnedByManager().size(), 0);
306  BOOST_REQUIRE_EQUAL(man.GetBuffersOwnedByManager().size(), 0);
307  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 9);
308  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(true), 10);
309  sleep(1);
310  BOOST_REQUIRE_EQUAL(man.WriteReadyCount(false), 10);
311  TLOG_DEBUG("SharedMemoryManager_t") << "END TEST Broadcast" << TLOG_ENDL;
312 }
313 
314 BOOST_AUTO_TEST_SUITE_END()
The buffer is full, and waiting for a reader.
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...
void configureMessageFacility(char const *progname, bool useConsole=true, bool printDebug=false)
Configure and start the message facility. Provide the program name so that messages will be appropria...
uint64_t gettimeofday_us()
Get the current time of day in microseconds (from gettimeofday system call)
Definition: TimeUtils.cc:51