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