1f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007  Chris Wilson
32409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009,2010  Red Hat, Inc.
4cdafe3a7d8483ac586e2c16487e2a09164e0f65cBehdad Esfahbod * Copyright © 2011,2012  Google, Inc.
5f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *
6c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
7f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *
8f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Permission is hereby granted, without written agreement and without
9f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
10f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * software and its documentation for any purpose, provided that the
11f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
12f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * all copies of this software.
13f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *
14f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DAMAGE.
19f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *
20f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *
26f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Contributor(s):
27f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod *	Chris Wilson <chris@chris-wilson.co.uk>
2835a7383c6138fd705560f0d4bb30659cbd1ab64cBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
292409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Google Author(s): Behdad Esfahbod
30f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod */
31f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod
32c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#ifndef HB_OBJECT_PRIVATE_HH
33c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#define HB_OBJECT_PRIVATE_HH
34f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod
35c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh"
3623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
37ec3ba4b96fc4f262db1ff9f906628c32f26c9b7dBehdad Esfahbod#include "hb-atomic-private.hh"
3845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod#include "hb-mutex-private.hh"
3945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod
40799b3c375ad0e1293fd37a0e3a0d422a3166dcd8Behdad Esfahbod
41863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod/* Debug */
42863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod
43863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod#ifndef HB_DEBUG_OBJECT
4411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_OBJECT (HB_DEBUG+0)
45863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod#endif
46863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod
47863df68e894b7644dcd12da88aa22f73edf829dcBehdad Esfahbod
48852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod/* reference_count */
4929c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
50326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod#define HB_REFERENCE_COUNT_INERT_VALUE -1
51326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
52326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)}
533f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt
5470600dbf626808a30fb0fd8b7ae860e64d9ffe87Behdad Esfahbodstruct hb_reference_count_t
5570600dbf626808a30fb0fd8b7ae860e64d9ffe87Behdad Esfahbod{
563b8fd9c48f4bde368bf2d465c148b9743a9216eeBehdad Esfahbod  hb_atomic_int_t ref_count;
5729c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
583f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt  inline void init (int v) { ref_count.set_unsafe (v); }
593f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
603f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt  inline int inc (void) { return ref_count.inc (); }
613f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt  inline int dec (void) { return ref_count.dec (); }
62326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
6329c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
64326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
65326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
6670600dbf626808a30fb0fd8b7ae860e64d9ffe87Behdad Esfahbod};
6729c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
6829c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
69852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod/* user_data */
7029c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
717babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
7270600dbf626808a30fb0fd8b7ae860e64d9ffe87Behdad Esfahbodstruct hb_user_data_array_t
7370600dbf626808a30fb0fd8b7ae860e64d9ffe87Behdad Esfahbod{
7421d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod  struct hb_user_data_item_t {
7521d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    hb_user_data_key_t *key;
7621d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    void *data;
7721d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    hb_destroy_func_t destroy;
78811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod
7921d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
8021d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
8129c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
8221d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod    void finish (void) { if (destroy) destroy (data); }
8321d2c92fdf7307c7117f8948021f0dd7d5a5d2a3Behdad Esfahbod  };
8429c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
857babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod  hb_mutex_t lock;
860e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
8729c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
887babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod  inline void init (void) { lock.init (); items.init (); }
89bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod
90218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod  HB_INTERNAL bool set (hb_user_data_key_t *key,
91218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod			void *              data,
9233ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod			hb_destroy_func_t   destroy,
937babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod			hb_bool_t           replace);
9429c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
957babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod  HB_INTERNAL void *get (hb_user_data_key_t *key);
9629c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
977babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod  inline void finish (void) { items.finish (lock); lock.finish (); }
9829c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod};
9929c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
10029c67d3f70b081766a6c01353980f457f38aeb12Behdad Esfahbod
1010d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod/* object_header */
1020d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1030d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbodstruct hb_object_header_t
1040d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod{
1050d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  hb_reference_count_t ref_count;
1060d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  hb_user_data_array_t user_data;
1070d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1083f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT}
1090d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1100d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  private:
1110d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  ASSERT_POD ();
1120d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod};
1130d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1140d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1159d861b81f349188a4507350398786a6e94038095Behdad Esfahbod/* object */
1169d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
1179d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1189d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline void hb_object_trace (const Type *obj, const char *function)
1199d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1200d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  DEBUG_MSG (OBJECT, (void *) obj,
1210d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod	     "%s refcount=%d",
1220d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod	     function,
1233f174cd020b7762fae96f20ce14fc9e9abec748fKonstantin Ritt	     obj ? obj->header.ref_count.get_unsafe () : 0);
1249d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1259d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
1269d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1279d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline Type *hb_object_create (void)
1289d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1299d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  Type *obj = (Type *) calloc (1, sizeof (Type));
1309d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
1319d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  if (unlikely (!obj))
1329d861b81f349188a4507350398786a6e94038095Behdad Esfahbod    return obj;
1339d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
1349d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  hb_object_init (obj);
1359d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  hb_object_trace (obj, HB_FUNC);
1369d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  return obj;
1379d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1389d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1399d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline void hb_object_init (Type *obj)
1409d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1410d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  obj->header.ref_count.init (1);
1420d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  obj->header.user_data.init ();
1439d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1449d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1459d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline bool hb_object_is_inert (const Type *obj)
1469d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
147326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  return unlikely (obj->header.ref_count.is_inert ());
148326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod}
149326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbodtemplate <typename Type>
150326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbodstatic inline bool hb_object_is_valid (const Type *obj)
151326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod{
152326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  return likely (obj->header.ref_count.is_valid ());
1539d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1549d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1559d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline Type *hb_object_reference (Type *obj)
1569d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1579d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  hb_object_trace (obj, HB_FUNC);
1580d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  if (unlikely (!obj || hb_object_is_inert (obj)))
1590d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod    return obj;
160326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  assert (hb_object_is_valid (obj));
1610d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  obj->header.ref_count.inc ();
1629d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  return obj;
1639d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1649d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1659d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline bool hb_object_destroy (Type *obj)
1669d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1679d861b81f349188a4507350398786a6e94038095Behdad Esfahbod  hb_object_trace (obj, HB_FUNC);
1680d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  if (unlikely (!obj || hb_object_is_inert (obj)))
1690d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod    return false;
170326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  assert (hb_object_is_valid (obj));
1710d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  if (obj->header.ref_count.dec () != 1)
1720d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod    return false;
1730d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod
1740d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  obj->header.ref_count.finish (); /* Do this before user_data */
1750d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  obj->header.user_data.finish ();
1760d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  return true;
1779d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1789d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1799d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline bool hb_object_set_user_data (Type               *obj,
1809d861b81f349188a4507350398786a6e94038095Behdad Esfahbod					    hb_user_data_key_t *key,
1819d861b81f349188a4507350398786a6e94038095Behdad Esfahbod					    void *              data,
1829d861b81f349188a4507350398786a6e94038095Behdad Esfahbod					    hb_destroy_func_t   destroy,
1839d861b81f349188a4507350398786a6e94038095Behdad Esfahbod					    hb_bool_t           replace)
1849d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1850d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  if (unlikely (!obj || hb_object_is_inert (obj)))
1869d861b81f349188a4507350398786a6e94038095Behdad Esfahbod    return false;
187326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  assert (hb_object_is_valid (obj));
1880d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  return obj->header.user_data.set (key, data, destroy, replace);
1899d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
1909d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
1919d861b81f349188a4507350398786a6e94038095Behdad Esfahbodtemplate <typename Type>
1929d861b81f349188a4507350398786a6e94038095Behdad Esfahbodstatic inline void *hb_object_get_user_data (Type               *obj,
1939d861b81f349188a4507350398786a6e94038095Behdad Esfahbod					     hb_user_data_key_t *key)
1949d861b81f349188a4507350398786a6e94038095Behdad Esfahbod{
1950d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  if (unlikely (!obj || hb_object_is_inert (obj)))
1969d861b81f349188a4507350398786a6e94038095Behdad Esfahbod    return NULL;
197326b5ebf5748f547e4eb7388d66b79fe23130e2aBehdad Esfahbod  assert (hb_object_is_valid (obj));
1980d2c2f238bf0a847ecd55a70cc0f081f18a053acBehdad Esfahbod  return obj->header.user_data.get (key);
1999d861b81f349188a4507350398786a6e94038095Behdad Esfahbod}
2009d861b81f349188a4507350398786a6e94038095Behdad Esfahbod
201ec6f9c2fd03a49d1e91cbaefa5bdbbfb35dff92eBehdad Esfahbod
202c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#endif /* HB_OBJECT_PRIVATE_HH */
203