////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2005-2008. // (C) Copyright Vicente J. Botet Escriba 2008-2009. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or // copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/synchro for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_SYNCHRO_SEMAPHORE_HPP #define BOOST_SYNCHRO_SEMAPHORE_HPP #include #include #include //!\file //!Describes a semaphore class for inter-process synchronization namespace boost { namespace synchro { //!Wraps a semaphore that can be placed in shared memory and can be //!shared between processes. Allows timed lock tries template class basic_semaphore { typedef synchronization_family Sync; typedef typename Sync::mutex_type lockable_type; typedef typename Sync::condition_type condition_variable; typedef typename unique_lock_type::type scoped_lock; typedef basic_semaphore this_type; public: BOOST_COPY_CONSTRUCTOR_DELETE(basic_semaphore) /*< disable copy construction >*/ BOOST_COPY_ASSIGNEMENT_DELETE(basic_semaphore) /*< disable copy asignement >*/ //!Creates a semaphore with the given initial count. //!exception if there is an error.*/ inline basic_semaphore(int initialCount); //!Destroys the semaphore. //!Does not throw inline ~basic_semaphore(); //!Increments the semaphore count. If there are processes/threads blocked waiting //!for the semaphore, then one of these processes will return successfully from //!its wait function. If there is an error an exception exception is thrown. inline void post(); //!Decrements the semaphore. If the semaphore value is not greater than zero, //!then the calling process/thread blocks until it can decrement the counter. //!If there is an error an exception exception is thrown. inline void wait(); //!Decrements the semaphore if the semaphore's value is greater than zero //!and returns true. If the value is not greater than zero returns false. //!If there is an error an exception exception is thrown. inline bool try_wait(); //!Decrements the semaphore if the semaphore's value is greater //!than zero and returns true. Otherwise, waits for the semaphore //!to the posted or the timeout expires. If the timeout expires, the //!function returns false. If the semaphore is posted the function //!returns true. If there is an error throws sem_exception inline bool try_wait_until(const system_time &abs_time); template inline bool try_wait_for(const TimeDuration &rel_time) { return try_wait_until(get_system_time()+rel_time); } inline void wait_until(const system_time &abs_time) { if (!try_wait_until(abs_time)) throw timeout_exception(); } template inline void wait_for(const TimeDuration &rel_time) { if (!try_wait_until(rel_time)) throw timeout_exception(); } /// @cond protected: lockable_type m_mut; condition_variable m_cond; int m_count; /// @endcond }; template inline basic_semaphore::~basic_semaphore() {} template inline basic_semaphore::basic_semaphore(int initialCount) : m_mut(), m_cond(), m_count(initialCount) {} template inline void basic_semaphore::post() { scoped_lock lock(m_mut); if(m_count == 0){ m_cond.notify_one(); } ++m_count; } template inline void basic_semaphore::wait() { scoped_lock lock(m_mut); while(m_count == 0){ m_cond.wait(lock); } --m_count; } template inline bool basic_semaphore::try_wait() { scoped_lock lock(m_mut); if(m_count == 0){ return false; } --m_count; return true; } template inline bool basic_semaphore::try_wait_until(const system_time &abs_time) { scoped_lock lock(m_mut); while(m_count == 0){ if(!m_cond.timed_wait(lock, abs_time)) return m_count != 0; } --m_count; return true; } typedef basic_semaphore<> semaphore; template class basic_binary_semaphore: public basic_semaphore { public: BOOST_COPY_CONSTRUCTOR_DELETE(basic_binary_semaphore) /*< disable copy construction >*/ BOOST_COPY_ASSIGNEMENT_DELETE(basic_binary_semaphore) /*< disable copy asignement >*/ //!Creates a semaphore with the given initial count. //!exception if there is an error.*/ inline explict basic_binary_semaphore(int initialCount):basic_semaphore(initialCount>0?1:0) {}; inline void post() { scoped_lock lock(this->m_mut); if(this->m_count == 0){ this->m_cond.notify_one(); ++(this->m_count); } } }; typedef basic_binary_semaphore<> binary_semaphore; } } #endif //BOOST_SYNCHRO_SEMAPHORE_HPP