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