Reputation: 309
I wrote a dll
with Visual c++ in Visual Studio 2008
which is used by several processes and threads.
The scenario is something like that:
One writer process calls the "init" method of the dll, this method creates a shared memory and creates a boost multi_index
container in the shared memory and starts to push data by calling its insert method.
After container has created, up to 10 reader applications start to perform search operations in it by calling the search method.
And after some time (let's say 30 seconds) writer process creates a delete thread which starts to delete data (the oldest) in the container with a frequency like 1 delete operation/sec.
The header file (hpp) of the code looks like:
class SharedMemoryContainer
{
private:
typedef boost::interprocess::allocator<SharedObj, managed_shared_memory::segment_manager> ShmemAllocator;
typedef multi_index_container<
SharedObj,
indexed_by<
random_access<>,
ordered_non_unique< member<SharedObj, unsigned _int64, &SharedObj::id >
>, ShmemAllocator
> SharedMemoryContainerType;
struct compare
{
unsigned _int64 _compare;
int _trackNo;
compare(unsigned _int64 id, int trackNo) : _compare(id), _trackNo(trackNo) {}
bool operator()(SharedObj const& item) const {return (item.id == _compare && item.trackNo == _trackNo);};
};
static boost::mutex mutex_; // the mutex that i used to synchronize the operations
/*
.
.
some more variables and methods...
.
.
*/
public:
bool insert (/*.. parameters ..*/);
SharedObj search (/*.. parameters ..*/);
bool delete ();
/*
.
.
some more variables and methods...
.
.
*/
};
And in the implementation (cpp) file I use mutex like this:
boost::mutex SharedMemoryContainer::mutex_; // for the static mutex
// insert new data to shared container
bool SharedMemoryContainer::insert(/*.. parameters ..*/)
{
boost::mutex::scoped_lock m(mutex_);
bool result;
try
{
// Make the insertion here
}
catch(interprocess_exception &ex)
{
std::cout << "Error in Insert!" << std::endl <<ex.what() << std::endl;
return false;
}
return result;
}
// reader applications perform search in shared container
SharedObj SharedMemoryContainer::search(/*.. parameters ..*/)
{
boost::mutex::scoped_lock m(mutex_);
IndexType& idIndex = myContainer->get<0>();
IteratorType current = std::find_if(idIndex.begin(), idIndex.end(), compare(id, trackNo));
/*
.
.
other operations
.
.
*/
}
// it always delete the oldest one
bool SharedMemoryContainer::delete()
{
boost::mutex::scoped_lock m(mutex_);
IndexType& idIndex = myContainer->get<0>();
it first = myContainer->begin();
idIndex.erase(first);
}
This kind of mutex usage doestn't seems to work. Because it always crashes in a different time (I mean it changes, it can be after 40 sec or 5 minutes etc...)
It crashes in the compare struct
(which is called in search - find_if) with "access violation unable to read location ..."
because of the delete thread changes the container I guess(it works fine without delete thread)
What can I do to keep my shared multi_index container thread/process safe and synchronized?
Thanks...
EDIT:
I have also one more question regarding the work logic of mutexes.
As far as I read mutexes just locks the code to prevent multiple entry to a code block not the container itself. So for example, in the code above when a reader app enters to "search" method and locks the container no other reader app can enter the code, but the delete thread can also make its task by entering "delete" method and change the container?
So how to prevent multiple operations on one shared container at one time?
Upvotes: 3
Views: 1894
Reputation: 18864
As you already have boost as a dependency the best course of action would be to just start using mutex from the interprocess library. Manual and examples (here).
Make sure to always use timed locking, as otherwise if reader or writer crashes while holding it your whole system deadlocks.
Upvotes: 3
Reputation: 409186
If you read this link the very first paragraph states:
Variables that are declared as global in a DLL source code file are treated as global variables by the compiler and linker, but each process that loads a given DLL gets its own copy of that DLL's global variables. The scope of static variables is limited to the block in which the static variables are declared. As a result, each process has its own instance of the DLL global and static variables by default.
That means that each process that uses your DLL will have it's own separate and unshared copy of the mutex. So even if two processes share the container the mutex will be separate and not shared causing data races.
Upvotes: 4