This is a simple piece of code that I wrote about a year ago, in response to a question on Daniweb. I decided to infuse it with some C++11 magic, which led to a pretty sweet code snippet, full of neat little techniques you might want to use, not to mention that this class can actually be pretty handy to have. There are a few similar implementations out-there, but they all use a different approach, my main inspiration is the scope-guard technique.
This is an implementation of a simple wrapper class template that allows a variable to be externally made thread-safe via a mutex lock. This can be useful when a single variable (e.g. non-trivial object, like a std::string or std::vector) is of a class that has no built-in thread-safety, when thread-safety is required. The typical solution is to pair the object with an associated mutex and lock it during any thread-sensitive operations. For example, if the object is a std::vector, one could wrap all calls that rely on the underlying elements (like accessing them or insertions) with a mutex lock. Although this is typically the best solution in terms of fine-grained control over when threads can get blocked, it can be cumbersome to implement in general (at worst, creating a "completely thread-safe std::vector" would involve wrapping every member function in a mutex lock).
This simple wrapper superposes a scoped locking mechanism on top of an underlying object. This forces all the operations on the object to be mutex-locked, within a scope, such that any operations done within that scope are thread-safe. Obviously, this provides a very coarse-grained thread-safety and may not be the best solution, performance-wise, in most applications. However, it is quick and simple, and reduces clutter in classes that would otherwise have many pairs like var1 and var1_mutex, var2 and var2_mutex, etc.
This wrapper template works as follows. First, it privately wraps the actual object along with a mutex for it. Then, the object can only be indirectly accessed via the creation of a const or non-const locked-pointer to the object. The locked-pointer is non-copyable, non-assignable, immovable, and always const. This prohibits most unintentional misuses on the user-side (but not dirty hacks, of course!). The locked-pointer can be used as an ordinary pointer to refer to the object. Because references to the variable can be given by the lock, there are ways in which a reference could be carried out of the scope of the lock, and thus, enabling access to it in a thread-unsafe manner. However, such a trick would appear obvious (violating common practice in C++) and could hardly go unoticed or be unintentional. Finally, the wrapper relies on the binding of a temporary to a const reference to restrict the scope of the lock without allowing copy-constructor or assignment to anything outside the scope of original lock (this is basic scope-guard technique).
N.B. for Compilation: The code requires pretty good C++11 support. It compiles and runs without errors on GCC 4.7.0 (required for the template aliases only), it also compiles with GCC 4.6.2 when replacing the template alias with its C++03 equivalent. Of course, it requires the compilation flag
-std=c++11. As for MSVC++, don't even try.
Edited 4 Years Ago by mike_2000_17: tab-space formatting