diff --git a/boost/thread/pthread/shared_mutex.hpp b/boost/thread/pthread/shared_mutex.hpp
index 458d6c8..2a7b983 100644
|
a
|
b
|
|
| 24 | 24 | |
| 25 | 25 | #include <boost/config/abi_prefix.hpp> |
| 26 | 26 | |
| | 27 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 28 | #include <stdexcept> |
| | 29 | #include <pthread.h> |
| | 30 | #endif |
| | 31 | |
| 27 | 32 | namespace boost |
| 28 | 33 | { |
| 29 | 34 | class shared_mutex |
| … |
… |
namespace boost
|
| 162 | 167 | boost::condition_variable exclusive_cond; |
| 163 | 168 | boost::condition_variable upgrade_cond; |
| 164 | 169 | |
| | 170 | #if defined BOOST_THREAD_PTHREAD_USE_RWLOCKS |
| | 171 | pthread_rwlock_t rw_lock; |
| | 172 | #endif |
| | 173 | |
| 165 | 174 | void release_waiters() |
| 166 | 175 | { |
| 167 | 176 | exclusive_cond.notify_one(); |
| … |
… |
namespace boost
|
| 172 | 181 | |
| 173 | 182 | BOOST_THREAD_NO_COPYABLE(shared_mutex) |
| 174 | 183 | |
| | 184 | #if defined BOOST_THREAD_PTHREAD_USE_RWLOCKS |
| | 185 | BOOST_THREAD_NO_COPYABLE(rw_lock) |
| | 186 | #endif |
| | 187 | |
| 175 | 188 | shared_mutex() |
| 176 | 189 | { |
| | 190 | #if defined BOOST_THREAD_PTHREAD_USE_RWLOCKS |
| | 191 | int ret = 0; |
| | 192 | #if defined(__linux__) |
| | 193 | // Linux rwlocks are by default writer-starving |
| | 194 | pthread_rwlockattr_t attr; |
| | 195 | ret = pthread_rwlockattr_init(&attr); |
| | 196 | if (ret) |
| | 197 | { |
| | 198 | throw std::runtime_error("pthread_rwlockattr_init faild"); |
| | 199 | } |
| | 200 | ret = pthread_rwlockattr_setkind_np(&attr, |
| | 201 | PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); |
| | 202 | if (ret) |
| | 203 | { |
| | 204 | throw std::runtime_error("pthread_rwlockattr_setkind_np failed"); |
| | 205 | } |
| | 206 | ret = pthread_rwlock_init(&lock_, &attr); |
| | 207 | if (ret) |
| | 208 | { |
| | 209 | throw std::runtime_error("pthread_rwlock_init failed"); |
| | 210 | } |
| | 211 | ret = pthread_rwlockattr_destroy(&attr); |
| | 212 | if (ret) |
| | 213 | { |
| | 214 | throw std::runtime_error("pthread_rwlockattr_destroy failed"); |
| | 215 | } |
| | 216 | #else |
| | 217 | ret = pthread_rwlock_init(&lock_, NULL); |
| | 218 | if (ret) |
| | 219 | { |
| | 220 | throw std::runtime_error("pthread_rwlock_init failed"); |
| | 221 | } |
| | 222 | #endif |
| | 223 | #endif |
| 177 | 224 | } |
| 178 | 225 | |
| 179 | 226 | ~shared_mutex() |
| 180 | 227 | { |
| | 228 | #if defined BOOST_THREAD_PTHREAD_USE_RWLOCKS |
| | 229 | int ret = pthread_rwlock_destroy(&lock_); |
| | 230 | if (ret) |
| | 231 | { |
| | 232 | throw std::runtime_error("pthread_rwlock_destroy failed"); |
| | 233 | } |
| | 234 | #endif |
| 181 | 235 | } |
| 182 | 236 | |
| 183 | 237 | void lock_shared() |
| 184 | 238 | { |
| | 239 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 240 | int ret = pthread_rwlock_rdlock(&rw_lock); |
| | 241 | if (ret) |
| | 242 | { |
| | 243 | throw std::runtime_error("pthread_rwlock_rdlock failed"); |
| | 244 | } |
| | 245 | #else |
| 185 | 246 | #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS |
| 186 | 247 | boost::this_thread::disable_interruption do_not_disturb; |
| 187 | 248 | #endif |
| … |
… |
namespace boost
|
| 191 | 252 | shared_cond.wait(lk); |
| 192 | 253 | } |
| 193 | 254 | state.lock_shared(); |
| | 255 | #endif |
| 194 | 256 | } |
| 195 | 257 | |
| 196 | 258 | bool try_lock_shared() |
| 197 | 259 | { |
| | 260 | #if definet BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 261 | int ret = pthread_rwlock_tryrdlock(&rw_lock); |
| | 262 | if (!ret) |
| | 263 | { |
| | 264 | return true; |
| | 265 | } |
| | 266 | else if (ret == EBUSY) |
| | 267 | { |
| | 268 | return false; |
| | 269 | } |
| | 270 | throw std::runtime_error("pthread_rwlock_tryrdlock failed"); |
| | 271 | #else |
| 198 | 272 | boost::unique_lock<boost::mutex> lk(state_change); |
| 199 | 273 | |
| 200 | 274 | if(!state.can_lock_shared()) |
| … |
… |
namespace boost
|
| 203 | 277 | } |
| 204 | 278 | state.lock_shared(); |
| 205 | 279 | return true; |
| | 280 | #endif |
| 206 | 281 | } |
| 207 | 282 | |
| 208 | 283 | #if defined BOOST_THREAD_USES_DATETIME |
| … |
… |
namespace boost
|
| 258 | 333 | #endif |
| 259 | 334 | void unlock_shared() |
| 260 | 335 | { |
| | 336 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 337 | int ret = pthread_rwlock_unlock(&rw_lock); |
| | 338 | if (ret) |
| | 339 | { |
| | 340 | throw std::runtime_error("pthread_rwlock_unlock failed"); |
| | 341 | } |
| | 342 | #else |
| 261 | 343 | boost::unique_lock<boost::mutex> lk(state_change); |
| 262 | 344 | state.assert_lock_shared(); |
| 263 | 345 | state.unlock_shared(); |
| … |
… |
namespace boost
|
| 279 | 361 | } |
| 280 | 362 | release_waiters(); |
| 281 | 363 | } |
| | 364 | #endif |
| 282 | 365 | } |
| 283 | 366 | |
| 284 | 367 | void lock() |
| 285 | 368 | { |
| | 369 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 370 | int ret = pthread_rwlock_wrlock(&rw_lock); |
| | 371 | if (ret) |
| | 372 | { |
| | 373 | throw std::runtime_error("pthread_rwlock_wrlock failed"); |
| | 374 | } |
| | 375 | #else |
| 286 | 376 | #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS |
| 287 | 377 | boost::this_thread::disable_interruption do_not_disturb; |
| 288 | 378 | #endif |
| … |
… |
namespace boost
|
| 294 | 384 | exclusive_cond.wait(lk); |
| 295 | 385 | } |
| 296 | 386 | state.exclusive=true; |
| | 387 | #endif |
| 297 | 388 | } |
| 298 | 389 | |
| 299 | 390 | #if defined BOOST_THREAD_USES_DATETIME |
| … |
… |
namespace boost
|
| 363 | 454 | |
| 364 | 455 | bool try_lock() |
| 365 | 456 | { |
| | 457 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 458 | int ret = pthread_rwlock_trywrlock(&rw_lock); |
| | 459 | if (!ret) |
| | 460 | { |
| | 461 | return true; |
| | 462 | } |
| | 463 | else if (ret == EBUSY) |
| | 464 | { |
| | 465 | return false; |
| | 466 | } |
| | 467 | throw std::runtime_error("pthread_rwlock_trywrlock failed"); |
| | 468 | #else |
| 366 | 469 | boost::unique_lock<boost::mutex> lk(state_change); |
| 367 | 470 | |
| 368 | 471 | if(state.shared_count || state.exclusive) |
| … |
… |
namespace boost
|
| 374 | 477 | state.exclusive=true; |
| 375 | 478 | return true; |
| 376 | 479 | } |
| 377 | | |
| | 480 | #endif |
| 378 | 481 | } |
| 379 | 482 | |
| 380 | 483 | void unlock() |
| 381 | 484 | { |
| | 485 | #if defined BOOST_THREAD_USE_PTHREAD_RWLOCKS |
| | 486 | int ret = pthread_rwlock_unlock(&rw_lock); |
| | 487 | if (ret) |
| | 488 | { |
| | 489 | throw std::runtime_error("pthread_rwlock_unlock failed"); |
| | 490 | } |
| | 491 | #else |
| 382 | 492 | boost::unique_lock<boost::mutex> lk(state_change); |
| 383 | 493 | state.assert_locked(); |
| 384 | 494 | state.exclusive=false; |
| 385 | 495 | state.exclusive_waiting_blocked=false; |
| 386 | 496 | state.assert_free(); |
| 387 | 497 | release_waiters(); |
| | 498 | #endif |
| 388 | 499 | } |
| 389 | 500 | |
| 390 | 501 | void lock_upgrade() |