Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #ifndef __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
31 : #define __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
32 :
33 : #include "platform.hpp"
34 : #include "clock.hpp"
35 : #include "err.hpp"
36 : #include "mutex.hpp"
37 :
38 : // Condition variable class encapsulates OS mutex in a platform-independent way.
39 :
40 : #ifdef ZMQ_HAVE_WINDOWS
41 :
42 : #include "windows.hpp"
43 :
44 : // Condition variable is supported from Windows Vista only, to use condition variable define _WIN32_WINNT to 0x0600
45 : #if _WIN32_WINNT < 0x0600
46 :
47 : namespace zmq
48 : {
49 :
50 : class condition_variable_t
51 : {
52 : public:
53 : inline condition_variable_t ()
54 : {
55 : zmq_assert(false);
56 : }
57 :
58 : inline ~condition_variable_t ()
59 : {
60 :
61 : }
62 :
63 : inline int wait (mutex_t* mutex_, int timeout_ )
64 : {
65 : zmq_assert(false);
66 : return -1;
67 : }
68 :
69 : inline void broadcast ()
70 : {
71 : zmq_assert(false);
72 : }
73 :
74 : private:
75 :
76 : // Disable copy construction and assignment.
77 : condition_variable_t (const condition_variable_t&);
78 : void operator = (const condition_variable_t&);
79 : };
80 :
81 : }
82 :
83 : #else
84 :
85 : namespace zmq
86 : {
87 :
88 : class condition_variable_t
89 : {
90 : public:
91 : inline condition_variable_t ()
92 : {
93 : InitializeConditionVariable (&cv);
94 : }
95 :
96 : inline ~condition_variable_t ()
97 : {
98 :
99 : }
100 :
101 : inline int wait (mutex_t* mutex_, int timeout_ )
102 : {
103 : int rc = SleepConditionVariableCS(&cv, mutex_->get_cs (), timeout_);
104 :
105 : if (rc != 0)
106 : return 0;
107 :
108 : rc = GetLastError();
109 :
110 : if (rc != ERROR_TIMEOUT)
111 : win_assert(rc);
112 :
113 : errno = EAGAIN;
114 : return -1;
115 : }
116 :
117 : inline void broadcast ()
118 : {
119 : WakeAllConditionVariable(&cv);
120 : }
121 :
122 : private:
123 :
124 : CONDITION_VARIABLE cv;
125 :
126 : // Disable copy construction and assignment.
127 : condition_variable_t (const condition_variable_t&);
128 : void operator = (const condition_variable_t&);
129 : };
130 :
131 : }
132 :
133 : #endif
134 :
135 : #else
136 :
137 : #include <pthread.h>
138 :
139 : namespace zmq
140 : {
141 :
142 : class condition_variable_t
143 : {
144 : public:
145 51 : inline condition_variable_t ()
146 : {
147 51 : int rc = pthread_cond_init (&cond, NULL);
148 51 : posix_assert (rc);
149 51 : }
150 :
151 51 : inline ~condition_variable_t ()
152 : {
153 51 : int rc = pthread_cond_destroy (&cond);
154 51 : posix_assert (rc);
155 51 : }
156 :
157 8984 : inline int wait (mutex_t* mutex_, int timeout_)
158 : {
159 : int rc;
160 :
161 8984 : if (timeout_ != -1) {
162 : struct timespec timeout;
163 7863 : clock_gettime(CLOCK_REALTIME, &timeout);
164 :
165 7863 : timeout.tv_sec += timeout_ / 1000;
166 7863 : timeout.tv_nsec += (timeout_ % 1000) * 1000000;
167 :
168 7863 : if (timeout.tv_nsec > 1000000000) {
169 0 : timeout.tv_sec++;
170 0 : timeout.tv_nsec -= 1000000000;
171 : }
172 :
173 7863 : rc = pthread_cond_timedwait (&cond, mutex_->get_mutex (), &timeout);
174 : }
175 : else
176 1121 : rc = pthread_cond_wait(&cond, mutex_->get_mutex());
177 :
178 8984 : if (rc == 0)
179 : return 0;
180 :
181 7507 : if (rc == ETIMEDOUT){
182 7507 : errno= EAGAIN;
183 7507 : return -1;
184 : }
185 :
186 0 : posix_assert (rc);
187 : return -1;
188 : }
189 :
190 1485 : inline void broadcast ()
191 : {
192 1485 : int rc = pthread_cond_broadcast (&cond);
193 1485 : posix_assert (rc);
194 1485 : }
195 :
196 : private:
197 :
198 : pthread_cond_t cond;
199 :
200 : // Disable copy construction and assignment.
201 : condition_variable_t (const condition_variable_t&);
202 : const condition_variable_t &operator = (const condition_variable_t&);
203 : };
204 : }
205 :
206 : #endif
207 :
208 :
209 : #endif
|