| 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 | }
|
|---|