-
Notifications
You must be signed in to change notification settings - Fork 118
/
lock.h
114 lines (100 loc) · 2.91 KB
/
lock.h
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* libobjc requires recursive mutexes. These are delegated to the underlying
* threading implementation. This file contains a VERY thin wrapper over the
* Windows and POSIX mutex APIs.
*/
#ifndef __LIBOBJC_LOCK_H_INCLUDED__
#define __LIBOBJC_LOCK_H_INCLUDED__
#ifdef _WIN32
# include "safewindows.h"
typedef CRITICAL_SECTION mutex_t;
# define INIT_LOCK(x) InitializeCriticalSection(&(x))
# define LOCK(x) EnterCriticalSection(x)
# define UNLOCK(x) LeaveCriticalSection(x)
# define DESTROY_LOCK(x) DeleteCriticalSection(x)
#else
# include <pthread.h>
typedef pthread_mutex_t mutex_t;
// If this pthread implementation has a static initializer for recursive
// mutexes, use that, otherwise fall back to the portable version
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
# define INIT_LOCK(x) x = (pthread_mutex_t)PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
# elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
# define INIT_LOCK(x) x = (pthread_mutex_t)PTHREAD_RECURSIVE_MUTEX_INITIALIZER
# else
# define INIT_LOCK(x) init_recursive_mutex(&(x))
static inline void init_recursive_mutex(pthread_mutex_t *x)
{
pthread_mutexattr_t recursiveAttributes;
pthread_mutexattr_init(&recursiveAttributes);
pthread_mutexattr_settype(&recursiveAttributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(x, &recursiveAttributes);
pthread_mutexattr_destroy(&recursiveAttributes);
}
# endif
# define LOCK(x) pthread_mutex_lock(x)
# define UNLOCK(x) pthread_mutex_unlock(x)
# define DESTROY_LOCK(x) pthread_mutex_destroy(x)
#endif
__attribute__((unused)) static void objc_release_lock(void *x)
{
mutex_t *lock = *(mutex_t**)x;
UNLOCK(lock);
}
/**
* Concatenate strings during macro expansion.
*/
#define LOCK_HOLDERN_NAME_CAT(x, y) x ## y
/**
* Concatenate string with unique variable during macro expansion.
*/
#define LOCK_HOLDER_NAME_COUNTER(x, y) LOCK_HOLDERN_NAME_CAT(x, y)
/**
* Create a unique name for a lock holder variable
*/
#define LOCK_HOLDER_NAME(x) LOCK_HOLDER_NAME_COUNTER(x, __COUNTER__)
/**
* Acquires the lock and automatically releases it at the end of the current
* scope.
*/
#define LOCK_FOR_SCOPE(lock) \
__attribute__((cleanup(objc_release_lock)))\
__attribute__((unused)) mutex_t *LOCK_HOLDER_NAME(lock_pointer) = lock;\
LOCK(lock)
/**
* The global runtime mutex.
*/
extern mutex_t runtime_mutex;
#define LOCK_RUNTIME() LOCK(&runtime_mutex)
#define UNLOCK_RUNTIME() UNLOCK(&runtime_mutex)
#define LOCK_RUNTIME_FOR_SCOPE() LOCK_FOR_SCOPE(&runtime_mutex)
#ifdef __cplusplus
/**
* C++ wrapper around our mutex, for use with std::lock_guard and friends.
*/
class RecursiveMutex
{
/// The underlying mutex
mutex_t mutex;
public:
/**
* Explicit initialisation of the underlying lock, so that this can be a
* global.
*/
void init()
{
INIT_LOCK(mutex);
}
/// Acquire the lock.
void lock()
{
LOCK(&mutex);
}
/// Release the lock.
void unlock()
{
UNLOCK(&mutex);
}
};
#endif
#endif // __LIBOBJC_LOCK_H_INCLUDED__