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
- /*
- Condition Variable Algorithm By Michael Podolsky
- http://groups.google.com/group/comp.programming.threads/msg/fe8217a6f3512fe4
- */
- class win_condvar
- {
- VAR_T(int) m_waiters;
- VAR_T(int) m_task;
- HANDLE m_turn1;
- HANDLE m_turn2;
- CRITICAL_SECTION m_mutex;
- private:
- void prv_signal(bool all)
- {
- WaitForSingleObject(m_turn1, INFINITE);
- EnterCriticalSection(&m_mutex);
- int waiters = VAR(m_waiters);
- if (waiters)
- {
- if (all)
- {
- VAR(m_task) = 0;
- }
- else
- {
- VAR(m_task) = waiters - 1;
- }
- LeaveCriticalSection(&m_mutex);
- ReleaseSemaphore(m_turn2, 1, NULL);
- }
- else
- {
- LeaveCriticalSection(&m_mutex);
- ReleaseSemaphore(m_turn1, 1, NULL);
- }
- }
- public:
- win_condvar()
- : m_waiters(0),
- m_task(0),
- m_turn1(CreateSemaphore(NULL, 1, LONG_MAX, NULL)),
- m_turn2(CreateSemaphore(NULL, 0, LONG_MAX, NULL))
- {
- InitializeCriticalSection(&m_mutex);
- }
- ~win_condvar()
- {
- DeleteCriticalSection(&m_mutex);
- CloseHandle(m_turn2);
- CloseHandle(m_turn1);
- }
- public:
- void wait(CRITICAL_SECTION& umutex)
- {
- WaitForSingleObject(m_turn1, INFINITE);
- EnterCriticalSection(&m_mutex);
- ++VAR(m_waiters);
- LeaveCriticalSection(&m_mutex);
- ReleaseSemaphore(m_turn1, 1, NULL);
- LeaveCriticalSection(&umutex);
- WaitForSingleObject(m_turn2, INFINITE);
- EnterCriticalSection(&m_mutex);
- --VAR(m_waiters);
- bool last = VAR(m_waiters) == VAR(m_task) ? true : false;
- LeaveCriticalSection(&m_mutex);
- if (last)
- {
- ReleaseSemaphore(m_turn1, 1, NULL);
- }
- else
- {
- ReleaseSemaphore(m_turn2, 1, NULL);
- }
- EnterCriticalSection(&umutex);
- }
- void signal()
- {
- prv_signal(false);
- }
- void broadcast()
- {
- prv_signal(true);
- }
- };
- #define ITERS 10
- #define THREADS 6
- 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;
- if (! (tid % 2))
- {
- g_condvar.signal();
- g_condvar.broadcast();
- }
- LeaveCriticalSection(&g_mutex);
- if (tid % 2)
- {
- g_condvar.signal();
- 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);
- }
- std::puts("\n\n____________________________________\n"
- "The program has completed!\n");
- std::fflush(stdout);
- std::getchar();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement