]>
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))) { | |
71 | errno = err; | |
3f81d239 | 72 | throw PDNSException("error acquiring rwlock wrlock: "+stringerror()); |
12c86877 BH |
73 | } |
74 | } | |
75 | ~WriteLock() | |
76 | { | |
76698c6e BH |
77 | if(g_singleThreaded) |
78 | return; | |
2be43892 | 79 | if(d_lock) // might have been moved |
80 | pthread_rwlock_unlock(d_lock); | |
81 | } | |
76698c6e | 82 | |
2be43892 | 83 | WriteLock(WriteLock&& rhs) |
84 | { | |
85 | d_lock = rhs.d_lock; | |
86 | rhs.d_lock=0; | |
12c86877 | 87 | } |
2be43892 | 88 | WriteLock(const WriteLock& rhs) = delete; |
89 | WriteLock& operator=(const WriteLock& rhs) = delete; | |
90 | ||
91 | ||
12c86877 BH |
92 | }; |
93 | ||
94 | class TryWriteLock | |
95 | { | |
96 | pthread_rwlock_t *d_lock; | |
97 | bool d_havelock; | |
98 | public: | |
2be43892 | 99 | TryWriteLock(const TryWriteLock& rhs) = delete; |
100 | TryWriteLock& operator=(const TryWriteLock& rhs) = delete; | |
12c86877 BH |
101 | |
102 | TryWriteLock(pthread_rwlock_t *lock) : d_lock(lock) | |
103 | { | |
2b808f13 BH |
104 | if(g_singleThreaded) { |
105 | d_havelock=true; | |
76698c6e | 106 | return; |
2b808f13 | 107 | } |
76698c6e | 108 | |
12c86877 | 109 | d_havelock=false; |
d90dad50 RG |
110 | int err; |
111 | if((err = pthread_rwlock_trywrlock(d_lock)) && err!=EBUSY) { | |
112 | errno = err; | |
3f81d239 | 113 | throw PDNSException("error acquiring rwlock tryrwlock: "+stringerror()); |
d90dad50 RG |
114 | } |
115 | d_havelock=(err==0); | |
12c86877 | 116 | } |
d676748c | 117 | |
118 | TryWriteLock(TryWriteLock&& rhs) | |
119 | { | |
120 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
121 | rhs.d_lock = nullptr; |
122 | d_havelock = rhs.d_havelock; | |
123 | rhs.d_havelock = false; | |
d676748c | 124 | } |
125 | ||
126 | ||
12c86877 BH |
127 | ~TryWriteLock() |
128 | { | |
76698c6e BH |
129 | if(g_singleThreaded) |
130 | return; | |
131 | ||
d676748c | 132 | if(d_havelock && d_lock) // we might be moved |
12c86877 BH |
133 | pthread_rwlock_unlock(d_lock); |
134 | } | |
135 | bool gotIt() | |
136 | { | |
76698c6e BH |
137 | if(g_singleThreaded) |
138 | return true; | |
139 | ||
12c86877 BH |
140 | return d_havelock; |
141 | } | |
142 | }; | |
143 | ||
144 | class TryReadLock | |
145 | { | |
146 | pthread_rwlock_t *d_lock; | |
147 | bool d_havelock; | |
148 | public: | |
2be43892 | 149 | TryReadLock(const TryReadLock& rhs) = delete; |
150 | TryReadLock& operator=(const TryReadLock& rhs) = delete; | |
12c86877 BH |
151 | |
152 | TryReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
153 | { | |
2b808f13 BH |
154 | if(g_singleThreaded) { |
155 | d_havelock=true; | |
76698c6e | 156 | return; |
2b808f13 | 157 | } |
76698c6e | 158 | |
d90dad50 RG |
159 | int err; |
160 | if((err = pthread_rwlock_tryrdlock(d_lock)) && err!=EBUSY) { | |
161 | errno = err; | |
3f81d239 | 162 | throw PDNSException("error acquiring rwlock tryrdlock: "+stringerror()); |
d90dad50 RG |
163 | } |
164 | d_havelock=(err==0); | |
12c86877 | 165 | } |
d676748c | 166 | TryReadLock(TryReadLock&& rhs) |
167 | { | |
168 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
169 | rhs.d_lock = nullptr; |
170 | d_havelock = rhs.d_havelock; | |
171 | rhs.d_havelock = false; | |
d676748c | 172 | } |
173 | ||
12c86877 BH |
174 | ~TryReadLock() |
175 | { | |
76698c6e BH |
176 | if(g_singleThreaded) |
177 | return; | |
178 | ||
d676748c | 179 | if(d_havelock && d_lock) |
12c86877 BH |
180 | pthread_rwlock_unlock(d_lock); |
181 | } | |
182 | bool gotIt() | |
183 | { | |
76698c6e BH |
184 | if(g_singleThreaded) |
185 | return true; | |
186 | ||
12c86877 BH |
187 | return d_havelock; |
188 | } | |
189 | }; | |
190 | ||
191 | ||
192 | class ReadLock | |
193 | { | |
194 | pthread_rwlock_t *d_lock; | |
195 | public: | |
196 | ||
197 | ReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
198 | { | |
76698c6e BH |
199 | if(g_singleThreaded) |
200 | return; | |
201 | ||
d90dad50 RG |
202 | int err; |
203 | if((err = pthread_rwlock_rdlock(d_lock))) { | |
204 | errno = err; | |
2be43892 | 205 | throw PDNSException("error acquiring rwlock readlock: "+stringerror()); |
d90dad50 | 206 | } |
12c86877 BH |
207 | } |
208 | ~ReadLock() | |
209 | { | |
76698c6e BH |
210 | if(g_singleThreaded) |
211 | return; | |
2be43892 | 212 | if(d_lock) // may have been moved |
213 | pthread_rwlock_unlock(d_lock); | |
214 | } | |
76698c6e | 215 | |
2be43892 | 216 | ReadLock(ReadLock&& rhs) |
217 | { | |
218 | d_lock = rhs.d_lock; | |
219 | rhs.d_lock=0; | |
12c86877 | 220 | } |
2be43892 | 221 | ReadLock(const ReadLock& rhs) = delete; |
222 | ReadLock& operator=(const ReadLock& rhs) = delete; | |
12c86877 | 223 | }; |
12c86877 | 224 | #endif |