Guest User

Chris M. Thomasson

a guest
Aug 29th, 2010
561
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