hb-object-private.hh revision 24229eb13268a422efffbcb28a094b726824c7f0
1/* 2 * Copyright (C) 2007 Chris Wilson 3 * Copyright (C) 2009,2010 Red Hat, Inc. 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Contributor(s): 26 * Chris Wilson <chris@chris-wilson.co.uk> 27 * Red Hat Author(s): Behdad Esfahbod 28 */ 29 30#ifndef HB_OBJECT_PRIVATE_HH 31#define HB_OBJECT_PRIVATE_HH 32 33#include "hb-private.hh" 34 35HB_BEGIN_DECLS 36 37 38typedef struct { 39 hb_atomic_int_t ref_count; 40 41#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) 42#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} 43 44 inline void init (int v) { ref_count = v; /* non-atomic is fine */ } 45 inline int inc (void) { return hb_atomic_int_fetch_and_add (ref_count, 1); } 46 inline int dec (void) { return hb_atomic_int_fetch_and_add (ref_count, -1); } 47 inline void set (int v) { return hb_atomic_int_set (ref_count, v); } 48 49 inline int get (void) const { return hb_atomic_int_get (ref_count); } 50 inline bool is_invalid (void) const { return get () == HB_REFERENCE_COUNT_INVALID_VALUE; } 51 52} hb_reference_count_t; 53 54 55 56/* Debug */ 57 58#ifndef HB_DEBUG_OBJECT 59#define HB_DEBUG_OBJECT (HB_DEBUG+0) 60#endif 61 62static inline void 63_hb_trace_object (const void *obj, 64 hb_reference_count_t *ref_count, 65 const char *function) 66{ 67 (void) (HB_DEBUG_OBJECT && 68 fprintf (stderr, "OBJECT(%p) refcount=%d %s\n", 69 obj, 70 ref_count->get (), 71 function)); 72} 73 74#define TRACE_OBJECT(obj) _hb_trace_object (obj, &obj->ref_count, __FUNCTION__) 75 76 77 78/* Object allocation and lifecycle manamgement macros */ 79 80#define HB_OBJECT_IS_INERT(obj) \ 81 (unlikely ((obj)->ref_count.is_invalid ())) 82 83#define HB_OBJECT_DO_INIT_EXPR(obj) \ 84 obj->ref_count.init (1) 85 86#define HB_OBJECT_DO_INIT(obj) \ 87 HB_STMT_START { \ 88 HB_OBJECT_DO_INIT_EXPR (obj); \ 89 } HB_STMT_END 90 91#define HB_OBJECT_DO_CREATE(Type, obj) \ 92 likely (( \ 93 (void) ( \ 94 ((obj) = (Type *) calloc (1, sizeof (Type))) && \ 95 ( \ 96 HB_OBJECT_DO_INIT_EXPR (obj), \ 97 TRACE_OBJECT (obj), \ 98 TRUE \ 99 ) \ 100 ), \ 101 (obj) \ 102 )) 103 104#define HB_OBJECT_DO_REFERENCE(obj) \ 105 HB_STMT_START { \ 106 int old_count; \ 107 if (unlikely (!(obj) || HB_OBJECT_IS_INERT (obj))) \ 108 return obj; \ 109 TRACE_OBJECT (obj); \ 110 old_count = obj->ref_count.inc (); \ 111 assert (old_count > 0); \ 112 return obj; \ 113 } HB_STMT_END 114 115#define HB_OBJECT_DO_DESTROY(obj) \ 116 HB_STMT_START { \ 117 int old_count; \ 118 if (unlikely (!(obj) || HB_OBJECT_IS_INERT (obj))) \ 119 return; \ 120 TRACE_OBJECT (obj); \ 121 old_count = obj->ref_count.dec (); \ 122 assert (old_count > 0); \ 123 if (old_count != 1) \ 124 return; \ 125 } HB_STMT_END 126 127 128HB_END_DECLS 129 130#endif /* HB_OBJECT_PRIVATE_HH */ 131