Reputation: 33
I am implementing boost::circular_buffer
in boost::managed_shared_memory
. I used the sample code demonstrating vector in shared memory here. I made the following changes :
1) typedef boost::circular_buffer<int, ShmemAllocatorCB> MyCircularBuffer;
2) MyCircularBuffer *circbuff = segment.construct<MyCircularBuffer>("MyCB")(alloc_inst);
3) circbuff->push_back(1);
The code is giving a compile error on line #3. The error is
error C2665: 'operator new' : none of the 5 overloads could convert all the argument types c:\boost2005\boost\circular_buffer\base.hpp 1470
From the documentation, I understand the push_back function is expecting one of these 3 forms :
void push_back(param_value_type);
void push_back(rvalue_type);
void push_back();
I tried the empty parameter call, tried casting the 1 into param_value_type, rvalue_type but none of them seem to work. This might be a simple mistake but I have not been able to figure this out for quite some time now. Any help is appreciated. Thanks.
Edit:
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocatorCB;
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
const ShmemAllocatorCB alloc_inst (segment.get_segment_manager());
Upvotes: 3
Views: 1570
Reputation: 21
The issue here is that you are not setting the capacity of the circular_buffer correctly. I would imagine the capacity is zero and hence you cannot push.
After constructing the circular_buffer set the capacity to the required size.
#define BOOST_CB_DISABLE_DEBUG
#include <boost/circular_buffer.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
using namespace boost;
using namespace boost::interprocess;
typedef allocator<T, managed_shared_memory::segment_manager> cb_alloc;
typedef circular_buffer<T, cb_alloc> cb;
managed_shared_memory* m_mem_segment;
cb* m_buffer;
// Create shared memory segment of a size able to hold the max updates.
m_mem_segment = new managed_shared_memory(open_or_create, NAMED_MEMORY, MEMORY_SIZE);
if (m_mem_segment == nullptr) {
return false;
}
// Get the segement manager for allocating a circular buffer.
const cb_alloc alloc_inst(m_mem_segment->get_segment_manager());
// Create a circular buffer in the shared memory segment.
m_buffer = m_mem_segment->find_or_construct<cb>(NAMED_BUFFER)(alloc_inst);
if (m_mem_segment == nullptr) {
return false;
}
// Set the capacity if not set (zero) (this must be set!)
if (m_buffer->capacity() <= 0) {
m_buffer->set_capacity(50);
}
You can push to this fine, I tested with multiple processes exchanging data fine. This is a simple example you obviously must implement your own synchronism between processes using named_mutex or semaphores etc.
Upvotes: 0
Reputation: 161
It looks like Boost's circular buffer uses raw pointers at some point in time for debugging. This, unfortunately, is prohibitive:
Boost provides some reference on the subject:
In summary, compile your code without circular_buffer debugging support by defining either BOOST_CB_DISABLE_DEBUG
or NDEBUG
preprocessor defines.
(tested with BOOST_LIB_VERSION
= 1_49
)
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/circular_buffer.hpp>
#include <iostream>
#include <string>
#include <cstdlib> //std::system
using namespace boost::interprocess;
//Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
//This allocator will allow placing containers in the segment
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocatorCB;
//Alias a vector that uses the previous STL-like allocator so that allocates
//its values from the segment
typedef boost::circular_buffer<int, ShmemAllocatorCB> MyCircularBuffer;
//Main function. For parent process argc == 1, for child process argc == 2
int main(int argc, char *argv[])
{
if(argc == 1){ //Parent process
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a new segment with given name and size
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
//Initialize shared memory STL-compatible allocator
const ShmemAllocatorCB alloc_inst (segment.get_segment_manager());
//Construct a buffer named "MyCB" in shared memory with argument 10 (for size) and alloc_inst
MyCircularBuffer *circbuff = segment.construct<MyCircularBuffer>("MyCB")(10, alloc_inst);
for(int i = 0; i < 100; ++i) //Insert data in the buffer, with overflows
circbuff->push_back(i);
//Launch child process
std::string s(argv[0]); s += " child ";
if(0 != std::system(s.c_str()))
return 1;
//Check child has destroyed the buffer
if(segment.find<MyCircularBuffer>("MyCB").first)
return 1;
}
else{ //Child process
//Open the managed segment
managed_shared_memory segment(open_only, "MySharedMemory");
//Find the buffer using the c-string name
MyCircularBuffer *circbuff = segment.find<MyCircularBuffer>("MyCB").first;
//Use buffer in reverse order
std::cout << "Child got: " << (*circbuff)[3] << "\n"; // 93
//When done, destroy the buffer from the segment
segment.destroy<MyCircularBuffer>("MyCB");
}
return 0;
};
To complie it:
g++ -DBOOST_CB_DISABLE_DEBUG -DNDEBUG cb_ipc.cpp -o cb_ipc -lboost_system -lrt
To run it:
./cb_ipc
Child got: 93
Upvotes: 2