I have two threads, each of which has a function that manipulates the same std:map and std:vector variables.
What is the best way to keep these variables.
Thanks
It depends on the kind of manipulations. Do you only overwrite the stored values, or do you also insert / remove elements? In the former case you could lock only a specific element of the container (e.g. by embedding a std::mutex inside each element), whereas in the latter case you need to lock the entire container during each manipulation.
There is no universal best way. You need to sanitize all read/write calls to your synchronized structure through one functions that locks/unlocks mutex accordingly. You might have multiple functions but they should all operate on the same common mutex.
Its better to have a storage class and keep the map and vector as private member variables. and write forwarding functions in that class that locks/unlocks the mutex and forwards the read/write call to actual map or vector. then you have limited number of doors to access actual structures. and it will be easier to manage.
You may use boost::mutex as member variable of that class.
Related
I havea class, used for data storage, of which there is only a single instance.
The caller is message driven and has become too large and is a prime candidate for refactoring, such that each message is handled by a separate thread. However, these could then compete to read/write the data.
If I were using mutexes (mutices?), I would only use them on write operations. I don't think that matters here, as the data are atomic, not the functions which access the data.
Is there any easy way to make all of the data atomic? Currently it consists of simple types, vectors and objects of other classes. If I have to add std::atomic<> to every sub-field, I may as well use mutexes.
std::atomic requires the type to be trivially copyable. Since you are saying std::vector is involved, that makes it impossible to use it, either on the whole structure or the std::vector itself.
The purpose of std::atomic is to be able to atomically replace the whole value of the object. You cannot do something like access individual members or so on.
From the limited context you gave in your question, I think std::mutex is the correct approach. Each object that should be independently accessible should have its own mutex protecting it.
Also note that the mutex generally needs to protect writes and reads, since a read happening unsynchronized with a write is a data race and causes undefined behavior, not only unsynchronized writes.
I have a huge class X with ~40 complex members and many read/write function calls (which can call each other) which I want to make it thread-safe. One simple approach would be to add an object lock in the implementation wherever someone is trying read/write a specific member. But that would result in adding/modifying a lot of code wherever any of the members are being accessed. Aside from refactoring so much code, it would make a simple function complex to understand for a normal reader. Also, anyone updating the class in future has to be very careful to avoid creating deadlock possibilities.
Is there any simple way to achieve this read-write synchronization?
I have a code which uses tbb::enumerable_thread_specific variables, and in the deep place of the call stack the thread local variables are used. The naive implementation leads to a lot of local() function calls.
Now I want to avoid local() function calls by passing parameters hierarchically. Is there a simpler way of doing this? I have many places with local() function calls if I do not pass Foo as a parameter, but the code would be messy if I do. I have been looking for possible usage of an array with size equal to the number of threads, and use thread-id to access the thread local variable, but it seems tbb does not provide that (in contrast to omp_get_thread_num() in OpenMP).
See more descriptions here:
https://software.intel.com/en-us/forums/intel-threading-building-blocks/topic/804043
Repeating and expanding my own answer from the TBB forum:
You can use tbb::this_task_arena::max_concurrency() and tbb::this_task_arena::current_thread_index() to implement array-based custom thread local storage. The first function gives the upper limit for the number of working threads; to a degree it's TBB equivalent for omp_get_num_threads(). The second one gives an index of the current thread within the limit, similarly to omp_get_thread_num().
Ryan. Before suggesting something else, I would suggest you try to use enumerable_thread_specific if you can. It provides one feature you may have trouble getting in general: each variable is guaranteed to line up on a cache line, which eliminates false sharing.
If you decide to manage your own thread-local storage, you must
Allocate the storage
Assign the storage to a thread, and
(potentially) free the storage.
Remember also that TBB does not guarantee a particular number of threads, though in general it will give you what you ask for. Be careful of oversubscription.
You can use any storage that does not get reallocated, so std::vector<T> is out. I'd suggest you use a concurrent_vector<T>, which doesn't get moved on expanding the array.
So you have to assign each thread a slot in the vector. That index can be stored in TLS. Then use this index to fetch the instance from your concurrent_vector. This can be an expensive operation if the vector is fragmented.
You can also use the threadID of the thread to hash into storage. If you are willing to allocate a hash map once and never resize, this will work; otherwise you have to manage a chain of hash tables and walk through the chain looking for your instance. If I remember right enumerable_thread_specific uses this technique.
You can see it is a non-trivial to implement your own version, and you'll always do better if you use a stack variable in each thread and pass that as a formal parameter. Your problem may not be structured that way, though.
Basically I'm maintaining a set of states for a bunch of objects:
#define SUBSCRIPTION_TYPE int
std::map< SUBSCRIPTION_TYPE , bool > is_object_valid;
And I need to protect each element in is_object_valid with their respective mutex_t(Rather than a big lock). As valid values of SUBSCRIPTION_TYPE are sparse (say, dozens of values ranging from 0 to 10000000 ), a std::map is prefered over std::vector, C-style array, etc.
I'm trying to achieve something like:
std::map< SUBSCRIPTION_TYPE , pthread_mutex_t > mutex_array;
But it doesn't seem to work. (Well, data race may occur when std::map is being updated).
So what's the best way to achieve this? Must I write a thread-safe subscription allocator that maps SUBSCRIPTION_TYPE into consecutive integers so that I can store the mutex_ts in an array?
If any thread is modifying the map itself (inserting, etc.), you
need to protect all accesses to the map. After that: if the
member is just a bool, how much processing can you be doing on
it that adding this time to the time the map level mutex is held
would change anything.
Otherwise: if you need a mutex per object, the simple solution
would be to put them into same object as the one on the map.
But it mutex_t copyable? pthread_mutex_t and std::mutex
aren't. This could make the insertion code overly complex,
since you can't initialize the pthread_mutex_t, or construct
the std::mutex, before the object is inserted. (In C++11, you
could use emplace to solve this problem; contents of a map
don't have to be copyable if you use emplace.) In C++03,
however, you'll have to separate allocation from initialization;
the struct which contains your mapped value and the mutex will
in fact have to be declared with raw memory for the mutex, and
then placement new used to initialize it using the iterator you
get back from insert.
If you have multiple threads reading and writing to the mutex_array, you will need another mutex to guard it.
Are you sure you will have multiple threads writing to the mutex_array?
The other thing is, instead of having two maps, you can have a map<subscription_type, object_struct>
struct object_struct {
bool valid;
pthread_mutex_t mutex;
};
And then have a single overarcing mutex to guard that map.
I have a hash map, from a string key to a pointer to a thread-safe class. Each object of this class contains a mutex which I use to synchronize between its various methods.
In addition, every once in a while I want to discard values that were not used for some time. I want to be able to safely delete the value pointer and remove it from the hash map, while making sure that no one uses my value.
What's the best way to achieve this (in general, and in C++)?
If you want people to use your hash map to get these pointers then be able to keep using them without having to notify your hash map class that they've finished with it, then storing shared pointers in the hash map is the easiest way to time actual object deletion to the time the last user of the object finishes with it. The hash map is then free to erase it's shared pointer to the object at any time.
Store and pass around shared pointers (std::shared_ptr) to your objects. Use std::shared_ptr::use_count method to check how many pointers are being used at the moment
You can also use concurrent_hash_map from TBB library. It protects concurrent accesses and lifetime of its elements using accessors (kind of a smart pointer with a lock)