1 #ifndef LOCK_GUARDED_CONTAINER_HPP_ 2 #define LOCK_GUARDED_CONTAINER_HPP_ 3 4 #include <mutex> 5 6 /* This is a bundle of a container (well, in fact, of anything) plus a 7 * lock. The copy/move work just the same as they do (or don't) in the 8 * original container, while a lock is created afresh for each new 9 * object. Moves don't move the mutexes. 10 */ 11 12 template<typename T> struct lock_guarded_container : public T { 13 private: 14 mutable std::mutex mm; 15 public: mutexlock_guarded_container16 std::mutex & mutex() const { return mm; } 17 /* forward the constructors of the embedded container. No lock needed 18 * here. */ lock_guarded_containerlock_guarded_container19 template<typename... Args> lock_guarded_container(Args&& ...args) : 20 T(std::forward<Args>(args)...) {} 21 /* add a few of our own to circumvent the lack of copy/move for the 22 * mutex. 23 * We considered having a dedicated (private) ctor taking a transient 24 * lock_guard object, so that we can avoid the cost of 25 * constructing+assigning, and construct the T base simply in the 26 * initializer list by delegating to this private ctor. Alas, this is 27 * incompatible with our perfect forwarding of the constructors of T. 28 * I don't know if a workaround is possible. 29 */ lock_guarded_containerlock_guarded_container30 lock_guarded_container(lock_guarded_container<T> const & o) 31 { 32 std::lock_guard<std::mutex> foo(o.mutex()); 33 (T&)*this = (T const&) o; 34 } lock_guarded_containerlock_guarded_container35 lock_guarded_container(lock_guarded_container<T> && o) 36 { 37 std::lock_guard<std::mutex> foo(o.mutex()); 38 std::lock_guard<std::mutex> bar(mutex()); 39 std::swap((T&)*this, (T&) o); 40 } operator =lock_guarded_container41 lock_guarded_container& operator=(lock_guarded_container<T> const & o) { 42 std::lock_guard<std::mutex> foo(o.mutex()); 43 std::lock_guard<std::mutex> bar(mutex()); 44 (T&)*this = (T const&) o; 45 return *this; 46 } operator =lock_guarded_container47 lock_guarded_container& operator=(lock_guarded_container<T> && o) { 48 std::lock_guard<std::mutex> foo(o.mutex()); 49 std::lock_guard<std::mutex> bar(mutex()); 50 std::swap((T&)*this, (T&) o); 51 return *this; 52 } 53 }; 54 55 #endif /* LOCK_GUARDED_CONTAINER_HPP_ */ 56