00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2007 Petter Urkedal <urkedal@nbi.dk> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CUFLOW_CDISJ_H 00019 #define CUFLOW_CDISJ_H 00020 00021 #include <cuflow/fwd.h> 00022 #include <atomic_ops.h> 00023 00024 CU_BEGIN_DECLARATIONS 00025 /** \defgroup cuflow_cdisj_h cuflow/cdisj.h: Inter-Thread Conditionals 00026 ** @{ \ingroup cuflow_smp_mod */ 00027 00028 /** Type used to maintain a disjunction of several conditions across threads. 00029 ** This is a simple atomic integer with a special interpretation. Typically a 00030 ** non-zero value means that work scheduled by the current thread is not yet 00031 ** completed. */ 00032 typedef AO_t cuflow_cdisj_t; 00033 00034 #ifndef CU_IN_DOXYGEN 00035 void cuflowP_cdisj_wait_while(cuflow_cdisj_t *, cu_bool_t cond_val); 00036 void cuflowP_cdisj_broadcast(cuflow_cdisj_t *); 00037 #endif 00038 00039 /** Waits while \c *\a cdisj is non-zero, tending to scheduled work if the 00040 ** condition is not fulfilled. */ 00041 CU_SINLINE void 00042 cuflow_cdisj_wait_while(cuflow_cdisj_t *cdisj) 00043 { 00044 if (AO_load(cdisj)) 00045 cuflowP_cdisj_wait_while(cdisj, cu_false); 00046 } 00047 00048 /** Waits until \c *\a cdisj becomes non-zero, tending to scheduled work if the 00049 ** condition is not fulfilled */ 00050 CU_SINLINE void 00051 cuflow_cdisj_wait_until(cuflow_cdisj_t *cdisj) 00052 { 00053 if (AO_load(cdisj)) 00054 cuflowP_cdisj_wait_while(cdisj, cu_true); 00055 } 00056 00057 /** Decrements \c *\a cdisj and if it becomes zero, broadcasts to other threads 00058 ** possibly waiting for \a cdisj to become zero. */ 00059 CU_SINLINE void 00060 cuflow_cdisj_sub1(cuflow_cdisj_t *cdisj) 00061 { 00062 if (AO_fetch_and_sub1(cdisj) == 1) 00063 cuflowP_cdisj_broadcast(cdisj); 00064 } 00065 00066 /** A variant of \ref cuflow_cdisj_sub1 which release barrier (cf 00067 ** AO_fetch_and_sub1_release). */ 00068 CU_SINLINE void 00069 cuflow_cdisj_sub1_release(cuflow_cdisj_t *cdisj) 00070 { 00071 if (AO_fetch_and_sub1_release(cdisj) == 1) 00072 cuflowP_cdisj_broadcast(cdisj); 00073 } 00074 00075 /** A variant of \ref cuflow_cdisj_sub1 with write-release barrier (cf 00076 ** AO_fetch_and_sub1_release_write). */ 00077 CU_SINLINE void 00078 cuflow_cdisj_sub1_release_write(cuflow_cdisj_t *cdisj) 00079 { 00080 if (AO_fetch_and_sub1_release_write(cdisj) == 1) 00081 cuflowP_cdisj_broadcast(cdisj); 00082 } 00083 00084 /** @} */ 00085 CU_END_DECLARATIONS 00086 00087 #endif