1 // semaphore.hpp, mutex/condition_varibale emulation
2 //
3 // Copyright (C) 2013 Tim Blechmann
4 // Copyright (C) 2013 Andrey Semashev
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 
10 #ifndef BOOST_SYNC_DETAIL_SEMAPHORE_SEMAPHORE_EMULATION_HPP_INCLUDED_
11 #define BOOST_SYNC_DETAIL_SEMAPHORE_SEMAPHORE_EMULATION_HPP_INCLUDED_
12 
13 #include <boost/utility/enable_if.hpp>
14 #include <boost/sync/detail/config.hpp>
15 #include <boost/sync/detail/time_traits.hpp>
16 #include <boost/sync/locks/lock_guard.hpp>
17 #include <boost/sync/locks/unique_lock.hpp>
18 #include <boost/sync/mutexes/mutex.hpp>
19 #include <boost/sync/condition_variables/condition_variable.hpp>
20 #include <boost/sync/detail/header.hpp>
21 
22 #ifdef BOOST_HAS_PRAGMA_ONCE
23 #pragma once
24 #endif
25 
26 #define BOOST_SYNC_SEMAPHORE_EMULATED
27 
28 namespace boost {
29 
30 namespace sync  {
31 
32 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
33 
34 class semaphore
35 {
36     BOOST_DELETED_FUNCTION(semaphore(semaphore const&))
37     BOOST_DELETED_FUNCTION(semaphore& operator=(semaphore const&))
38 
39 public:
40     explicit semaphore(unsigned int i = 0) : m_count(i)
41     {
42     }
43 
44     void post()
45     {
46         sync::lock_guard< sync::mutex > lock(m_mutex);
47         ++m_count;
48         m_cond.notify_one();
49     }
50 
51     void wait()
52     {
53         sync::unique_lock< sync::mutex > lock(m_mutex);
54         while (m_count == 0)
55             m_cond.wait(lock);
56 
57         --m_count;
58     }
59 
60     bool try_wait()
61     {
62         sync::lock_guard< sync::mutex > lock(m_mutex);
63         if (m_count == 0)
64             return false;
65 
66         --m_count;
67         return true;
68     }
69 
70     template< typename Time >
71     typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type timed_wait(Time const& timeout)
72     {
73         sync::unique_lock< sync::mutex > lock(m_mutex);
74         while (m_count == 0)
75         {
76             if (!m_cond.timed_wait(lock, timeout))
77             {
78                 if (m_count == 0)
79                     return false;
80                 else
81                     break;
82             }
83         }
84 
85         --m_count;
86         return true;
87     }
88 
89     template< typename Duration >
90     typename enable_if< detail::is_time_tag_of< Duration, detail::time_duration_tag >, bool >::type wait_for(Duration const& duration)
91     {
92         return timed_wait(duration);
93     }
94 
95     template< typename TimePoint >
96     typename enable_if< detail::is_time_tag_of< TimePoint, detail::time_point_tag >, bool >::type wait_until(TimePoint const& abs_time)
97     {
98         return timed_wait(abs_time);
99     }
100 
101 private:
102     sync::mutex m_mutex;
103     sync::condition_variable m_cond;
104     unsigned int m_count;
105 };
106 
107 } // namespace abi
108 
109 } // namespace sync
110 
111 } // namespace boost
112 
113 #include <boost/sync/detail/footer.hpp>
114 
115 #endif // BOOST_SYNC_DETAIL_SEMAPHORE_SEMAPHORE_EMULATION_HPP_INCLUDED_
116