Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright © 2007 Chris Wilson |
michael@0 | 3 | * Copyright © 2009,2010 Red Hat, Inc. |
michael@0 | 4 | * Copyright © 2011,2012 Google, Inc. |
michael@0 | 5 | * |
michael@0 | 6 | * This is part of HarfBuzz, a text shaping library. |
michael@0 | 7 | * |
michael@0 | 8 | * Permission is hereby granted, without written agreement and without |
michael@0 | 9 | * license or royalty fees, to use, copy, modify, and distribute this |
michael@0 | 10 | * software and its documentation for any purpose, provided that the |
michael@0 | 11 | * above copyright notice and the following two paragraphs appear in |
michael@0 | 12 | * all copies of this software. |
michael@0 | 13 | * |
michael@0 | 14 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
michael@0 | 15 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
michael@0 | 16 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
michael@0 | 17 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
michael@0 | 18 | * DAMAGE. |
michael@0 | 19 | * |
michael@0 | 20 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
michael@0 | 21 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
michael@0 | 22 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
michael@0 | 23 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
michael@0 | 24 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
michael@0 | 25 | * |
michael@0 | 26 | * Contributor(s): |
michael@0 | 27 | * Chris Wilson <chris@chris-wilson.co.uk> |
michael@0 | 28 | * Red Hat Author(s): Behdad Esfahbod |
michael@0 | 29 | * Google Author(s): Behdad Esfahbod |
michael@0 | 30 | */ |
michael@0 | 31 | |
michael@0 | 32 | #ifndef HB_OBJECT_PRIVATE_HH |
michael@0 | 33 | #define HB_OBJECT_PRIVATE_HH |
michael@0 | 34 | |
michael@0 | 35 | #include "hb-private.hh" |
michael@0 | 36 | |
michael@0 | 37 | #include "hb-atomic-private.hh" |
michael@0 | 38 | #include "hb-mutex-private.hh" |
michael@0 | 39 | |
michael@0 | 40 | |
michael@0 | 41 | /* Debug */ |
michael@0 | 42 | |
michael@0 | 43 | #ifndef HB_DEBUG_OBJECT |
michael@0 | 44 | #define HB_DEBUG_OBJECT (HB_DEBUG+0) |
michael@0 | 45 | #endif |
michael@0 | 46 | |
michael@0 | 47 | |
michael@0 | 48 | /* reference_count */ |
michael@0 | 49 | |
michael@0 | 50 | #define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) |
michael@0 | 51 | #define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} |
michael@0 | 52 | struct hb_reference_count_t |
michael@0 | 53 | { |
michael@0 | 54 | hb_atomic_int_t ref_count; |
michael@0 | 55 | |
michael@0 | 56 | inline void init (int v) { ref_count = v; } |
michael@0 | 57 | inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), 1); } |
michael@0 | 58 | inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); } |
michael@0 | 59 | inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } |
michael@0 | 60 | |
michael@0 | 61 | inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; } |
michael@0 | 62 | |
michael@0 | 63 | }; |
michael@0 | 64 | |
michael@0 | 65 | |
michael@0 | 66 | /* user_data */ |
michael@0 | 67 | |
michael@0 | 68 | #define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} |
michael@0 | 69 | struct hb_user_data_array_t |
michael@0 | 70 | { |
michael@0 | 71 | /* TODO Add tracing. */ |
michael@0 | 72 | |
michael@0 | 73 | struct hb_user_data_item_t { |
michael@0 | 74 | hb_user_data_key_t *key; |
michael@0 | 75 | void *data; |
michael@0 | 76 | hb_destroy_func_t destroy; |
michael@0 | 77 | |
michael@0 | 78 | inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; } |
michael@0 | 79 | inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; } |
michael@0 | 80 | |
michael@0 | 81 | void finish (void) { if (destroy) destroy (data); } |
michael@0 | 82 | }; |
michael@0 | 83 | |
michael@0 | 84 | hb_mutex_t lock; |
michael@0 | 85 | hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items; |
michael@0 | 86 | |
michael@0 | 87 | inline void init (void) { lock.init (); items.init (); } |
michael@0 | 88 | |
michael@0 | 89 | HB_INTERNAL bool set (hb_user_data_key_t *key, |
michael@0 | 90 | void * data, |
michael@0 | 91 | hb_destroy_func_t destroy, |
michael@0 | 92 | hb_bool_t replace); |
michael@0 | 93 | |
michael@0 | 94 | HB_INTERNAL void *get (hb_user_data_key_t *key); |
michael@0 | 95 | |
michael@0 | 96 | inline void finish (void) { items.finish (lock); lock.finish (); } |
michael@0 | 97 | }; |
michael@0 | 98 | |
michael@0 | 99 | |
michael@0 | 100 | /* object_header */ |
michael@0 | 101 | |
michael@0 | 102 | struct hb_object_header_t |
michael@0 | 103 | { |
michael@0 | 104 | hb_reference_count_t ref_count; |
michael@0 | 105 | hb_user_data_array_t user_data; |
michael@0 | 106 | |
michael@0 | 107 | #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} |
michael@0 | 108 | |
michael@0 | 109 | static inline void *create (unsigned int size) { |
michael@0 | 110 | hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size); |
michael@0 | 111 | |
michael@0 | 112 | if (likely (obj)) |
michael@0 | 113 | obj->init (); |
michael@0 | 114 | |
michael@0 | 115 | return obj; |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | inline void init (void) { |
michael@0 | 119 | ref_count.init (1); |
michael@0 | 120 | user_data.init (); |
michael@0 | 121 | } |
michael@0 | 122 | |
michael@0 | 123 | inline bool is_inert (void) const { |
michael@0 | 124 | return unlikely (ref_count.is_invalid ()); |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | inline void reference (void) { |
michael@0 | 128 | if (unlikely (!this || this->is_inert ())) |
michael@0 | 129 | return; |
michael@0 | 130 | ref_count.inc (); |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | inline bool destroy (void) { |
michael@0 | 134 | if (unlikely (!this || this->is_inert ())) |
michael@0 | 135 | return false; |
michael@0 | 136 | if (ref_count.dec () != 1) |
michael@0 | 137 | return false; |
michael@0 | 138 | |
michael@0 | 139 | ref_count.finish (); /* Do this before user_data */ |
michael@0 | 140 | user_data.finish (); |
michael@0 | 141 | |
michael@0 | 142 | return true; |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | inline bool set_user_data (hb_user_data_key_t *key, |
michael@0 | 146 | void * data, |
michael@0 | 147 | hb_destroy_func_t destroy_func, |
michael@0 | 148 | hb_bool_t replace) { |
michael@0 | 149 | if (unlikely (!this || this->is_inert ())) |
michael@0 | 150 | return false; |
michael@0 | 151 | |
michael@0 | 152 | return user_data.set (key, data, destroy_func, replace); |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | inline void *get_user_data (hb_user_data_key_t *key) { |
michael@0 | 156 | if (unlikely (!this || this->is_inert ())) |
michael@0 | 157 | return NULL; |
michael@0 | 158 | |
michael@0 | 159 | return user_data.get (key); |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | inline void trace (const char *function) const { |
michael@0 | 163 | if (unlikely (!this)) return; |
michael@0 | 164 | /* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only |
michael@0 | 165 | * prints the class name and throws away the template info. */ |
michael@0 | 166 | DEBUG_MSG (OBJECT, (void *) this, |
michael@0 | 167 | "%s refcount=%d", |
michael@0 | 168 | function, |
michael@0 | 169 | this ? ref_count.ref_count : 0); |
michael@0 | 170 | } |
michael@0 | 171 | |
michael@0 | 172 | private: |
michael@0 | 173 | ASSERT_POD (); |
michael@0 | 174 | }; |
michael@0 | 175 | |
michael@0 | 176 | |
michael@0 | 177 | /* object */ |
michael@0 | 178 | |
michael@0 | 179 | template <typename Type> |
michael@0 | 180 | static inline void hb_object_trace (const Type *obj, const char *function) |
michael@0 | 181 | { |
michael@0 | 182 | obj->header.trace (function); |
michael@0 | 183 | } |
michael@0 | 184 | template <typename Type> |
michael@0 | 185 | static inline Type *hb_object_create (void) |
michael@0 | 186 | { |
michael@0 | 187 | Type *obj = (Type *) hb_object_header_t::create (sizeof (Type)); |
michael@0 | 188 | hb_object_trace (obj, HB_FUNC); |
michael@0 | 189 | return obj; |
michael@0 | 190 | } |
michael@0 | 191 | template <typename Type> |
michael@0 | 192 | static inline bool hb_object_is_inert (const Type *obj) |
michael@0 | 193 | { |
michael@0 | 194 | return unlikely (obj->header.is_inert ()); |
michael@0 | 195 | } |
michael@0 | 196 | template <typename Type> |
michael@0 | 197 | static inline Type *hb_object_reference (Type *obj) |
michael@0 | 198 | { |
michael@0 | 199 | hb_object_trace (obj, HB_FUNC); |
michael@0 | 200 | obj->header.reference (); |
michael@0 | 201 | return obj; |
michael@0 | 202 | } |
michael@0 | 203 | template <typename Type> |
michael@0 | 204 | static inline bool hb_object_destroy (Type *obj) |
michael@0 | 205 | { |
michael@0 | 206 | hb_object_trace (obj, HB_FUNC); |
michael@0 | 207 | return obj->header.destroy (); |
michael@0 | 208 | } |
michael@0 | 209 | template <typename Type> |
michael@0 | 210 | static inline bool hb_object_set_user_data (Type *obj, |
michael@0 | 211 | hb_user_data_key_t *key, |
michael@0 | 212 | void * data, |
michael@0 | 213 | hb_destroy_func_t destroy, |
michael@0 | 214 | hb_bool_t replace) |
michael@0 | 215 | { |
michael@0 | 216 | return obj->header.set_user_data (key, data, destroy, replace); |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | template <typename Type> |
michael@0 | 220 | static inline void *hb_object_get_user_data (Type *obj, |
michael@0 | 221 | hb_user_data_key_t *key) |
michael@0 | 222 | { |
michael@0 | 223 | return obj->header.get_user_data (key); |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | |
michael@0 | 227 | #endif /* HB_OBJECT_PRIVATE_HH */ |