OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright © 2007 Chris Wilson | 2 * Copyright © 2007 Chris Wilson |
3 * Copyright © 2009,2010 Red Hat, Inc. | 3 * Copyright © 2009,2010 Red Hat, Inc. |
4 * Copyright © 2011,2012 Google, Inc. | 4 * Copyright © 2011,2012 Google, Inc. |
5 * | 5 * |
6 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
7 * | 7 * |
8 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
9 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
10 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_I NVALID_VALUE; } | 61 inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_I NVALID_VALUE; } |
62 | 62 |
63 }; | 63 }; |
64 | 64 |
65 | 65 |
66 /* user_data */ | 66 /* user_data */ |
67 | 67 |
68 #define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} | 68 #define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} |
69 struct hb_user_data_array_t | 69 struct hb_user_data_array_t |
70 { | 70 { |
71 /* TODO Add tracing. */ | |
72 | |
73 struct hb_user_data_item_t { | 71 struct hb_user_data_item_t { |
74 hb_user_data_key_t *key; | 72 hb_user_data_key_t *key; |
75 void *data; | 73 void *data; |
76 hb_destroy_func_t destroy; | 74 hb_destroy_func_t destroy; |
77 | 75 |
78 inline bool operator == (hb_user_data_key_t *other_key) const { return key = = other_key; } | 76 inline bool operator == (hb_user_data_key_t *other_key) const { return key = = other_key; } |
79 inline bool operator == (hb_user_data_item_t &other) const { return key == o ther.key; } | 77 inline bool operator == (hb_user_data_item_t &other) const { return key == o ther.key; } |
80 | 78 |
81 void finish (void) { if (destroy) destroy (data); } | 79 void finish (void) { if (destroy) destroy (data); } |
82 }; | 80 }; |
(...skipping 16 matching lines...) Expand all Loading... | |
99 | 97 |
100 /* object_header */ | 98 /* object_header */ |
101 | 99 |
102 struct hb_object_header_t | 100 struct hb_object_header_t |
103 { | 101 { |
104 hb_reference_count_t ref_count; | 102 hb_reference_count_t ref_count; |
105 hb_user_data_array_t user_data; | 103 hb_user_data_array_t user_data; |
106 | 104 |
107 #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_ INIT} | 105 #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_ INIT} |
108 | 106 |
109 static inline void *create (unsigned int size) { | |
110 hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size); | |
111 | |
112 if (likely (obj)) | |
113 obj->init (); | |
114 | |
115 return obj; | |
116 } | |
117 | |
118 inline void init (void) { | |
119 ref_count.init (1); | |
120 user_data.init (); | |
121 } | |
122 | |
123 inline bool is_inert (void) const { | |
124 return unlikely (ref_count.is_invalid ()); | |
125 } | |
126 | |
127 inline void reference (void) { | |
128 if (unlikely (!this || this->is_inert ())) | |
129 return; | |
130 ref_count.inc (); | |
131 } | |
132 | |
133 inline bool destroy (void) { | |
134 if (unlikely (!this || this->is_inert ())) | |
135 return false; | |
136 if (ref_count.dec () != 1) | |
137 return false; | |
138 | |
139 ref_count.finish (); /* Do this before user_data */ | |
140 user_data.finish (); | |
141 | |
142 return true; | |
143 } | |
144 | |
145 inline bool set_user_data (hb_user_data_key_t *key, | |
146 void * data, | |
147 hb_destroy_func_t destroy_func, | |
148 hb_bool_t replace) { | |
149 if (unlikely (!this || this->is_inert ())) | |
150 return false; | |
151 | |
152 return user_data.set (key, data, destroy_func, replace); | |
153 } | |
154 | |
155 inline void *get_user_data (hb_user_data_key_t *key) { | |
156 if (unlikely (!this || this->is_inert ())) | |
157 return NULL; | |
158 | |
159 return user_data.get (key); | |
160 } | |
161 | |
162 inline void trace (const char *function) const { | |
163 if (unlikely (!this)) return; | |
164 /* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only | |
165 * prints the class name and throws away the template info. */ | |
166 DEBUG_MSG (OBJECT, (void *) this, | |
167 "%s refcount=%d", | |
168 function, | |
169 this ? ref_count.ref_count : 0); | |
170 } | |
171 | |
172 private: | 107 private: |
173 ASSERT_POD (); | 108 ASSERT_POD (); |
174 }; | 109 }; |
175 | 110 |
176 | 111 |
177 /* object */ | 112 /* object */ |
178 | 113 |
179 template <typename Type> | 114 template <typename Type> |
180 static inline void hb_object_trace (const Type *obj, const char *function) | 115 static inline void hb_object_trace (const Type *obj, const char *function) |
181 { | 116 { |
182 obj->header.trace (function); | 117 DEBUG_MSG (OBJECT, (void *) obj, |
118 » "%s refcount=%d", | |
Nico
2014/08/17 04:15:27
(looks like someone added tabs here, you might wan
| |
119 » function, | |
120 » obj ? obj->header.ref_count.ref_count : 0); | |
183 } | 121 } |
122 | |
184 template <typename Type> | 123 template <typename Type> |
185 static inline Type *hb_object_create (void) | 124 static inline Type *hb_object_create (void) |
186 { | 125 { |
187 Type *obj = (Type *) hb_object_header_t::create (sizeof (Type)); | 126 Type *obj = (Type *) calloc (1, sizeof (Type)); |
127 | |
128 if (unlikely (!obj)) | |
129 return obj; | |
130 | |
131 hb_object_init (obj); | |
188 hb_object_trace (obj, HB_FUNC); | 132 hb_object_trace (obj, HB_FUNC); |
189 return obj; | 133 return obj; |
190 } | 134 } |
191 template <typename Type> | 135 template <typename Type> |
136 static inline void hb_object_init (Type *obj) | |
137 { | |
138 obj->header.ref_count.init (1); | |
139 obj->header.user_data.init (); | |
140 } | |
141 template <typename Type> | |
192 static inline bool hb_object_is_inert (const Type *obj) | 142 static inline bool hb_object_is_inert (const Type *obj) |
193 { | 143 { |
194 return unlikely (obj->header.is_inert ()); | 144 return unlikely (obj->header.ref_count.is_invalid ()); |
195 } | 145 } |
196 template <typename Type> | 146 template <typename Type> |
197 static inline Type *hb_object_reference (Type *obj) | 147 static inline Type *hb_object_reference (Type *obj) |
198 { | 148 { |
199 hb_object_trace (obj, HB_FUNC); | 149 hb_object_trace (obj, HB_FUNC); |
200 obj->header.reference (); | 150 if (unlikely (!obj || hb_object_is_inert (obj))) |
151 return obj; | |
152 obj->header.ref_count.inc (); | |
201 return obj; | 153 return obj; |
202 } | 154 } |
203 template <typename Type> | 155 template <typename Type> |
204 static inline bool hb_object_destroy (Type *obj) | 156 static inline bool hb_object_destroy (Type *obj) |
205 { | 157 { |
206 hb_object_trace (obj, HB_FUNC); | 158 hb_object_trace (obj, HB_FUNC); |
207 return obj->header.destroy (); | 159 if (unlikely (!obj || hb_object_is_inert (obj))) |
160 return false; | |
161 if (obj->header.ref_count.dec () != 1) | |
162 return false; | |
163 | |
164 obj->header.ref_count.finish (); /* Do this before user_data */ | |
165 obj->header.user_data.finish (); | |
166 return true; | |
208 } | 167 } |
209 template <typename Type> | 168 template <typename Type> |
210 static inline bool hb_object_set_user_data (Type *obj, | 169 static inline bool hb_object_set_user_data (Type *obj, |
211 hb_user_data_key_t *key, | 170 hb_user_data_key_t *key, |
212 void * data, | 171 void * data, |
213 hb_destroy_func_t destroy, | 172 hb_destroy_func_t destroy, |
214 hb_bool_t replace) | 173 hb_bool_t replace) |
215 { | 174 { |
216 return obj->header.set_user_data (key, data, destroy, replace); | 175 if (unlikely (!obj || hb_object_is_inert (obj))) |
176 return false; | |
177 return obj->header.user_data.set (key, data, destroy, replace); | |
217 } | 178 } |
218 | 179 |
219 template <typename Type> | 180 template <typename Type> |
220 static inline void *hb_object_get_user_data (Type *obj, | 181 static inline void *hb_object_get_user_data (Type *obj, |
221 hb_user_data_key_t *key) | 182 hb_user_data_key_t *key) |
222 { | 183 { |
223 return obj->header.get_user_data (key); | 184 if (unlikely (!obj || hb_object_is_inert (obj))) |
185 return NULL; | |
186 return obj->header.user_data.get (key); | |
224 } | 187 } |
225 | 188 |
226 | 189 |
227 #endif /* HB_OBJECT_PRIVATE_HH */ | 190 #endif /* HB_OBJECT_PRIVATE_HH */ |
OLD | NEW |