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_
|