SHARE
TWEET

Chris M. Thomasson

a guest Oct 6th, 2010 254 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.  
  7.  
  8. #include <relacy/relacy_std.hpp>
  9. #include <cstdio>
  10. #include <cstddef>
  11. #include <climits>
  12. #include <cassert>
  13.  
  14.  
  15.  
  16.  
  17. #define mb_relaxed std::memory_order_relaxed
  18. #define mb_consume std::memory_order_consume
  19. #define mb_acquire std::memory_order_acquire
  20. #define mb_release std::memory_order_release
  21. #define mb_acq_rel std::memory_order_acq_rel
  22. #define mb_system FlushProcessWriteBuffers
  23. #define thread_yield SwitchToThread
  24.  
  25.  
  26.  
  27.  
  28. #if ! defined (NDEBUG)
  29. #   define DBG_PRINTF(e) std::printf e
  30. #else
  31. #   define DBG_PRINTF(e) ((void)0)
  32. #endif
  33.  
  34.  
  35.  
  36.  
  37. /*
  38.     Condition Variable Algorithm By Michael Podolsky
  39.  
  40.     http://groups.google.com/group/comp.programming.threads/msg/fe8217a6f3512fe4
  41. */
  42. class win_condvar
  43. {
  44.     VAR_T(int) m_waiters;
  45.     VAR_T(int) m_task;
  46.     HANDLE m_turn1;
  47.     HANDLE m_turn2;
  48.     CRITICAL_SECTION m_mutex;
  49.  
  50.  
  51. private:
  52.     void prv_signal(bool all)
  53.     {
  54.         WaitForSingleObject(m_turn1, INFINITE);
  55.         EnterCriticalSection(&m_mutex);
  56.         int waiters = VAR(m_waiters);
  57.  
  58.         if (waiters)
  59.         {
  60.             if (all)
  61.             {
  62.                 VAR(m_task) = 0;
  63.             }
  64.  
  65.             else
  66.             {
  67.                 VAR(m_task) = waiters - 1;
  68.             }
  69.  
  70.             LeaveCriticalSection(&m_mutex);
  71.             ReleaseSemaphore(m_turn2, 1, NULL);
  72.         }
  73.  
  74.         else
  75.         {
  76.             LeaveCriticalSection(&m_mutex);
  77.             ReleaseSemaphore(m_turn1, 1, NULL);
  78.         }
  79.     }
  80.  
  81.  
  82. public:
  83.     win_condvar()
  84.     :   m_waiters(0),
  85.         m_task(0),
  86.         m_turn1(CreateSemaphore(NULL, 1, LONG_MAX, NULL)),
  87.         m_turn2(CreateSemaphore(NULL, 0, LONG_MAX, NULL))
  88.     {
  89.         InitializeCriticalSection(&m_mutex);
  90.     }
  91.  
  92.  
  93.     ~win_condvar()
  94.     {
  95.         DeleteCriticalSection(&m_mutex);
  96.         CloseHandle(m_turn2);
  97.         CloseHandle(m_turn1);
  98.     }
  99.    
  100.  
  101. public:
  102.     void wait(CRITICAL_SECTION& umutex)
  103.     {
  104.         WaitForSingleObject(m_turn1, INFINITE);
  105.         EnterCriticalSection(&m_mutex);
  106.         ++VAR(m_waiters);
  107.         LeaveCriticalSection(&m_mutex);
  108.         ReleaseSemaphore(m_turn1, 1, NULL);
  109.  
  110.         LeaveCriticalSection(&umutex);
  111.  
  112.         WaitForSingleObject(m_turn2, INFINITE);
  113.  
  114.         EnterCriticalSection(&m_mutex);
  115.         --VAR(m_waiters);
  116.         bool last = VAR(m_waiters) == VAR(m_task) ? true : false;
  117.         LeaveCriticalSection(&m_mutex);
  118.  
  119.         if (last)
  120.         {
  121.             ReleaseSemaphore(m_turn1, 1, NULL);
  122.         }
  123.  
  124.         else
  125.         {
  126.             ReleaseSemaphore(m_turn2, 1, NULL);
  127.         }
  128.  
  129.         EnterCriticalSection(&umutex);
  130.     }
  131.  
  132.  
  133.     void signal()
  134.     {
  135.         prv_signal(false);
  136.     }
  137.  
  138.  
  139.     void broadcast()
  140.     {
  141.         prv_signal(true);
  142.     }
  143. };
  144.  
  145.  
  146.  
  147.  
  148. #define ITERS 10
  149. #define THREADS 6
  150.  
  151.  
  152. struct win_condvar_test
  153. :   rl::test_suite<win_condvar_test, THREADS>
  154. {
  155.     win_condvar g_condvar;
  156.     CRITICAL_SECTION g_mutex;
  157.     VAR_T(int) g_state;
  158.  
  159.  
  160.     void before()
  161.     {
  162.         InitializeCriticalSection(&g_mutex);
  163.         VAR(g_state) = 0;
  164.     }
  165.  
  166.  
  167.     void after()
  168.     {
  169.         DeleteCriticalSection(&g_mutex);
  170.     }
  171.  
  172.  
  173.     void thread(unsigned tid)
  174.     {
  175.         DBG_PRINTF(("(%u)->win_condvar_test::thread - init\n", tid));
  176.  
  177.         EnterCriticalSection(&g_mutex);
  178.         unsigned state = VAR(g_state);
  179.  
  180.         while (state != tid)
  181.         {
  182.             g_condvar.wait(g_mutex);
  183.             state = VAR(g_state);
  184.         }
  185.  
  186.         VAR(g_state) = tid + 1;
  187.  
  188.         if (! (tid % 2))
  189.         {
  190.             g_condvar.signal();
  191.             g_condvar.broadcast();
  192.         }
  193.  
  194.         LeaveCriticalSection(&g_mutex);
  195.  
  196.         if (tid % 2)
  197.         {
  198.             g_condvar.signal();
  199.             g_condvar.broadcast();
  200.         }
  201.  
  202.         DBG_PRINTF(("(%u)->win_condvar_test::thread - fini\n", tid));
  203.     }
  204. };
  205.  
  206.  
  207.  
  208.  
  209. int main()
  210. {
  211.     {
  212.         rl::test_params p;
  213.  
  214.         //p.execution_depth_limit = 100000;
  215.         //p.initial_state = "10000000";
  216.         p.iteration_count = 60000000;
  217.         //p.search_type = rl::sched_bound;
  218.         //p.search_type = rl::fair_full_search_scheduler_type;
  219.         //p.search_type = rl::fair_context_bound_scheduler_type;
  220.         rl::simulate<win_condvar_test>(p);
  221.     }
  222.  
  223.         std::puts("\n\n____________________________________\n"
  224.                       "The program has completed!\n");
  225.         std::fflush(stdout);
  226.         std::getchar();
  227.  
  228.     return 0;
  229. }
RAW Paste Data
Top