1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-object-private.hh Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,227 @@ 1.4 +/* 1.5 + * Copyright © 2007 Chris Wilson 1.6 + * Copyright © 2009,2010 Red Hat, Inc. 1.7 + * Copyright © 2011,2012 Google, Inc. 1.8 + * 1.9 + * This is part of HarfBuzz, a text shaping library. 1.10 + * 1.11 + * Permission is hereby granted, without written agreement and without 1.12 + * license or royalty fees, to use, copy, modify, and distribute this 1.13 + * software and its documentation for any purpose, provided that the 1.14 + * above copyright notice and the following two paragraphs appear in 1.15 + * all copies of this software. 1.16 + * 1.17 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1.18 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1.19 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1.20 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1.21 + * DAMAGE. 1.22 + * 1.23 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1.24 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.25 + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 1.26 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 1.27 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 1.28 + * 1.29 + * Contributor(s): 1.30 + * Chris Wilson <chris@chris-wilson.co.uk> 1.31 + * Red Hat Author(s): Behdad Esfahbod 1.32 + * Google Author(s): Behdad Esfahbod 1.33 + */ 1.34 + 1.35 +#ifndef HB_OBJECT_PRIVATE_HH 1.36 +#define HB_OBJECT_PRIVATE_HH 1.37 + 1.38 +#include "hb-private.hh" 1.39 + 1.40 +#include "hb-atomic-private.hh" 1.41 +#include "hb-mutex-private.hh" 1.42 + 1.43 + 1.44 +/* Debug */ 1.45 + 1.46 +#ifndef HB_DEBUG_OBJECT 1.47 +#define HB_DEBUG_OBJECT (HB_DEBUG+0) 1.48 +#endif 1.49 + 1.50 + 1.51 +/* reference_count */ 1.52 + 1.53 +#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) 1.54 +#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} 1.55 +struct hb_reference_count_t 1.56 +{ 1.57 + hb_atomic_int_t ref_count; 1.58 + 1.59 + inline void init (int v) { ref_count = v; } 1.60 + inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), 1); } 1.61 + inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); } 1.62 + inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } 1.63 + 1.64 + inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; } 1.65 + 1.66 +}; 1.67 + 1.68 + 1.69 +/* user_data */ 1.70 + 1.71 +#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} 1.72 +struct hb_user_data_array_t 1.73 +{ 1.74 + /* TODO Add tracing. */ 1.75 + 1.76 + struct hb_user_data_item_t { 1.77 + hb_user_data_key_t *key; 1.78 + void *data; 1.79 + hb_destroy_func_t destroy; 1.80 + 1.81 + inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; } 1.82 + inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; } 1.83 + 1.84 + void finish (void) { if (destroy) destroy (data); } 1.85 + }; 1.86 + 1.87 + hb_mutex_t lock; 1.88 + hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items; 1.89 + 1.90 + inline void init (void) { lock.init (); items.init (); } 1.91 + 1.92 + HB_INTERNAL bool set (hb_user_data_key_t *key, 1.93 + void * data, 1.94 + hb_destroy_func_t destroy, 1.95 + hb_bool_t replace); 1.96 + 1.97 + HB_INTERNAL void *get (hb_user_data_key_t *key); 1.98 + 1.99 + inline void finish (void) { items.finish (lock); lock.finish (); } 1.100 +}; 1.101 + 1.102 + 1.103 +/* object_header */ 1.104 + 1.105 +struct hb_object_header_t 1.106 +{ 1.107 + hb_reference_count_t ref_count; 1.108 + hb_user_data_array_t user_data; 1.109 + 1.110 +#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} 1.111 + 1.112 + static inline void *create (unsigned int size) { 1.113 + hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size); 1.114 + 1.115 + if (likely (obj)) 1.116 + obj->init (); 1.117 + 1.118 + return obj; 1.119 + } 1.120 + 1.121 + inline void init (void) { 1.122 + ref_count.init (1); 1.123 + user_data.init (); 1.124 + } 1.125 + 1.126 + inline bool is_inert (void) const { 1.127 + return unlikely (ref_count.is_invalid ()); 1.128 + } 1.129 + 1.130 + inline void reference (void) { 1.131 + if (unlikely (!this || this->is_inert ())) 1.132 + return; 1.133 + ref_count.inc (); 1.134 + } 1.135 + 1.136 + inline bool destroy (void) { 1.137 + if (unlikely (!this || this->is_inert ())) 1.138 + return false; 1.139 + if (ref_count.dec () != 1) 1.140 + return false; 1.141 + 1.142 + ref_count.finish (); /* Do this before user_data */ 1.143 + user_data.finish (); 1.144 + 1.145 + return true; 1.146 + } 1.147 + 1.148 + inline bool set_user_data (hb_user_data_key_t *key, 1.149 + void * data, 1.150 + hb_destroy_func_t destroy_func, 1.151 + hb_bool_t replace) { 1.152 + if (unlikely (!this || this->is_inert ())) 1.153 + return false; 1.154 + 1.155 + return user_data.set (key, data, destroy_func, replace); 1.156 + } 1.157 + 1.158 + inline void *get_user_data (hb_user_data_key_t *key) { 1.159 + if (unlikely (!this || this->is_inert ())) 1.160 + return NULL; 1.161 + 1.162 + return user_data.get (key); 1.163 + } 1.164 + 1.165 + inline void trace (const char *function) const { 1.166 + if (unlikely (!this)) return; 1.167 + /* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only 1.168 + * prints the class name and throws away the template info. */ 1.169 + DEBUG_MSG (OBJECT, (void *) this, 1.170 + "%s refcount=%d", 1.171 + function, 1.172 + this ? ref_count.ref_count : 0); 1.173 + } 1.174 + 1.175 + private: 1.176 + ASSERT_POD (); 1.177 +}; 1.178 + 1.179 + 1.180 +/* object */ 1.181 + 1.182 +template <typename Type> 1.183 +static inline void hb_object_trace (const Type *obj, const char *function) 1.184 +{ 1.185 + obj->header.trace (function); 1.186 +} 1.187 +template <typename Type> 1.188 +static inline Type *hb_object_create (void) 1.189 +{ 1.190 + Type *obj = (Type *) hb_object_header_t::create (sizeof (Type)); 1.191 + hb_object_trace (obj, HB_FUNC); 1.192 + return obj; 1.193 +} 1.194 +template <typename Type> 1.195 +static inline bool hb_object_is_inert (const Type *obj) 1.196 +{ 1.197 + return unlikely (obj->header.is_inert ()); 1.198 +} 1.199 +template <typename Type> 1.200 +static inline Type *hb_object_reference (Type *obj) 1.201 +{ 1.202 + hb_object_trace (obj, HB_FUNC); 1.203 + obj->header.reference (); 1.204 + return obj; 1.205 +} 1.206 +template <typename Type> 1.207 +static inline bool hb_object_destroy (Type *obj) 1.208 +{ 1.209 + hb_object_trace (obj, HB_FUNC); 1.210 + return obj->header.destroy (); 1.211 +} 1.212 +template <typename Type> 1.213 +static inline bool hb_object_set_user_data (Type *obj, 1.214 + hb_user_data_key_t *key, 1.215 + void * data, 1.216 + hb_destroy_func_t destroy, 1.217 + hb_bool_t replace) 1.218 +{ 1.219 + return obj->header.set_user_data (key, data, destroy, replace); 1.220 +} 1.221 + 1.222 +template <typename Type> 1.223 +static inline void *hb_object_get_user_data (Type *obj, 1.224 + hb_user_data_key_t *key) 1.225 +{ 1.226 + return obj->header.get_user_data (key); 1.227 +} 1.228 + 1.229 + 1.230 +#endif /* HB_OBJECT_PRIVATE_HH */