/*
 * Test program that illustrates how to annotate a smart pointer
 * implementation.  In a multithreaded program the following is relevant when
 * working with smart pointers:
 * - whether or not the objects pointed at are shared over threads.
 * - whether or not the methods of the objects pointed at are thread-safe.
 * - whether or not the smart pointer objects are shared over threads.
 * - whether or not the smart pointer object itself is thread-safe.
 *
 * Most smart pointer implemenations are not thread-safe
 * (e.g. boost::shared_ptr<>, tr1::shared_ptr<> and the smart_ptr<>
 * implementation below). This means that it is not safe to modify a shared
 * pointer object that is shared over threads without proper synchronization.
 *
 * Even for non-thread-safe smart pointers it is possible to have different
 * threads access the same object via smart pointers without triggering data
 * races on the smart pointer objects.
 *
 * A smart pointer implementation guarantees that the destructor of the object
 * pointed at is invoked after the last smart pointer that points to that
 * object has been destroyed or reset. Data race detection tools cannot detect
 * this ordering without explicit annotation for smart pointers that track
 * references without invoking synchronization operations recognized by data
 * race detection tools.
 */


#include <cassert>     // assert()
#include <climits>     // PTHREAD_STACK_MIN
#include <iostream>    // std::cerr
#include <stdlib.h>    // atoi()
#include <vector>
#ifdef _WIN32
#include <process.h>   // _beginthreadex()
#include <windows.h>   // CRITICAL_SECTION
#else
#include <pthread.h>   // pthread_mutex_t
#endif
#include "unified_annotations.h"


static bool s_enable_annotations;


#ifdef _WIN32

class AtomicInt32
{
public:
  AtomicInt32(const int value = 0) : m_value(value) { }
  ~AtomicInt32() { }
  LONG operator++() { return InterlockedIncrement(&m_value); }
  LONG operator--() { return InterlockedDecrement(&m_value); }

private:
  volatile LONG m_value;
};

class Mutex
{
public:
  Mutex() : m_mutex()
  { InitializeCriticalSection(&m_mutex); }
  ~Mutex()
  { DeleteCriticalSection(&m_mutex); }
  void Lock()
  { EnterCriticalSection(&m_mutex); }
  void Unlock()
  { LeaveCriticalSection(&m_mutex); }

private:
  CRITICAL_SECTION m_mutex;
};

class Thread
{
public:
  Thread() : m_thread(INVALID_HANDLE_VALUE) { }
  ~Thread() { }
  void Create(void* (*pf)(void*), void* arg)
  {
    WrapperArgs* wrapper_arg_p = new WrapperArgs(pf, arg);
    m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, wrapper,
						       wrapper_arg_p, 0, NULL));
  }
  void Join()
  { WaitForSingleObject(m_thread, INFINITE); }

private:
  struct WrapperArgs
  {
    WrapperArgs(void* (*pf)(void*), void* arg) : m_pf(pf), m_arg(arg) { }

    void* (*m_pf)(void*);
    void* m_arg;
  };
  static unsigned int __stdcall wrapper(void* arg)
  {
    WrapperArgs* wrapper_arg_p = reinterpret_cast<WrapperArgs*>(arg);
    WrapperArgs wa = *wrapper_arg_p;
    delete wrapper_arg_p;
    return reinterpret_cast<unsigned>((wa.m_pf)(wa.m_arg));
  }
  HANDLE m_thread;
};

#else // _WIN32

class AtomicInt32
{
public:
  AtomicInt32(const int value = 0) : m_value(value) { }
  ~AtomicInt32() { }
  int operator++() { return __sync_add_and_fetch(&m_value, 1); }
  int operator--() { return __sync_sub_and_fetch(&m_value, 1); }
private:
  volatile int m_value;
};

class Mutex
{
public:
  Mutex() : m_mutex()
  { pthread_mutex_init(&m_mutex, NULL); }
  ~Mutex()
  { pthread_mutex_destroy(&m_mutex); }
  void Lock()
  { pthread_mutex_lock(&m_mutex); }
  void Unlock()
  { pthread_mutex_unlock(&m_mutex); }

private:
  pthread_mutex_t m_mutex;
};

class Thread
{
public:
  Thread() : m_tid() { }
  ~Thread() { }
  void Create(void* (*pf)(void*), void* arg)
  {
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
    pthread_create(&m_tid, &attr, pf, arg);
    pthread_attr_destroy(&attr);
  }
  void Join()
  { pthread_join(m_tid, NULL); }
private:
  pthread_t m_tid;
};

#endif // !defined(_WIN32)


template<class T>
class smart_ptr
{
public:
  typedef AtomicInt32 counter_t;

  template <typename Q> friend class smart_ptr;

  explicit smart_ptr()
    : m_ptr(NULL), m_count_ptr(NULL)
  { }

  explicit smart_ptr(T* const pT)
    : m_ptr(NULL), m_count_ptr(NULL)
  {
    set(pT, pT ? new counter_t(0) : NULL);
  }

  template <typename Q>
  explicit smart_ptr(Q* const q)
    : m_ptr(NULL), m_count_ptr(NULL)
  {
    set(q, q ? new counter_t(0) : NULL);
  }

  ~smart_ptr()
  {
    set(NULL, NULL);
  }

  smart_ptr(const smart_ptr<T>& sp)
    : m_ptr(NULL), m_count_ptr(NULL)
  {
    set(sp.m_ptr, sp.m_count_ptr);
  }

  template <typename Q>
  smart_ptr(const smart_ptr<Q>& sp)
    : m_ptr(NULL), m_count_ptr(NULL)
  {
    set(sp.m_ptr, sp.m_count_ptr);
  }

  smart_ptr& operator=(const smart_ptr<T>& sp)
  {
    set(sp.m_ptr, sp.m_count_ptr);
    return *this;
  }

  smart_ptr& operator=(T* const p)
  {
    set(p, p ? new counter_t(0) : NULL);
    return *this;
  }

  template <typename Q>
  smart_ptr& operator=(Q* const q)
  {
    set(q, q ? new counter_t(0) : NULL);
    return *this;
  }

  T* operator->() const
  {
    assert(m_ptr);
    return m_ptr;
  }

  T& operator*() const
  {
    assert(m_ptr);
    return *m_ptr;
  }

private:
  void set(T* const pT, counter_t* const count_ptr)
  {
    if (m_ptr != pT)
    {
      if (m_count_ptr)
      {
	if (s_enable_annotations)
	  U_ANNOTATE_HAPPENS_BEFORE(m_count_ptr);
	if (--(*m_count_ptr) == 0)
	{
	  if (s_enable_annotations)
	    U_ANNOTATE_HAPPENS_AFTER(m_count_ptr);
	  delete m_ptr;
	  m_ptr = NULL;
	  delete m_count_ptr;
	  m_count_ptr = NULL;
	}
      }
      m_ptr = pT;
      m_count_ptr = count_ptr;
      if (count_ptr)
	++(*m_count_ptr);
    }
  }

  T*         m_ptr;
  counter_t* m_count_ptr;
};

class counter
{
public:
  counter()
    : m_mutex(), m_count()
  { }
  ~counter()
  {
    // Data race detection tools that do not recognize the
    // ANNOTATE_HAPPENS_BEFORE() / ANNOTATE_HAPPENS_AFTER() annotations in the
    // smart_ptr<> implementation will report that the assignment below
    // triggers a data race.
    m_count = -1;
  }
  int get() const
  {
    int result;
    m_mutex.Lock();
    result = m_count;
    m_mutex.Unlock();
    return result;
  }
  int post_increment()
  {
    int result;
    m_mutex.Lock();
    result = m_count++;
    m_mutex.Unlock();
    return result;
  }

private:
  mutable Mutex m_mutex;
  int           m_count;
};

static void* thread_func(void* arg)
{
  smart_ptr<counter>* pp = reinterpret_cast<smart_ptr<counter>*>(arg);
  (*pp)->post_increment();
  *pp = NULL;
  delete pp;
  return NULL;
}

int main(int argc, char** argv)
{
  const int nthreads = std::max(argc > 1 ? atoi(argv[1]) : 1, 1);
  const int iterations = std::max(argc > 2 ? atoi(argv[2]) : 1, 1);
  s_enable_annotations = argc > 3 ? !!atoi(argv[3]) : true;

  for (int j = 0; j < iterations; ++j)
  {
    std::vector<Thread> T(nthreads);
    smart_ptr<counter> p(new counter);
    p->post_increment();
    for (std::vector<Thread>::iterator q = T.begin(); q != T.end(); q++)
      q->Create(thread_func, new smart_ptr<counter>(p));
    {
      // Avoid that counter.m_mutex introduces a false ordering on the
      // counter.m_count accesses.
      const timespec delay = { 0, 100 * 1000 * 1000 };
      nanosleep(&delay, 0);
    }
    p = NULL;
    for (std::vector<Thread>::iterator q = T.begin(); q != T.end(); q++)
      q->Join();
  }
  std::cerr << "Done.\n";
  return 0;
}
