// Copyright (c) 2007 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt #include "event.hpp" #include struct monitor { pthread_mutex_t mx_; pthread_cond_t cn_; }; #define MONITOR_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER } int const N = 7; static monitor s_monitor_pool[ N ] = { MONITOR_INIT, MONITOR_INIT, MONITOR_INIT, MONITOR_INIT, MONITOR_INIT, MONITOR_INIT, MONITOR_INIT, }; static monitor * monitor_for( void const * p ) { return &s_monitor_pool[ ((size_t)p) % N ]; } class pt_scoped_lock { private: pthread_mutex_t * pmx_; public: explicit pt_scoped_lock( pthread_mutex_t & mx ): pmx_( &mx ) { pthread_mutex_lock( pmx_ ); } ~pt_scoped_lock() { pthread_mutex_unlock( pmx_ ); } }; event::event(): is_set_( false ) { } void event::set() { monitor * pm = monitor_for( this ); { pt_scoped_lock lock( pm->mx_ ); is_set_ = true; } pthread_cond_broadcast( &pm->cn_ ); } void event::reset() { monitor * pm = monitor_for( this ); pt_scoped_lock lock( pm->mx_ ); is_set_ = false; } int event::wait() { monitor * pm = monitor_for( this ); pt_scoped_lock lock( pm->mx_ ); while( !is_set_ ) { int r = pthread_cond_wait( &pm->cn_, &pm->mx_ ); if( r != 0 ) return r; } return 0; } int event::try_wait() { monitor * pm = monitor_for( this ); pt_scoped_lock lock( pm->mx_ ); return is_set_? 0: EBUSY; } int event::timed_wait( timespec const & abstime ) { monitor * pm = monitor_for( this ); pt_scoped_lock lock( pm->mx_ ); while( !is_set_ ) { int r = pthread_cond_timedwait( &pm->cn_, &pm->mx_, &abstime ); if( r == ETIMEDOUT && is_set_ ) return 0; if( r != 0 ) return r; } return 0; } int event::lock() { monitor * pm = monitor_for( this ); return pthread_mutex_lock( &pm->mx_ ); } int event::try_lock() { monitor * pm = monitor_for( this ); return pthread_mutex_trylock( &pm->mx_ ); } int event::timed_lock( timespec const & abstime ) { monitor * pm = monitor_for( this ); return pthread_mutex_timedlock( &pm->mx_, &abstime ); } int event::unlock() { monitor * pm = monitor_for( this ); return pthread_mutex_unlock( &pm->mx_ ); } bool event::unlocked_is_set() const { return is_set_; } void event::unlocked_set() { is_set_ = true; monitor * pm = monitor_for( this ); pthread_cond_broadcast( &pm->cn_ ); } void event::unlocked_reset() { is_set_ = false; }