#include<algorithm>
#include<iostream>
#include<iterator>
#include<mutex>
#include<thread>
#include<vector>

std::mutex mutex;
#define PRINT(VALUE) std::cout << __FUNCTION__ << "(" << std::this_thread::get_id() << "): " << VALUE << "\n"

namespace Util
{
  template<class Class,
           class Mutex = std::mutex>
  class Concurrent : private Class
  {
    public: using Class::Class;

    private: class Safe
             {
               public: Safe (Concurrent* const this_,
                             Mutex& rMutex) :
                       m_This(this_),
                       m_rMutex(rMutex)
                       { m_rMutex.lock(); }
               public: ~Safe () { m_rMutex.unlock(); }

               public: Class* operator-> () { return m_This; }
               public: const Class* operator-> () const { return m_This; }
               public: Class& operator* () { return *m_This; }
               public: const Class& operator* () const { return *m_This; }

               private: Concurrent* const m_This;
               private: Mutex& m_rMutex;
             };

    public: Safe ScopeLocked () { return Safe(this, m_Mutex); }
    public: const Class* Unsafe () const { return this; }

    public: Safe operator-> () { return ScopeLocked(); }
    public: const Class* operator-> () const { return this; }
    public: const Class& operator* () const { return *this; }

    private: Mutex m_Mutex;
  };
}

Util::Concurrent<std::vector<int>> vi{8,9};

void
Thread ()
{
  PRINT("started...");
  vi->push_back(2); 
  PRINT((*vi)[0]);
  auto viLocked = vi.ScopeLocked();
  std::copy(viLocked->begin(), viLocked->end(), std::ostream_iterator<int>(std::cout, ", "));
  std::sort(viLocked->begin(), viLocked->end());
  PRINT("copied...");
}

int main ()
{
  std::thread run(Thread);
  PRINT("started...");

  vi->push_back(1);
  {
    PRINT("looping...");
    auto viLocked = vi.ScopeLocked();
    for(auto it = viLocked->begin(); it != viLocked->end(); ++it)
      PRINT(*it);
  }

  auto viLocked = vi.ScopeLocked();
  auto it = std::begin(*viLocked);
  PRINT(*++it);

  run.join();
}