I have the following UtlSharedIPCWrapper
template class that I created access a user defined type that is placed in inter-process memory.
Normally this class is used with a simple type for example:
// construct a FaultReport - default to no faults
auto faultWrapper = managed_shm.construct<
UtlSharedIPCWrapper<uint64_t>>("FaultReport")(0);
and this works well, however I recently had the need to use a boost shared memory map collection (boost::interprocess::map
) as a template argument) as in:
using char_allocator = boost::interprocess::managed_shared_memory::allocator<char>::type;
using shm_string = boost::interprocess::basic_string<char, std::char_traits<char>, char_allocator>;
using KeyType = shm_string;
using ValueType = std::pair<const KeyType, shm_string>;
using ShmemAllocator = boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager>;
using SharedMemoryMap = boost::interprocess::map<shm_string, shm_string, std::less<KeyType>, ShmemAllocator>;
...
// create a new shared memory segment 2K size
managed_shared_memory managed_shm(open_only, "sharedmemname");
//Initialize the shared memory STL-compatible allocator
ShmemAllocator alloc(managed_shm.get_segment_manager());
auto pSharedNVPairs = managed_shm.find<UtlSharedIPCWrapper<
SharedMemoryMap>>("NameValuePairs").first;
my question is how can I change the template class definition below to pass collection::value types's as parameters instead of separately reading the entire map as one operation via pSharedNVPairs->getSharedData()
updating the temporary map and writing it back to shared memory again via pSharedNVPairs->setSharedData(*pSharedNVPairs)
. I know that this will be different for types that are not collections and thefore some template metaprogramming magic will have to be performed that does selective enable if etc,., but I would like to have a method added to my class something along the lines of
// I don't know the correct signature here
void setSharedDataValue(const T::value_type& rSharedDataValue) {
boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mMutex);
... not sure what to do here to update the collection
}
template<typename T>
struct UtlSharedIPCWrapper {
private:
using upgradable_mutex_type = boost::interprocess::interprocess_upgradable_mutex;
mutable upgradable_mutex_type mMutex;
/*volatile*/ T mSharedData;
public:
// explicit constructor used to initialize directly from existing memory
explicit UtlSharedIPCWrapper(const T& rInitialValue)
: mSharedData(rInitialValue)
{}
T getSharedData() const {
boost::interprocess::sharable_lock<upgradable_mutex_type> lock(mMutex);
return mSharedData;
}
void setSharedData(const T& rSharedData) {
boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mMutex);
// update the shared data copy mapped - scoped locked used if exception thrown
// a bit like the lock guard we normally use
this->mSharedData = rSharedData;
}
};
Why not just
// I don't know the correct signature here
void setSharedDataValue(const typename T::value_type& rSharedDataValue) {
boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mMutex);
mSharedData.insert(rSharedDataValue);
}