SHARE
TWEET

Chris M. Thomasson

a guest Aug 29th, 2010 349 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //#define RL_DEBUGBREAK_ON_ASSERT
  2. //#define RL_MSVC_OUTPUT
  3. //#define RL_FORCE_SEQ_CST
  4.  
  5.  
  6. #include <relacy/relacy_std.hpp>
  7. #include <cstdio>
  8. #include <cstddef>
  9. #include <climits>
  10. #include <cassert>
  11.  
  12.  
  13.  
  14.  
  15. #define mb_relaxed std::memory_order_relaxed
  16. #define mb_consume std::memory_order_consume
  17. #define mb_acquire std::memory_order_acquire
  18. #define mb_release std::memory_order_release
  19. #define mb_acq_rel std::memory_order_acq_rel
  20. #define mb_system FlushProcessWriteBuffers
  21. #define thread_yield SwitchToThread
  22.  
  23.  
  24.  
  25.  
  26. #if ! defined (NDEBUG)
  27. #   define DBG_PRINTF(e) std::printf e
  28. #else
  29. #   define DBG_PRINTF(e) ((void)0)
  30. #endif
  31.  
  32.  
  33.  
  34.  
  35. class win_condvar
  36. {
  37.     struct waitset
  38.     {
  39.         HANDLE m_events[2];
  40.         std::atomic<unsigned> m_refs;
  41.  
  42.  
  43.         waitset()
  44.         :   m_refs(0)
  45.         {
  46.             m_events[0] = CreateEvent(NULL, true, false, NULL);
  47.             m_events[1] = CreateEvent(NULL, false, false, NULL);
  48.         }
  49.  
  50.  
  51.         ~waitset()
  52.         {
  53.             CloseHandle(m_events[0]);
  54.             CloseHandle(m_events[1]);
  55.         }
  56.     };
  57.  
  58.  
  59. private:
  60.     VAR_T(waitset*) m_waitset;
  61.     VAR_T(unsigned) m_refs;
  62.     CRITICAL_SECTION m_mutex;
  63.  
  64.  
  65. public:
  66.     win_condvar()
  67.     :   m_waitset(NULL),
  68.         m_refs(0)
  69.     {
  70.         InitializeCriticalSection(&m_mutex);
  71.     }
  72.  
  73.  
  74.     ~win_condvar()
  75.     {
  76.         DeleteCriticalSection(&m_mutex);
  77.     }
  78.  
  79.  
  80. public:
  81.     void wait(CRITICAL_SECTION& umutex)
  82.     {
  83.         EnterCriticalSection(&m_mutex);
  84.  
  85.         waitset* w = VAR(m_waitset);
  86.  
  87.         if (! w)
  88.         {
  89.             w = new waitset();
  90.             VAR(m_waitset) = w;
  91.         }
  92.  
  93.         ++VAR(m_refs);
  94.  
  95.         LeaveCriticalSection(&m_mutex);
  96.  
  97.         LeaveCriticalSection(&umutex);
  98.  
  99.         WaitForMultipleObjects(2, w->m_events, false, INFINITE);
  100.  
  101.         if (w->m_refs.fetch_sub(1, mb_release) == 1)
  102.         {
  103.             std::atomic_thread_fence(mb_acquire);
  104.             delete w;
  105.         }
  106.  
  107.         EnterCriticalSection(&umutex);
  108.     }
  109.  
  110.  
  111.     void broadcast()
  112.     {
  113.         EnterCriticalSection(&m_mutex);
  114.  
  115.         waitset* w = VAR(m_waitset);
  116.         unsigned refs = VAR(m_refs);
  117.  
  118.         VAR(m_waitset) = NULL;
  119.         VAR(m_refs) = 0;
  120.  
  121.         LeaveCriticalSection(&m_mutex);
  122.  
  123.         if (w)
  124.         {
  125.             SetEvent(w->m_events[0]);
  126.  
  127.             if (w->m_refs.fetch_add(refs, mb_release) == -refs)
  128.             {
  129.                 std::atomic_thread_fence(mb_acquire);
  130.                 delete w;
  131.             }
  132.         }
  133.     }
  134.  
  135.  
  136.     void signal()
  137.     {
  138.         EnterCriticalSection(&m_mutex);
  139.  
  140.         waitset* w = VAR(m_waitset);
  141.  
  142.         if (w)
  143.         {
  144.             SetEvent(w->m_events[1]);
  145.         }
  146.  
  147.         LeaveCriticalSection(&m_mutex);
  148.     }
  149. };
  150.  
  151.  
  152.  
  153.  
  154. #define ITERS 10
  155. #define THREADS 5
  156.  
  157.  
  158. struct win_condvar_test
  159. :   rl::test_suite<win_condvar_test, THREADS>
  160. {
  161.     win_condvar g_condvar;
  162.     CRITICAL_SECTION g_mutex;
  163.     VAR_T(int) g_state;
  164.  
  165.  
  166.     void before()
  167.     {
  168.         InitializeCriticalSection(&g_mutex);
  169.         VAR(g_state) = 0;
  170.     }
  171.  
  172.  
  173.     void after()
  174.     {
  175.         DeleteCriticalSection(&g_mutex);
  176.     }
  177.  
  178.  
  179.     void thread(unsigned tid)
  180.     {
  181.         DBG_PRINTF(("(%u)->win_condvar_test::thread - init\n", tid));
  182.  
  183.         EnterCriticalSection(&g_mutex);
  184.         unsigned state = VAR(g_state);
  185.  
  186.         while (state != tid)
  187.         {
  188.             g_condvar.wait(g_mutex);
  189.             state = VAR(g_state);
  190.         }
  191.  
  192.         VAR(g_state) = tid + 1;
  193.         LeaveCriticalSection(&g_mutex);
  194.         g_condvar.broadcast();
  195.  
  196.         DBG_PRINTF(("(%u)->win_condvar_test::thread - fini\n", tid));
  197.     }
  198. };
  199.  
  200.  
  201.  
  202.  
  203. int main()
  204. {
  205.     {
  206.         rl::test_params p;
  207.  
  208.         //p.execution_depth_limit = 100000;
  209.         //p.initial_state = "10000000";
  210.         p.iteration_count = 60000000;
  211.         //p.search_type = rl::sched_bound;
  212.         //p.search_type = rl::fair_full_search_scheduler_type;
  213.         //p.search_type = rl::fair_context_bound_scheduler_type;
  214.         rl::simulate<win_condvar_test>(p);
  215.     }
  216.  
  217.     return 0;
  218. }
RAW Paste Data
Top