]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/src/event.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / log / src / event.cpp
1 /*
2 * Copyright Andrey Semashev 2007 - 2021.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7 /*!
8 * \file event.cpp
9 * \author Andrey Semashev
10 * \date 24.07.2011
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16 #include <boost/log/detail/config.hpp>
17
18 #ifndef BOOST_LOG_NO_THREADS
19
20 #include <boost/assert.hpp>
21 #include <boost/cstdint.hpp>
22 #include <boost/throw_exception.hpp>
23 #include <boost/log/detail/event.hpp>
24 #include <boost/log/exceptions.hpp>
25
26 #if defined(BOOST_LOG_EVENT_USE_ATOMIC)
27
28 #include <boost/memory_order.hpp>
29 #include <boost/atomic/atomic.hpp>
30 #include <boost/atomic/fences.hpp>
31
32 #elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
33
34 #include <errno.h>
35 #include <semaphore.h>
36 #include <boost/memory_order.hpp>
37 #include <boost/atomic/fences.hpp>
38
39 #elif defined(BOOST_LOG_EVENT_USE_WINAPI)
40
41 #include <windows.h>
42 #include <boost/memory_order.hpp>
43 #include <boost/atomic/atomic.hpp>
44 #include <boost/atomic/fences.hpp>
45
46 #else
47
48 #include <boost/thread/locks.hpp>
49
50 #endif
51
52 #include <boost/log/detail/header.hpp>
53
54 namespace boost {
55
56 BOOST_LOG_OPEN_NAMESPACE
57
58 namespace aux {
59
60 #if defined(BOOST_LOG_EVENT_USE_ATOMIC)
61
62 //! Waits for the object to become signalled
63 BOOST_LOG_API void atomic_based_event::wait()
64 {
65 while (m_state.exchange(0u, boost::memory_order_acq_rel) == 0u)
66 {
67 m_state.wait(0u, boost::memory_order_relaxed);
68 }
69 }
70
71 //! Sets the object to a signalled state
72 BOOST_LOG_API void atomic_based_event::set_signalled()
73 {
74 if (m_state.load(boost::memory_order_relaxed) != 0u)
75 {
76 boost::atomic_thread_fence(boost::memory_order_release);
77 }
78 else if (m_state.exchange(1u, boost::memory_order_release) == 0u)
79 {
80 m_state.notify_one();
81 }
82 }
83
84 #elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
85
86 //! Default constructor
87 BOOST_LOG_API sem_based_event::sem_based_event() : m_state()
88 {
89 if (BOOST_UNLIKELY(sem_init(&m_semaphore, 0, 0) != 0))
90 {
91 const int err = errno;
92 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to initialize semaphore", (err));
93 }
94 }
95
96 //! Destructor
97 BOOST_LOG_API sem_based_event::~sem_based_event()
98 {
99 BOOST_VERIFY(sem_destroy(&m_semaphore) == 0);
100 }
101
102 //! Waits for the object to become signalled
103 BOOST_LOG_API void sem_based_event::wait()
104 {
105 boost::atomic_thread_fence(boost::memory_order_acq_rel);
106 while (true)
107 {
108 if (sem_wait(&m_semaphore) != 0)
109 {
110 const int err = errno;
111 if (BOOST_UNLIKELY(err != EINTR))
112 {
113 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to block on the semaphore", (err));
114 }
115 }
116 else
117 break;
118 }
119 m_state.clear(boost::memory_order_relaxed);
120 }
121
122 //! Sets the object to a signalled state
123 BOOST_LOG_API void sem_based_event::set_signalled()
124 {
125 if (!m_state.test_and_set(boost::memory_order_release))
126 {
127 if (BOOST_UNLIKELY(sem_post(&m_semaphore) != 0))
128 {
129 const int err = errno;
130 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to wake the blocked thread", (err));
131 }
132 }
133 }
134
135 #elif defined(BOOST_LOG_EVENT_USE_WINAPI)
136
137 //! Default constructor
138 BOOST_LOG_API winapi_based_event::winapi_based_event() :
139 m_state(0u),
140 m_event(NULL)
141 {
142 if (!m_state.has_native_wait_notify())
143 {
144 m_event = CreateEventA(NULL, false, false, NULL);
145 if (BOOST_UNLIKELY(!m_event))
146 {
147 const DWORD err = GetLastError();
148 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to create Windows event", (err));
149 }
150 }
151 }
152
153 //! Destructor
154 BOOST_LOG_API winapi_based_event::~winapi_based_event()
155 {
156 if (!!m_event)
157 {
158 BOOST_VERIFY(CloseHandle(m_event) != 0);
159 }
160 }
161
162 //! Waits for the object to become signalled
163 BOOST_LOG_API void winapi_based_event::wait()
164 {
165 if (!m_event)
166 {
167 while (m_state.exchange(0u, boost::memory_order_acq_rel) == 0u)
168 {
169 m_state.wait(0u, boost::memory_order_relaxed);
170 }
171 }
172 else
173 {
174 while (m_state.exchange(0u, boost::memory_order_acq_rel) == 0u)
175 {
176 if (BOOST_UNLIKELY(WaitForSingleObject(m_event, INFINITE) != 0))
177 {
178 const DWORD err = GetLastError();
179 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to block on Windows event", (err));
180 }
181 }
182 }
183 }
184
185 //! Sets the object to a signalled state
186 BOOST_LOG_API void winapi_based_event::set_signalled()
187 {
188 if (m_state.load(boost::memory_order_relaxed) != 0u)
189 {
190 boost::atomic_thread_fence(boost::memory_order_release);
191 }
192 else if (m_state.exchange(1u, boost::memory_order_release) == 0u)
193 {
194 if (!m_event)
195 {
196 m_state.notify_one();
197 }
198 else
199 {
200 if (BOOST_UNLIKELY(SetEvent(m_event) == 0))
201 {
202 const DWORD err = GetLastError();
203 m_state.store(0u, boost::memory_order_relaxed);
204 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to wake the blocked thread", (err));
205 }
206 }
207 }
208 }
209
210 #else
211
212 //! Default constructor
213 BOOST_LOG_API generic_event::generic_event() : m_state(false)
214 {
215 }
216
217 //! Destructor
218 BOOST_LOG_API generic_event::~generic_event()
219 {
220 }
221
222 //! Waits for the object to become signalled
223 BOOST_LOG_API void generic_event::wait()
224 {
225 boost::unique_lock< boost::mutex > lock(m_mutex);
226 while (!m_state)
227 {
228 m_cond.wait(lock);
229 }
230 m_state = false;
231 }
232
233 //! Sets the object to a signalled state
234 BOOST_LOG_API void generic_event::set_signalled()
235 {
236 boost::lock_guard< boost::mutex > lock(m_mutex);
237 if (!m_state)
238 {
239 m_state = true;
240 m_cond.notify_one();
241 }
242 }
243
244 #endif
245
246 } // namespace aux
247
248 BOOST_LOG_CLOSE_NAMESPACE // namespace log
249
250 } // namespace boost
251
252 #include <boost/log/detail/footer.hpp>
253
254 #endif // BOOST_LOG_NO_THREADS