summaryrefslogtreecommitdiff
path: root/upb/refcount.h
blob: cb2bda9aa5aa156f678d1654205504a53ab565e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * upb - a minimalist implementation of protocol buffers.
 *
 * Copyright (c) 2009 Google Inc.  See LICENSE for details.
 * Author: Josh Haberman <jhaberman@gmail.com>
 *
 * A thread-safe refcount that can optionally track references for debugging
 * purposes.  It helps avoid circular references by allowing a
 * strongly-connected component in the graph to share a refcount.
 *
 * This interface is internal to upb.
 */

#ifndef UPB_REFCOUNT_H_
#define UPB_REFCOUNT_H_

#include <stdbool.h>
#include <stdint.h>
#include "upb/table.h"

#ifndef NDEBUG
#define UPB_DEBUG_REFS
#endif

typedef struct _upb_refcount {
  uint32_t *count;
  struct _upb_refcount *next;  // Circularly-linked list of this SCC.
  uint16_t index;    // For SCC algorithm.
  uint16_t lowlink;  // For SCC algorithm.
#ifdef UPB_DEBUG_REFS
  upb_inttable refs;
#endif
} upb_refcount;

// NON THREAD SAFE operations //////////////////////////////////////////////////

// Initializes the refcount with a single ref for the given owner.  Returns
// NULL if memory could not be allocated.
bool upb_refcount_init(upb_refcount *r, void *owner);

// Uninitializes the refcount.  May only be called after unref() returns true.
void upb_refcount_uninit(upb_refcount *r);

// Moves an existing ref from ref_donor to new_owner, without changing the
// overall ref count.
void upb_refcount_donateref(upb_refcount *r, void *from, void *to);

// Finds strongly-connected components among some set of objects and merges all
// refcounts that share a SCC.  The given function will be called when the
// algorithm needs to visit children of a particular object; the function
// should call upb_refcount_visit() once for each child obj.
//
// Returns false if memory allocation failed.
typedef void upb_getsuccessors(upb_refcount *obj, void*);
bool upb_refcount_findscc(upb_refcount **objs, int n, upb_getsuccessors *func);
void upb_refcount_visit(upb_refcount *obj, upb_refcount *subobj, void *closure);

// Thread-safe operations //////////////////////////////////////////////////////

// Increases the ref count, the new ref is owned by "owner" which must not
// already own a ref.  Circular reference chains are not allowed.
void upb_refcount_ref(upb_refcount *r, void *owner);

// Release a ref owned by owner, returns true if that was the last ref.
bool upb_refcount_unref(upb_refcount *r, void *owner);

// Returns true if these two objects share a refcount.
bool upb_refcount_merged(const upb_refcount *r, const upb_refcount *r2);

#endif  // UPB_REFCOUNT_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback