]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
12471842 PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
12c86877 BH |
22 | #ifndef LOCK_HH |
23 | #define LOCK_HH | |
24 | ||
25 | #include <pthread.h> | |
26 | #include <errno.h> | |
27 | #include "misc.hh" | |
5c409fa2 | 28 | #include "pdnsexception.hh" |
76698c6e BH |
29 | |
30 | extern bool g_singleThreaded; | |
31 | ||
12c86877 BH |
32 | class Lock |
33 | { | |
34 | pthread_mutex_t *d_lock; | |
35 | public: | |
2be43892 | 36 | Lock(const Lock& rhs) = delete; |
37 | Lock& operator=(const Lock& rhs) = delete; | |
12c86877 BH |
38 | |
39 | Lock(pthread_mutex_t *lock) : d_lock(lock) | |
40 | { | |
76698c6e BH |
41 | if(g_singleThreaded) |
42 | return; | |
d90dad50 RG |
43 | |
44 | int err; | |
45 | if((err = pthread_mutex_lock(d_lock))) { | |
46 | errno = err; | |
3f81d239 | 47 | throw PDNSException("error acquiring lock: "+stringerror()); |
d90dad50 | 48 | } |
12c86877 BH |
49 | } |
50 | ~Lock() | |
51 | { | |
76698c6e BH |
52 | if(g_singleThreaded) |
53 | return; | |
54 | ||
12c86877 BH |
55 | pthread_mutex_unlock(d_lock); |
56 | } | |
57 | }; | |
58 | ||
59 | class WriteLock | |
60 | { | |
61 | pthread_rwlock_t *d_lock; | |
62 | public: | |
63 | ||
64 | WriteLock(pthread_rwlock_t *lock) : d_lock(lock) | |
65 | { | |
76698c6e BH |
66 | if(g_singleThreaded) |
67 | return; | |
68 | ||
d90dad50 RG |
69 | int err; |
70 | if((err = pthread_rwlock_wrlock(d_lock))) { | |
a2a81d42 | 71 | throw PDNSException("error acquiring rwlock wrlock: "+stringerror(err)); |
12c86877 BH |
72 | } |
73 | } | |
74 | ~WriteLock() | |
75 | { | |
76698c6e BH |
76 | if(g_singleThreaded) |
77 | return; | |
2be43892 | 78 | if(d_lock) // might have been moved |
79 | pthread_rwlock_unlock(d_lock); | |
80 | } | |
76698c6e | 81 | |
2be43892 | 82 | WriteLock(WriteLock&& rhs) |
83 | { | |
84 | d_lock = rhs.d_lock; | |
85 | rhs.d_lock=0; | |
12c86877 | 86 | } |
2be43892 | 87 | WriteLock(const WriteLock& rhs) = delete; |
88 | WriteLock& operator=(const WriteLock& rhs) = delete; | |
89 | ||
90 | ||
12c86877 BH |
91 | }; |
92 | ||
93 | class TryWriteLock | |
94 | { | |
95 | pthread_rwlock_t *d_lock; | |
96 | bool d_havelock; | |
97 | public: | |
2be43892 | 98 | TryWriteLock(const TryWriteLock& rhs) = delete; |
99 | TryWriteLock& operator=(const TryWriteLock& rhs) = delete; | |
12c86877 BH |
100 | |
101 | TryWriteLock(pthread_rwlock_t *lock) : d_lock(lock) | |
102 | { | |
2b808f13 BH |
103 | if(g_singleThreaded) { |
104 | d_havelock=true; | |
76698c6e | 105 | return; |
2b808f13 | 106 | } |
76698c6e | 107 | |
12c86877 | 108 | d_havelock=false; |
d90dad50 RG |
109 | int err; |
110 | if((err = pthread_rwlock_trywrlock(d_lock)) && err!=EBUSY) { | |
a2a81d42 | 111 | throw PDNSException("error acquiring rwlock tryrwlock: "+stringerror(err)); |
d90dad50 RG |
112 | } |
113 | d_havelock=(err==0); | |
12c86877 | 114 | } |
d676748c | 115 | |
116 | TryWriteLock(TryWriteLock&& rhs) | |
117 | { | |
118 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
119 | rhs.d_lock = nullptr; |
120 | d_havelock = rhs.d_havelock; | |
121 | rhs.d_havelock = false; | |
d676748c | 122 | } |
123 | ||
124 | ||
12c86877 BH |
125 | ~TryWriteLock() |
126 | { | |
76698c6e BH |
127 | if(g_singleThreaded) |
128 | return; | |
129 | ||
d676748c | 130 | if(d_havelock && d_lock) // we might be moved |
12c86877 BH |
131 | pthread_rwlock_unlock(d_lock); |
132 | } | |
133 | bool gotIt() | |
134 | { | |
76698c6e BH |
135 | if(g_singleThreaded) |
136 | return true; | |
137 | ||
12c86877 BH |
138 | return d_havelock; |
139 | } | |
140 | }; | |
141 | ||
142 | class TryReadLock | |
143 | { | |
144 | pthread_rwlock_t *d_lock; | |
145 | bool d_havelock; | |
146 | public: | |
2be43892 | 147 | TryReadLock(const TryReadLock& rhs) = delete; |
148 | TryReadLock& operator=(const TryReadLock& rhs) = delete; | |
12c86877 BH |
149 | |
150 | TryReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
151 | { | |
2b808f13 BH |
152 | if(g_singleThreaded) { |
153 | d_havelock=true; | |
76698c6e | 154 | return; |
2b808f13 | 155 | } |
76698c6e | 156 | |
d90dad50 RG |
157 | int err; |
158 | if((err = pthread_rwlock_tryrdlock(d_lock)) && err!=EBUSY) { | |
a2a81d42 | 159 | throw PDNSException("error acquiring rwlock tryrdlock: "+stringerror(err)); |
d90dad50 RG |
160 | } |
161 | d_havelock=(err==0); | |
12c86877 | 162 | } |
d676748c | 163 | TryReadLock(TryReadLock&& rhs) |
164 | { | |
165 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
166 | rhs.d_lock = nullptr; |
167 | d_havelock = rhs.d_havelock; | |
168 | rhs.d_havelock = false; | |
d676748c | 169 | } |
170 | ||
12c86877 BH |
171 | ~TryReadLock() |
172 | { | |
76698c6e BH |
173 | if(g_singleThreaded) |
174 | return; | |
175 | ||
d676748c | 176 | if(d_havelock && d_lock) |
12c86877 BH |
177 | pthread_rwlock_unlock(d_lock); |
178 | } | |
179 | bool gotIt() | |
180 | { | |
76698c6e BH |
181 | if(g_singleThreaded) |
182 | return true; | |
183 | ||
12c86877 BH |
184 | return d_havelock; |
185 | } | |
186 | }; | |
187 | ||
188 | ||
189 | class ReadLock | |
190 | { | |
191 | pthread_rwlock_t *d_lock; | |
192 | public: | |
193 | ||
194 | ReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
195 | { | |
76698c6e BH |
196 | if(g_singleThreaded) |
197 | return; | |
198 | ||
d90dad50 RG |
199 | int err; |
200 | if((err = pthread_rwlock_rdlock(d_lock))) { | |
a2a81d42 | 201 | throw PDNSException("error acquiring rwlock readlock: "+stringerror(err)); |
d90dad50 | 202 | } |
12c86877 BH |
203 | } |
204 | ~ReadLock() | |
205 | { | |
76698c6e BH |
206 | if(g_singleThreaded) |
207 | return; | |
2be43892 | 208 | if(d_lock) // may have been moved |
209 | pthread_rwlock_unlock(d_lock); | |
210 | } | |
76698c6e | 211 | |
2be43892 | 212 | ReadLock(ReadLock&& rhs) |
213 | { | |
214 | d_lock = rhs.d_lock; | |
215 | rhs.d_lock=0; | |
12c86877 | 216 | } |
2be43892 | 217 | ReadLock(const ReadLock& rhs) = delete; |
218 | ReadLock& operator=(const ReadLock& rhs) = delete; | |
12c86877 | 219 | }; |
12c86877 | 220 | #endif |