Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#define RL_DEBUGBREAK_ON_ASSERT
- //#define RL_MSVC_OUTPUT
- //#define RL_FORCE_SEQ_CST
- #include <relacy/relacy_std.hpp>
- #include <cstdio>
- #include <cstddef>
- #include <climits>
- #include <cassert>
- #define mb_relaxed std::memory_order_relaxed
- #define mb_consume std::memory_order_consume
- #define mb_acquire std::memory_order_acquire
- #define mb_release std::memory_order_release
- #define mb_acq_rel std::memory_order_acq_rel
- #define mb_system FlushProcessWriteBuffers
- #define thread_yield SwitchToThread
- #if ! defined (NDEBUG)
- # define DBG_PRINTF(e) std::printf e
- #else
- # define DBG_PRINTF(e) ((void)0)
- #endif
- class win_condvar
- {
- struct waitset
- {
- HANDLE m_events[2];
- std::atomic<unsigned> m_refs;
- waitset()
- : m_refs(0)
- {
- m_events[0] = CreateEvent(NULL, true, false, NULL);
- m_events[1] = CreateEvent(NULL, false, false, NULL);
- }
- ~waitset()
- {
- CloseHandle(m_events[0]);
- CloseHandle(m_events[1]);
- }
- };
- private:
- VAR_T(waitset*) m_waitset;
- VAR_T(unsigned) m_refs;
- CRITICAL_SECTION m_mutex;
- public:
- win_condvar()
- : m_waitset(NULL),
- m_refs(0)
- {
- InitializeCriticalSection(&m_mutex);
- }
- ~win_condvar()
- {
- DeleteCriticalSection(&m_mutex);
- }
- public:
- void wait(CRITICAL_SECTION& umutex)
- {
- EnterCriticalSection(&m_mutex);
- waitset* w = VAR(m_waitset);
- if (! w)
- {
- w = new waitset();
- VAR(m_waitset) = w;
- }
- ++VAR(m_refs);
- LeaveCriticalSection(&m_mutex);
- LeaveCriticalSection(&umutex);
- WaitForMultipleObjects(2, w->m_events, false, INFINITE);
- if (w->m_refs.fetch_sub(1, mb_release) == 1)
- {
- std::atomic_thread_fence(mb_acquire);
- delete w;
- }
- EnterCriticalSection(&umutex);
- }
- void broadcast()
- {
- EnterCriticalSection(&m_mutex);
- waitset* w = VAR(m_waitset);
- unsigned refs = VAR(m_refs);
- VAR(m_waitset) = NULL;
- VAR(m_refs) = 0;
- LeaveCriticalSection(&m_mutex);
- if (w)
- {
- SetEvent(w->m_events[0]);
- if (w->m_refs.fetch_add(refs, mb_release) == -refs)
- {
- std::atomic_thread_fence(mb_acquire);
- delete w;
- }
- }
- }
- void signal()
- {
- EnterCriticalSection(&m_mutex);
- waitset* w = VAR(m_waitset);
- if (w)
- {
- SetEvent(w->m_events[1]);
- }
- LeaveCriticalSection(&m_mutex);
- }
- };
- #define ITERS 10
- #define THREADS 5
- struct win_condvar_test
- : rl::test_suite<win_condvar_test, THREADS>
- {
- win_condvar g_condvar;
- CRITICAL_SECTION g_mutex;
- VAR_T(int) g_state;
- void before()
- {
- InitializeCriticalSection(&g_mutex);
- VAR(g_state) = 0;
- }
- void after()
- {
- DeleteCriticalSection(&g_mutex);
- }
- void thread(unsigned tid)
- {
- DBG_PRINTF(("(%u)->win_condvar_test::thread - init\n", tid));
- EnterCriticalSection(&g_mutex);
- unsigned state = VAR(g_state);
- while (state != tid)
- {
- g_condvar.wait(g_mutex);
- state = VAR(g_state);
- }
- VAR(g_state) = tid + 1;
- LeaveCriticalSection(&g_mutex);
- g_condvar.broadcast();
- DBG_PRINTF(("(%u)->win_condvar_test::thread - fini\n", tid));
- }
- };
- int main()
- {
- {
- rl::test_params p;
- //p.execution_depth_limit = 100000;
- //p.initial_state = "10000000";
- p.iteration_count = 60000000;
- //p.search_type = rl::sched_bound;
- //p.search_type = rl::fair_full_search_scheduler_type;
- //p.search_type = rl::fair_context_bound_scheduler_type;
- rl::simulate<win_condvar_test>(p);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement