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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/**
* \file ref.h
* Thread-safe reference counter.
*/
#ifndef REF_H
#define REF_H
#if __GNUC__ >= 4
# define REF_DECLARE() volatile int _ref
# define REF_INIT(ptr) \
((ptr)->_ref = 1)
# define REF_FREE(ptr)
# define REF_INC(ptr) \
__sync_add_and_fetch(&((ptr)->_ref), 1)
# define REF_DEC(ptr) \
(__sync_sub_and_fetch(&((ptr)->_ref), 1) <= 0)
#else
# warning Unsupported compiler, horrible fallback threadsafe reference counters
# include "thread.h"
/**
* Declare reference counter. Use in struct declaration.
*/
# define REF_DECLARE() int _ref; thread_lock_t* _reflock
/**
* Initialize reference counter. Must be first MACRO used.
* @param ptr pointer to the struct, may not be NULL
* @return false in case of allocation errors
*/
# define REF_INIT(ptr) \
_ref_init(&((ptr)->_ref), &((ptr)->_reflock))
/**
* Free reference counter.
* @param ptr pointer to the struct, may not be NULL
*/
# define REF_FREE(ptr) thread_lock_free((ptr)->_reflock)
/**
* Increase reference counter.
* @param ptr pointer to the struct, may not be NULL
*/
# define REF_INC(ptr) _ref_inc(&((ptr)->_ref), (ptr)->_reflock)
/**
* Decrease reference counter.
* @param ptr pointer to the struct, may not be NULL
* @return true if reference counter now is zero
*/
# define REF_DEC(ptr) _ref_dec(&((ptr)->_ref), (ptr)->_reflock)
/**
* Fallback implementation of REF_INIT.
* @param value pointer to reference counter, may not be NULL
* @param lock pointer to reference counter lock, may not be NULL
* @return true if both pointers was initialized correctly
*/
static inline NONULL bool _ref_init(int* value, thread_lock_t** lock)
{
assert(value);
assert(lock);
*value = 1;
*lock = thread_lock_new();
return *lock;
}
/**
* Fallback implementation of REF_INC.
* @param value pointer to reference counter, may not be NULL
* @param lock reference counter lock, may not be NULL
*/
static inline NONULL void _ref_inc(int* value, thread_lock_t* lock)
{
thread_lock_lock(lock);
(*value)++;
thread_lock_unlock(lock);
}
/**
* Fallback implementation of REF_DEC.
* @param value pointer to reference counter, may not be NULL
* @param lock reference counter lock, may not be NULL
* @return true if reference counter was decreased to 0
*/
static inline NONULL bool _ref_dec(int* value, thread_lock_t* lock)
{
bool ret;
thread_lock_lock(lock);
ret = --(*value) == 0;
thread_lock_unlock(lock);
return ret;
}
#endif
#endif /* REF_H */
|