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