]>
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 | */ | |
e8c59f2d | 22 | #pragma once |
12c86877 BH |
23 | #include <pthread.h> |
24 | #include <errno.h> | |
25 | #include "misc.hh" | |
5c409fa2 | 26 | #include "pdnsexception.hh" |
76698c6e BH |
27 | |
28 | extern bool g_singleThreaded; | |
29 | ||
12c86877 BH |
30 | class Lock |
31 | { | |
32 | pthread_mutex_t *d_lock; | |
33 | public: | |
2be43892 | 34 | Lock(const Lock& rhs) = delete; |
35 | Lock& operator=(const Lock& rhs) = delete; | |
12c86877 BH |
36 | |
37 | Lock(pthread_mutex_t *lock) : d_lock(lock) | |
38 | { | |
76698c6e BH |
39 | if(g_singleThreaded) |
40 | return; | |
d90dad50 RG |
41 | |
42 | int err; | |
43 | if((err = pthread_mutex_lock(d_lock))) { | |
44 | errno = err; | |
3f81d239 | 45 | throw PDNSException("error acquiring lock: "+stringerror()); |
d90dad50 | 46 | } |
12c86877 BH |
47 | } |
48 | ~Lock() | |
49 | { | |
76698c6e BH |
50 | if(g_singleThreaded) |
51 | return; | |
52 | ||
12c86877 BH |
53 | pthread_mutex_unlock(d_lock); |
54 | } | |
55 | }; | |
56 | ||
57 | class WriteLock | |
58 | { | |
59 | pthread_rwlock_t *d_lock; | |
60 | public: | |
61 | ||
62 | WriteLock(pthread_rwlock_t *lock) : d_lock(lock) | |
63 | { | |
76698c6e BH |
64 | if(g_singleThreaded) |
65 | return; | |
66 | ||
d90dad50 RG |
67 | int err; |
68 | if((err = pthread_rwlock_wrlock(d_lock))) { | |
a2a81d42 | 69 | throw PDNSException("error acquiring rwlock wrlock: "+stringerror(err)); |
12c86877 BH |
70 | } |
71 | } | |
72 | ~WriteLock() | |
73 | { | |
76698c6e BH |
74 | if(g_singleThreaded) |
75 | return; | |
2be43892 | 76 | if(d_lock) // might have been moved |
77 | pthread_rwlock_unlock(d_lock); | |
78 | } | |
76698c6e | 79 | |
2be43892 | 80 | WriteLock(WriteLock&& rhs) |
81 | { | |
82 | d_lock = rhs.d_lock; | |
83 | rhs.d_lock=0; | |
12c86877 | 84 | } |
2be43892 | 85 | WriteLock(const WriteLock& rhs) = delete; |
86 | WriteLock& operator=(const WriteLock& rhs) = delete; | |
87 | ||
12c86877 BH |
88 | }; |
89 | ||
90 | class TryWriteLock | |
91 | { | |
92 | pthread_rwlock_t *d_lock; | |
93 | bool d_havelock; | |
94 | public: | |
2be43892 | 95 | TryWriteLock(const TryWriteLock& rhs) = delete; |
96 | TryWriteLock& operator=(const TryWriteLock& rhs) = delete; | |
12c86877 BH |
97 | |
98 | TryWriteLock(pthread_rwlock_t *lock) : d_lock(lock) | |
99 | { | |
2b808f13 BH |
100 | if(g_singleThreaded) { |
101 | d_havelock=true; | |
76698c6e | 102 | return; |
2b808f13 | 103 | } |
76698c6e | 104 | |
12c86877 | 105 | d_havelock=false; |
d90dad50 RG |
106 | int err; |
107 | if((err = pthread_rwlock_trywrlock(d_lock)) && err!=EBUSY) { | |
a2a81d42 | 108 | throw PDNSException("error acquiring rwlock tryrwlock: "+stringerror(err)); |
d90dad50 RG |
109 | } |
110 | d_havelock=(err==0); | |
12c86877 | 111 | } |
d676748c | 112 | |
113 | TryWriteLock(TryWriteLock&& rhs) | |
114 | { | |
115 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
116 | rhs.d_lock = nullptr; |
117 | d_havelock = rhs.d_havelock; | |
118 | rhs.d_havelock = false; | |
d676748c | 119 | } |
120 | ||
121 | ||
12c86877 BH |
122 | ~TryWriteLock() |
123 | { | |
76698c6e BH |
124 | if(g_singleThreaded) |
125 | return; | |
126 | ||
d676748c | 127 | if(d_havelock && d_lock) // we might be moved |
12c86877 BH |
128 | pthread_rwlock_unlock(d_lock); |
129 | } | |
130 | bool gotIt() | |
131 | { | |
76698c6e BH |
132 | if(g_singleThreaded) |
133 | return true; | |
134 | ||
12c86877 BH |
135 | return d_havelock; |
136 | } | |
137 | }; | |
138 | ||
139 | class TryReadLock | |
140 | { | |
141 | pthread_rwlock_t *d_lock; | |
142 | bool d_havelock; | |
143 | public: | |
2be43892 | 144 | TryReadLock(const TryReadLock& rhs) = delete; |
145 | TryReadLock& operator=(const TryReadLock& rhs) = delete; | |
12c86877 BH |
146 | |
147 | TryReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
148 | { | |
2b808f13 BH |
149 | if(g_singleThreaded) { |
150 | d_havelock=true; | |
76698c6e | 151 | return; |
2b808f13 | 152 | } |
76698c6e | 153 | |
d90dad50 RG |
154 | int err; |
155 | if((err = pthread_rwlock_tryrdlock(d_lock)) && err!=EBUSY) { | |
a2a81d42 | 156 | throw PDNSException("error acquiring rwlock tryrdlock: "+stringerror(err)); |
d90dad50 RG |
157 | } |
158 | d_havelock=(err==0); | |
12c86877 | 159 | } |
d676748c | 160 | TryReadLock(TryReadLock&& rhs) |
161 | { | |
162 | d_lock = rhs.d_lock; | |
f10f2f2f RG |
163 | rhs.d_lock = nullptr; |
164 | d_havelock = rhs.d_havelock; | |
165 | rhs.d_havelock = false; | |
d676748c | 166 | } |
167 | ||
12c86877 BH |
168 | ~TryReadLock() |
169 | { | |
76698c6e BH |
170 | if(g_singleThreaded) |
171 | return; | |
172 | ||
d676748c | 173 | if(d_havelock && d_lock) |
12c86877 BH |
174 | pthread_rwlock_unlock(d_lock); |
175 | } | |
176 | bool gotIt() | |
177 | { | |
76698c6e BH |
178 | if(g_singleThreaded) |
179 | return true; | |
180 | ||
12c86877 BH |
181 | return d_havelock; |
182 | } | |
183 | }; | |
184 | ||
185 | ||
186 | class ReadLock | |
187 | { | |
188 | pthread_rwlock_t *d_lock; | |
189 | public: | |
190 | ||
191 | ReadLock(pthread_rwlock_t *lock) : d_lock(lock) | |
192 | { | |
76698c6e BH |
193 | if(g_singleThreaded) |
194 | return; | |
195 | ||
d90dad50 RG |
196 | int err; |
197 | if((err = pthread_rwlock_rdlock(d_lock))) { | |
a2a81d42 | 198 | throw PDNSException("error acquiring rwlock readlock: "+stringerror(err)); |
d90dad50 | 199 | } |
12c86877 BH |
200 | } |
201 | ~ReadLock() | |
202 | { | |
76698c6e BH |
203 | if(g_singleThreaded) |
204 | return; | |
2be43892 | 205 | if(d_lock) // may have been moved |
206 | pthread_rwlock_unlock(d_lock); | |
207 | } | |
76698c6e | 208 | |
2be43892 | 209 | ReadLock(ReadLock&& rhs) |
210 | { | |
211 | d_lock = rhs.d_lock; | |
212 | rhs.d_lock=0; | |
12c86877 | 213 | } |
2be43892 | 214 | ReadLock(const ReadLock& rhs) = delete; |
215 | ReadLock& operator=(const ReadLock& rhs) = delete; | |
12c86877 | 216 | }; |