00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2009 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 CU_SEMIWEAKPTR_H 00019 #define CU_SEMIWEAKPTR_H 00020 00021 #include <cu/memory.h> 00022 00023 CU_BEGIN_DECLARATIONS 00024 00025 void *cuP_weakptr_get_locked(void *link); 00026 00027 /** \defgroup cu_bistptr_h cu/bistptr.h: Bi-Strength Pointer 00028 ** @{ \ingroup cu_util_mod 00029 ** 00030 ** This header implements a discriminated union of a strong and a weak 00031 ** pointer, but with the restriction that all pointers stored must be even, 00032 ** e.g. due to alignment. 00033 ** 00034 ** \see cu_weakptr_h "cu/weakptr.h" */ 00035 00036 typedef struct { cu_hidden_ptr_t hptr; } cu_bistptr_t; 00037 00038 /** True iff \a bsp is a weak pointer. The \c NULL pointer counts as 00039 ** strong. */ 00040 CU_SINLINE cu_bool_t 00041 cu_bistptr_is_weak(cu_bistptr_t *bsp) 00042 { 00043 return (uintptr_t)bsp->hptr & 1; 00044 } 00045 00046 /** The complement of \ref cu_bistptr_is_weak, for symmetry. */ 00047 CU_SINLINE cu_bool_t 00048 cu_bistptr_is_strong(cu_bistptr_t *bsp) 00049 { 00050 return !cu_bistptr_is_weak(bsp); 00051 } 00052 00053 /** Returns the weak pointer held by \a bsp. 00054 ** \pre \ref cu_bistptr_is_weak(\a ptr) */ 00055 CU_SINLINE void * 00056 cu_bistptr_get_weak(cu_bistptr_t *bsp) 00057 { 00058 return GC_call_with_alloc_lock(cuP_weakptr_get_locked, bsp); 00059 } 00060 00061 /** Returns the strong pointer of \a bsp. 00062 ** \pre \ref cu_bistptr_is_strong(\a ptr) */ 00063 CU_SINLINE void * 00064 cu_bistptr_get_strong(cu_bistptr_t *bsp) 00065 { 00066 return (void *)bsp->hptr; 00067 } 00068 00069 /** Returns the pointer stored in \a bsp, independent of strength. */ 00070 CU_SINLINE void * 00071 cu_bistptr_get(cu_bistptr_t *bsp) 00072 { 00073 if (cu_bistptr_is_weak(bsp)) 00074 return cu_bistptr_get_weak(bsp); 00075 else 00076 return cu_bistptr_get_strong(bsp); 00077 } 00078 00079 /** Initialise \a bsp to a weak pointer to \a obj. 00080 ** 00081 ** \pre \a obj is aligned to an even address and points to or inside 00082 ** collectable memory. */ 00083 CU_SINLINE void 00084 cu_bistptr_init_weak(cu_bistptr_t *bsp, void *obj) 00085 { 00086 bsp->hptr = cu_hide_ptr(obj); 00087 GC_general_register_disappearing_link((void **)bsp, obj); 00088 } 00089 00090 /** Initialise \a bsp to a strong pointer to \a obj. 00091 ** 00092 ** \pre \a obj is aligned to an even address. */ 00093 CU_SINLINE void 00094 cu_bistptr_init_strong(cu_bistptr_t *bsp, void *obj) 00095 { 00096 bsp->hptr = (cu_hidden_ptr_t)obj; 00097 } 00098 00099 /** Deininialise \a bsp. If \a bsp holds a weak pointer, this unregisters 00100 ** the corresponding disappearing link. */ 00101 CU_SINLINE void 00102 cu_bistptr_deinit(cu_bistptr_t *bsp) 00103 { 00104 if (cu_bistptr_is_weak(bsp)) 00105 GC_unregister_disappearing_link((void **)&bsp->hptr); 00106 } 00107 00108 /** Reinitialise \a bsp to hold a weak pointer to \a obj. 00109 ** 00110 ** \pre \a obj is aligned to an even address and points to or inside 00111 ** collectable memory. */ 00112 CU_SINLINE void 00113 cu_bistptr_assign_weak(cu_bistptr_t *bsp, void *obj) 00114 { 00115 cu_bistptr_deinit(bsp); 00116 cu_bistptr_init_weak(bsp, obj); 00117 } 00118 00119 /** Reinitialise \a bsp to hold a strong pointer to \a obj. 00120 ** \pre \a obj is aligned to an even address. */ 00121 CU_SINLINE void 00122 cu_bistptr_assign_strong(cu_bistptr_t *bsp, void *obj) 00123 { 00124 cu_bistptr_deinit(bsp); 00125 bsp->hptr = (cu_hidden_ptr_t)obj; 00126 } 00127 00128 /** @} */ 00129 CU_END_DECLARATIONS 00130 00131 #endif