/src/rt/sync/lock_and_signal.cpp
http://github.com/jruderman/rust · C++ · 169 lines · 118 code · 18 blank · 33 comment · 3 complexity · 81de49abf2f34bec62d3b3ee9c6a0f1e MD5 · raw file
- #include "../rust_globals.h"
- #include "lock_and_signal.h"
- /*
- * A "lock-and-signal" pair. These are necessarily coupled on pthreads
- * systems, and artificially coupled (by this file) on win32. Put
- * together here to minimize ifdefs elsewhere; you must use them as
- * if you're using a pthreads cvar+mutex pair.
- */
- // FIXME (#2683): This is not a portable way of specifying an invalid
- // pthread_t
- #define INVALID_THREAD 0
- #if defined(__WIN32__)
- lock_and_signal::lock_and_signal()
- #if defined(DEBUG_LOCKS)
- : _holding_thread(INVALID_THREAD)
- #endif
- {
- _event = CreateEvent(NULL, FALSE, FALSE, NULL);
- // If a CRITICAL_SECTION is not initialized with a spin count, it will
- // default to 0, even on multi-processor systems. MSDN suggests using
- // 4000. On single-processor systems, the spin count parameter is ignored
- // and the critical section's spin count defaults to 0.
- const DWORD SPIN_COUNT = 4000;
- CHECKED(!InitializeCriticalSectionAndSpinCount(&_cs, SPIN_COUNT));
- // FIXME #2893 Consider checking
- // GetProcAddress("InitializeCriticalSectionEx")
- // so Windows >= Vista we can use CRITICAL_SECTION_NO_DEBUG_INFO to avoid
- // allocating CRITICAL_SECTION debug info that is never released. See:
- // http://stackoverflow.com/questions/804848/
- // critical-sections-leaking-memory-on-vista-win2008#889853
- }
- #else
- lock_and_signal::lock_and_signal()
- #if defined(DEBUG_LOCKS)
- : _holding_thread(INVALID_THREAD)
- #endif
- {
- CHECKED(pthread_cond_init(&_cond, NULL));
- CHECKED(pthread_mutex_init(&_mutex, NULL));
- }
- #endif
- lock_and_signal::~lock_and_signal() {
- #if defined(__WIN32__)
- CloseHandle(_event);
- DeleteCriticalSection(&_cs);
- #else
- CHECKED(pthread_cond_destroy(&_cond));
- CHECKED(pthread_mutex_destroy(&_mutex));
- #endif
- }
- void lock_and_signal::lock() {
- must_not_have_lock();
- #if defined(__WIN32__)
- EnterCriticalSection(&_cs);
- #if defined(DEBUG_LOCKS)
- _holding_thread = GetCurrentThreadId();
- #endif
- #else
- CHECKED(pthread_mutex_lock(&_mutex));
- #if defined(DEBUG_LOCKS)
- _holding_thread = pthread_self();
- #endif
- #endif
- }
- void lock_and_signal::unlock() {
- must_have_lock();
- #if defined(DEBUG_LOCKS)
- _holding_thread = INVALID_THREAD;
- #endif
- #if defined(__WIN32__)
- LeaveCriticalSection(&_cs);
- #else
- CHECKED(pthread_mutex_unlock(&_mutex));
- #endif
- }
- /**
- * Wait indefinitely until condition is signaled.
- */
- void lock_and_signal::wait() {
- must_have_lock();
- #if defined(DEBUG_LOCKS)
- _holding_thread = INVALID_THREAD;
- #endif
- #if defined(__WIN32__)
- LeaveCriticalSection(&_cs);
- WaitForSingleObject(_event, INFINITE);
- EnterCriticalSection(&_cs);
- must_not_be_locked();
- #if defined(DEBUG_LOCKS)
- _holding_thread = GetCurrentThreadId();
- #endif
- #else
- CHECKED(pthread_cond_wait(&_cond, &_mutex));
- must_not_be_locked();
- #if defined(DEBUG_LOCKS)
- _holding_thread = pthread_self();
- #endif
- #endif
- }
- /**
- * Signal condition, and resume the waiting thread.
- */
- void lock_and_signal::signal() {
- #if defined(__WIN32__)
- SetEvent(_event);
- #else
- CHECKED(pthread_cond_signal(&_cond));
- #endif
- }
- #if defined(DEBUG_LOCKS)
- bool lock_and_signal::lock_held_by_current_thread()
- {
- #if defined(__WIN32__)
- return _holding_thread == GetCurrentThreadId();
- #else
- return pthread_equal(_holding_thread, pthread_self());
- #endif
- }
- #endif
- #if defined(DEBUG_LOCKS)
- void lock_and_signal::must_have_lock() {
- assert(lock_held_by_current_thread() && "must have lock");
- }
- void lock_and_signal::must_not_have_lock() {
- assert(!lock_held_by_current_thread() && "must not have lock");
- }
- void lock_and_signal::must_not_be_locked() {
- }
- #else
- void lock_and_signal::must_have_lock() { }
- void lock_and_signal::must_not_have_lock() { }
- void lock_and_signal::must_not_be_locked() { }
- #endif
- scoped_lock::scoped_lock(lock_and_signal &lock)
- : lock(lock)
- {
- lock.lock();
- }
- scoped_lock::~scoped_lock()
- {
- lock.unlock();
- }
- //
- // Local Variables:
- // mode: C++
- // fill-column: 78;
- // indent-tabs-mode: nil
- // c-basic-offset: 4
- // buffer-file-coding-system: utf-8-unix
- // compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
- // End: