Question

Does anyone know where I can find an implimentation that wraps a std::map and makes it thread safe? When I say thread safe I mean that it offers only serial access to the map, one thread at a time. Optimally, this map should use only the standard-library and / or boost constructs.

Was it helpful?

Solution

Does not meet the criteria that you have specified, but you could have a look at the TBB containers. There is so called concurrent_hash_map which allows multiple threads to access concurrently the data in the map. There are some details, but everything is nicely documented and can give you an idea of the "concurrent container". Depending on your needs this might be totally inappropriate...

OTHER TIPS

It is generally not a good idea for collection classes to provide thread-safety, because they cannot know how they are being used. You will be much better served by implementing your own locking mechainisms in the higher level constructs that use the collections.

The boost shared_mutex would provide the best multiple reader/single writer approach to wrapping a standard map given your constraints. I don't know of any "pre-built" implementations that marry these two since the task is generally trivial.

This is up to the application to implement. A "thread-safe" map would make individual calls into the map thread-safe, but many operations need to be made thread-safe across calls. The application that uses the map should associate a mutex with the map, and use that mutex to coordinate accesses to it.

Trying to make thread-safe containers was a mistake in Java, and it would be a mistake in C++.

You might look at Thread Safe Template Library

Try this library

http://www.codeproject.com/KB/threads/lwsync.aspx

It is implemented in a modern c++ policy based approach.

Here is some cut from the link to show the idea with the 'vector' case

typedef lwsync::critical_resource<std::vector<int> > sync_vector_t;
sync_vector_t vec;

// some thread:
{
   // Critical resource can be naturally used with STL containers.
   sync_vector_t::const_accessor vec_access = vec.const_access();
   for(std::vector<int>::const_iterator where = vec_access->begin();
         where != vec_access->end();
         ++where;
        )
   std::cout << *where << std::endl;
}

sync_vector_t::accessor some_vector_action()
{
   sync_vector_t::accessor vec_access = vec.access();
   vec_access->push_back(10);
   return vec_access;
   // Access is escalated from within a some_vector_action() scope
   // So that one can make some other action with vector before it becomes
   // unlocked.
}

{
   sync_vector_t::accessor vec_access = some_vector_action();
   vec_access->push_back(20);
   // Elements 10 and 20 will be placed in vector sequentially.
   // Any other action with vector cannot be processed between those two
   // push_back's.
}

I came up with this (which I'm sure can be improved to take more than two arguments):

template<class T1, class T2>
class combine : public T1, public T2
{
public:

    /// We always need a virtual destructor.
    virtual ~combine() { }
};

This allows you to do:

// Combine an std::mutex and std::map<std::string, std::string> into
// a single instance.
combine<std::mutex, std::map<std::string, std::string>> lockableMap;

// Lock the map within scope to modify the map in a thread-safe way.
{
    // Lock the map.
    std::lock_guard<std::mutex> locked(lockableMap);

    // Modify the map.
    lockableMap["Person 1"] = "Jack";
    lockableMap["Person 2"] = "Jill";
}

If you wish to use an std::recursive_mutex and an std::set, that would also work.

There is a proposition here (by me - shameless plug) that wraps objects (including STL containers) for efficient (zero-cost) thread safe access:

https://github.com/isocpp/CppCoreGuidelines/issues/924

The basic idea is very simple. There are just a few wrapper classes used to enforce read/write locking and, at the same time, presenting either a const (for read-only) or non-const (for read-write) view of the wrapped object.

The idea is to make it compile-time impossible to improperly access a resource shared between threads.

Implementation code can be found here:

https://github.com/galik/GSL/blob/lockable-objects/include/gsl/gsl_lockable

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top