/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . * */ #include "e-flag.h" struct _EFlag { GCond cond; GMutex mutex; gboolean is_set; }; /* This is to keep e_flag_timed_wait() building, since * it relies on g_cond_timed_wait() which is deprecated. */ #ifdef G_DISABLE_DEPRECATED gboolean g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *timeval); #endif /* G_DISABLE_DEPRECATED */ /** * e_flag_new: (skip) * * Creates a new #EFlag object. It is initially unset. * * Returns: a new #EFlag * * Since: 1.12 **/ EFlag * e_flag_new (void) { EFlag *flag; flag = g_slice_new (EFlag); g_cond_init (&flag->cond); g_mutex_init (&flag->mutex); flag->is_set = FALSE; return flag; } /** * e_flag_is_set: (skip) * @flag: an #EFlag * * Returns the state of @flag. * * Returns: %TRUE if @flag is set * * Since: 1.12 **/ gboolean e_flag_is_set (EFlag *flag) { gboolean is_set; g_return_val_if_fail (flag != NULL, FALSE); g_mutex_lock (&flag->mutex); is_set = flag->is_set; g_mutex_unlock (&flag->mutex); return is_set; } /** * e_flag_set: (skip) * @flag: an #EFlag * * Sets @flag. All threads waiting on @flag are woken up. Threads that * call e_flag_wait() or e_flag_wait_until() once @flag is set will not * block at all. * * Since: 1.12 **/ void e_flag_set (EFlag *flag) { g_return_if_fail (flag != NULL); g_mutex_lock (&flag->mutex); flag->is_set = TRUE; g_cond_broadcast (&flag->cond); g_mutex_unlock (&flag->mutex); } /** * e_flag_clear: (skip) * @flag: an #EFlag * * Unsets @flag. Subsequent calls to e_flag_wait() or e_flag_wait_until() * will block until @flag is set. * * Since: 1.12 **/ void e_flag_clear (EFlag *flag) { g_return_if_fail (flag != NULL); g_mutex_lock (&flag->mutex); flag->is_set = FALSE; g_mutex_unlock (&flag->mutex); } /** * e_flag_wait: (skip) * @flag: an #EFlag * * Blocks until @flag is set. If @flag is already set, the function returns * immediately. * * Since: 1.12 **/ void e_flag_wait (EFlag *flag) { g_return_if_fail (flag != NULL); g_mutex_lock (&flag->mutex); while (!flag->is_set) g_cond_wait (&flag->cond, &flag->mutex); g_mutex_unlock (&flag->mutex); } /** * e_flag_timed_wait: (skip) * @flag: an #EFlag * @abs_time: (nullable): a #GTimeVal, determining the final time * * Blocks until @flag is set, or until the time specified by @abs_time. * If @flag is already set, the function returns immediately. The return * value indicates the state of @flag after waiting. * * If @abs_time is %NULL, e_flag_timed_wait() acts like e_flag_wait(). * * To easily calculate @abs_time, a combination of g_get_current_time() and * g_time_val_add() can be used. * * Returns: %TRUE if @flag is now set * * Since: 1.12 * * Deprecated: 3.8: Use e_flag_wait_until() instead. **/ G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean e_flag_timed_wait (EFlag *flag, GTimeVal *abs_time) { gboolean is_set; g_return_val_if_fail (flag != NULL, FALSE); g_mutex_lock (&flag->mutex); while (!flag->is_set) if (!g_cond_timed_wait (&flag->cond, &flag->mutex, abs_time)) break; is_set = flag->is_set; g_mutex_unlock (&flag->mutex); return is_set; } G_GNUC_END_IGNORE_DEPRECATIONS /** * e_flag_wait_until: (skip) * @flag: an #EFlag * @end_time: the monotonic time to wait until * * Blocks until @flag is set, or until the time specified by @end_time. * If @flag is already set, the function returns immediately. The return * value indicates the state of @flag after waiting. * * To easily calculate @end_time, a combination of g_get_monotonic_time() and * G_TIME_SPAN_SECOND macro. * * Returns: %TRUE if @flag is now set * * Since: 3.8 **/ gboolean e_flag_wait_until (EFlag *flag, gint64 end_time) { gboolean is_set; g_return_val_if_fail (flag != NULL, FALSE); g_mutex_lock (&flag->mutex); while (!flag->is_set) if (!g_cond_wait_until (&flag->cond, &flag->mutex, end_time)) break; is_set = flag->is_set; g_mutex_unlock (&flag->mutex); return is_set; } /** * e_flag_free: (skip) * @flag: an #EFlag * * Destroys @flag. * * Since: 1.12 **/ void e_flag_free (EFlag *flag) { g_return_if_fail (flag != NULL); /* Just to make sure that other threads are not holding the lock. */ g_mutex_lock (&flag->mutex); g_cond_clear (&flag->cond); g_mutex_unlock (&flag->mutex); g_mutex_clear (&flag->mutex); g_slice_free (EFlag, flag); }