Ensure only a single instance of static template class member I am interacting with a C library, whose documentation states that certain functions are not thread safe. Since its functions deal heterogeneously with multiple types, I have written a template wrapper to use it in a homogeneous manner from C++. However, I now need to ensure serialized access to certain functions, serialized across all instantiated template wrappers.

I believe the following approach should work; what I would like to know is, are there any caveats to the following approach, and if so, what are they and how can I get around them?

struct LibMutexPolicy
{
    static std::mutex &amp; getMutexInstance()
    {
        static std::mutex inst;
        return inst;
    }
};

template &lt;typename T&gt;
struct A : private LibMutexPolicy
{
    void foo()
    {
        std::lock_guard&lt;std::mutex&gt; lock(getMutexInstance());
        // Call non thread-safe library code
    }
};
I believe the following approach should work; what I would like to know is, are there any caveats to the following approach, and if so, what are they and how can I get around them?


Consider a decorator implementation, with a visitor function for method access:

template&lt;typename V&gt;
class threadsafe_reference // decorator
{
public:
    using reference_type = V&amp;;
    threadsafe_reference(reference_type v, std::mutex&amp; m): value_(v), mutex_(m) {}

    // synchronized visitor access
    void sync( std::function&lt;void(value_type&amp;)&gt; functor )
    {
        std::lock_guard&lt;std::mutex&gt; lock{ mutex_ };
        functor( value_ );
    }

    // you may wish to provide unsynchronized reference access here
private:
    reference_type value_;
    std::mutex&amp; mutex_; 
};

template&lt;typename V&gt;
threadsafe_reference&lt;V&gt; make_threadsafe(V&amp; value, std::mutex&amp; m)
{
    return threadsafe_reference&lt;V&gt;{ value, m };
} 


Client code:

struct A // agnostic to threading
{
    void do_stuff_n_things( int i ) {};
};

A a; // need to pass this on two threads
mutex m;

auto tsa = make_threadsafe(a, m); // proxy accessor


Thread access:

 tsa.sync( []( A&amp; self ) { self.do_things_n_stuff(10); } );


The code is incomplete (you'd need a specialization of sync for const access and so on) but it should be enough to give you a picture.

Advantages:


this is a non-intrusive decorator that you can use over virtually any type
separates concerns nicely and allows you to implement and test them separately (e.g. test A, then test the synchronization code)


Minor disadvantage:


the access to A's methods requires lambdas/external functions