1 | #include <cstddef>
|
---|
2 | #include <new>
|
---|
3 | #include <iostream>
|
---|
4 | #include <boost/interprocess/mapped_region.hpp>
|
---|
5 | #include <boost/interprocess/shared_memory_object.hpp>
|
---|
6 | #include <boost/interprocess/segment_manager.hpp>
|
---|
7 | #include <boost/interprocess/sync/mutex_family.hpp>
|
---|
8 | #include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
|
---|
9 | #include <boost/interprocess/offset_ptr.hpp>
|
---|
10 |
|
---|
11 | // If set to sizeof(void*) then it works
|
---|
12 | const unsigned int g_alignment = 32;
|
---|
13 |
|
---|
14 | // This is the queue descriptor. It's placed at the beginning of the shared memory segment.
|
---|
15 | struct queue_descriptor
|
---|
16 | {
|
---|
17 | typedef boost::interprocess::segment_manager_base<
|
---|
18 | boost::interprocess::rbtree_best_fit<
|
---|
19 | boost::interprocess::null_mutex_family,
|
---|
20 | boost::interprocess::offset_ptr< void >,
|
---|
21 | g_alignment
|
---|
22 | >
|
---|
23 | > segment_manager;
|
---|
24 |
|
---|
25 | // The test works if this data is removed
|
---|
26 | unsigned int data[6];
|
---|
27 |
|
---|
28 | // The segment manager manages dynamic memory right after queue_element_descriptors
|
---|
29 | segment_manager m_segment_manager;
|
---|
30 |
|
---|
31 | queue_descriptor(std::size_t shm_dynamic_offset, std::size_t shm_dynamic_size) :
|
---|
32 | m_segment_manager(shm_dynamic_size + shm_dynamic_offset, shm_dynamic_offset)
|
---|
33 | {
|
---|
34 | }
|
---|
35 | };
|
---|
36 |
|
---|
37 | // These structures describe queue elements. They are placed after the queue_descriptor in the shared memory.
|
---|
38 | struct queue_element_descriptor
|
---|
39 | {
|
---|
40 | unsigned int data[8];
|
---|
41 | };
|
---|
42 |
|
---|
43 | int main(int, char*[])
|
---|
44 | {
|
---|
45 | // Input parameters: queue geometry
|
---|
46 | const unsigned int capacity = 64, data_size = 460800;
|
---|
47 |
|
---|
48 | // This is where queue_element_descriptors start, aligned to g_alignment
|
---|
49 | const unsigned int queue_element_descriptor_offset = (sizeof(queue_descriptor) + (g_alignment - 1)) & (~(g_alignment - 1));
|
---|
50 |
|
---|
51 | // Align data size to g_alignment. Add 64 bytes as an overhead the segment manager might need for each allocation (BTW: is there a better estimate?).
|
---|
52 | const std::size_t elem_alloc_size = ((data_size + (g_alignment - 1U)) & (~(g_alignment - 1U))) + 64;
|
---|
53 |
|
---|
54 | const std::size_t shm_static_size = sizeof(queue_descriptor) + capacity * sizeof(queue_element_descriptor);
|
---|
55 | const std::size_t shm_dynamic_size = elem_alloc_size * capacity;
|
---|
56 | const std::size_t shm_dynamic_offset = queue_element_descriptor_offset + capacity * sizeof(queue_element_descriptor);
|
---|
57 | const std::size_t shm_size = shm_static_size + shm_dynamic_size;
|
---|
58 |
|
---|
59 | std::cout << "elem_alloc_size = " << elem_alloc_size << ", shm_static_size = " << shm_static_size << ", shm_dynamic_size = " << shm_dynamic_size << ", shm_dynamic_offset = " << shm_dynamic_offset << std::endl;
|
---|
60 |
|
---|
61 | // Create shared memory
|
---|
62 | boost::interprocess::shared_memory_object storage_shared_mem = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create, "/segment_manager_test", boost::interprocess::read_write);
|
---|
63 | storage_shared_mem.truncate(shm_size);
|
---|
64 |
|
---|
65 | // Map memory into our address space
|
---|
66 | boost::interprocess::mapped_region storage_region = boost::interprocess::mapped_region(storage_shared_mem, boost::interprocess::read_write);
|
---|
67 |
|
---|
68 | // This is where it fails
|
---|
69 | new (storage_region.get_address()) queue_descriptor(shm_dynamic_offset, shm_dynamic_size);
|
---|
70 |
|
---|
71 | static_cast< queue_descriptor* >(storage_region.get_address())->~queue_descriptor();
|
---|
72 | boost::interprocess::shared_memory_object::remove("/segment_manager_test");
|
---|
73 |
|
---|
74 | std::cout << "success" << std::endl;
|
---|
75 |
|
---|
76 | return 0;
|
---|
77 | }
|
---|