1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4 *
5 * This library is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include "e-flag.h"
20
21 struct _EFlag {
22 GCond cond;
23 GMutex mutex;
24 gboolean is_set;
25 };
26
27 /* This is to keep e_flag_timed_wait() building, since
28 * it relies on g_cond_timed_wait() which is deprecated. */
29 #ifdef G_DISABLE_DEPRECATED
30 gboolean g_cond_timed_wait (GCond *cond,
31 GMutex *mutex,
32 GTimeVal *timeval);
33 #endif /* G_DISABLE_DEPRECATED */
34
35 /**
36 * e_flag_new: (skip)
37 *
38 * Creates a new #EFlag object. It is initially unset.
39 *
40 * Returns: a new #EFlag
41 *
42 * Since: 1.12
43 **/
44 EFlag *
e_flag_new(void)45 e_flag_new (void)
46 {
47 EFlag *flag;
48
49 flag = g_slice_new (EFlag);
50 g_cond_init (&flag->cond);
51 g_mutex_init (&flag->mutex);
52 flag->is_set = FALSE;
53
54 return flag;
55 }
56
57 /**
58 * e_flag_is_set: (skip)
59 * @flag: an #EFlag
60 *
61 * Returns the state of @flag.
62 *
63 * Returns: %TRUE if @flag is set
64 *
65 * Since: 1.12
66 **/
67 gboolean
e_flag_is_set(EFlag * flag)68 e_flag_is_set (EFlag *flag)
69 {
70 gboolean is_set;
71
72 g_return_val_if_fail (flag != NULL, FALSE);
73
74 g_mutex_lock (&flag->mutex);
75 is_set = flag->is_set;
76 g_mutex_unlock (&flag->mutex);
77
78 return is_set;
79 }
80
81 /**
82 * e_flag_set: (skip)
83 * @flag: an #EFlag
84 *
85 * Sets @flag. All threads waiting on @flag are woken up. Threads that
86 * call e_flag_wait() or e_flag_wait_until() once @flag is set will not
87 * block at all.
88 *
89 * Since: 1.12
90 **/
91 void
e_flag_set(EFlag * flag)92 e_flag_set (EFlag *flag)
93 {
94 g_return_if_fail (flag != NULL);
95
96 g_mutex_lock (&flag->mutex);
97 flag->is_set = TRUE;
98 g_cond_broadcast (&flag->cond);
99 g_mutex_unlock (&flag->mutex);
100 }
101
102 /**
103 * e_flag_clear: (skip)
104 * @flag: an #EFlag
105 *
106 * Unsets @flag. Subsequent calls to e_flag_wait() or e_flag_wait_until()
107 * will block until @flag is set.
108 *
109 * Since: 1.12
110 **/
111 void
e_flag_clear(EFlag * flag)112 e_flag_clear (EFlag *flag)
113 {
114 g_return_if_fail (flag != NULL);
115
116 g_mutex_lock (&flag->mutex);
117 flag->is_set = FALSE;
118 g_mutex_unlock (&flag->mutex);
119 }
120
121 /**
122 * e_flag_wait: (skip)
123 * @flag: an #EFlag
124 *
125 * Blocks until @flag is set. If @flag is already set, the function returns
126 * immediately.
127 *
128 * Since: 1.12
129 **/
130 void
e_flag_wait(EFlag * flag)131 e_flag_wait (EFlag *flag)
132 {
133 g_return_if_fail (flag != NULL);
134
135 g_mutex_lock (&flag->mutex);
136 while (!flag->is_set)
137 g_cond_wait (&flag->cond, &flag->mutex);
138 g_mutex_unlock (&flag->mutex);
139 }
140
141 /**
142 * e_flag_timed_wait: (skip)
143 * @flag: an #EFlag
144 * @abs_time: a #GTimeVal, determining the final time
145 *
146 * Blocks until @flag is set, or until the time specified by @abs_time.
147 * If @flag is already set, the function returns immediately. The return
148 * value indicates the state of @flag after waiting.
149 *
150 * If @abs_time is %NULL, e_flag_timed_wait() acts like e_flag_wait().
151 *
152 * To easily calculate @abs_time, a combination of g_get_current_time() and
153 * g_time_val_add() can be used.
154 *
155 * Returns: %TRUE if @flag is now set
156 *
157 * Since: 1.12
158 *
159 * Deprecated: 3.8: Use e_flag_wait_until() instead.
160 **/
161 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
162 gboolean
e_flag_timed_wait(EFlag * flag,GTimeVal * abs_time)163 e_flag_timed_wait (EFlag *flag,
164 GTimeVal *abs_time)
165 {
166 gboolean is_set;
167
168 g_return_val_if_fail (flag != NULL, FALSE);
169
170 g_mutex_lock (&flag->mutex);
171 while (!flag->is_set)
172 if (!g_cond_timed_wait (&flag->cond, &flag->mutex, abs_time))
173 break;
174 is_set = flag->is_set;
175 g_mutex_unlock (&flag->mutex);
176
177 return is_set;
178 }
179 G_GNUC_END_IGNORE_DEPRECATIONS
180
181 /**
182 * e_flag_wait_until: (skip)
183 * @flag: an #EFlag
184 * @end_time: the monotonic time to wait until
185 *
186 * Blocks until @flag is set, or until the time specified by @end_time.
187 * If @flag is already set, the function returns immediately. The return
188 * value indicates the state of @flag after waiting.
189 *
190 * To easily calculate @end_time, a combination of g_get_monotonic_time() and
191 * G_TIME_SPAN_SECOND macro.
192 *
193 * Returns: %TRUE if @flag is now set
194 *
195 * Since: 3.8
196 **/
197 gboolean
e_flag_wait_until(EFlag * flag,gint64 end_time)198 e_flag_wait_until (EFlag *flag,
199 gint64 end_time)
200 {
201 gboolean is_set;
202
203 g_return_val_if_fail (flag != NULL, FALSE);
204
205 g_mutex_lock (&flag->mutex);
206 while (!flag->is_set)
207 if (!g_cond_wait_until (&flag->cond, &flag->mutex, end_time))
208 break;
209 is_set = flag->is_set;
210 g_mutex_unlock (&flag->mutex);
211
212 return is_set;
213 }
214
215 /**
216 * e_flag_free: (skip)
217 * @flag: an #EFlag
218 *
219 * Destroys @flag.
220 *
221 * Since: 1.12
222 **/
223 void
e_flag_free(EFlag * flag)224 e_flag_free (EFlag *flag)
225 {
226 g_return_if_fail (flag != NULL);
227
228 /* Just to make sure that other threads are not holding the lock. */
229 g_mutex_lock (&flag->mutex);
230 g_cond_clear (&flag->cond);
231 g_mutex_unlock (&flag->mutex);
232 g_mutex_clear (&flag->mutex);
233 g_slice_free (EFlag, flag);
234 }
235