// ***************************************************************** -*- C++ -*- /* * Copyright (C) 2004-2018 Exiv2 authors * This program is part of the Exiv2 distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. */ #ifndef RW_LOCK_HPP #define RW_LOCK_HPP #ifdef _MSC_VER #include #else #include #endif namespace Exiv2 { #ifdef _MSC_VER /*! @brief Class to provide a Read-Write Lock */ class RWLock { public: RWLock() { InitializeCriticalSection(&lock_); } ~RWLock() { DeleteCriticalSection(&lock_); } void wrlock() { enter(); } bool trywrlock() { return tryenter(); } void rdlock() { enter(); } bool tryrdlock() { return tryenter(); } void rdunlock() { leave(); } void wrunlock() { leave(); } private: void enter() { EnterCriticalSection(&lock_); } void leave() { LeaveCriticalSection(&lock_); } bool tryenter() { #if defined(MSDEV_2003) || defined(MSDEV_2005) EnterCriticalSection(&lock_); return true; #else return 0 != TryEnterCriticalSection(&lock_); #endif } private: CRITICAL_SECTION lock_; }; #else /*! @brief Class to provide a Read-Write Lock */ // UNIX systems (including MinGW and Cygwin) class RWLock { public: //! constructor (acquires the lock) explicit RWLock(const pthread_rwlockattr_t *attr = 0) { pthread_rwlock_init(&rwlock_, attr); } //! constructor (releases lock) ~RWLock() { pthread_rwlock_destroy(&rwlock_); } //! acquire rw lock void wrlock() { pthread_rwlock_wrlock(&rwlock_); } //! test to see if the rw lock can be acquired bool trywrlock() { return 0 == pthread_rwlock_trywrlock(&rwlock_); } //! acquire rd lock void rdlock() { pthread_rwlock_rdlock(&rwlock_); } //! test to see if the rd lock can be acquired bool tryrdlock() { return 0 == pthread_rwlock_tryrdlock(&rwlock_); } //! release rw lock void unlock() { pthread_rwlock_unlock(&rwlock_); } //! unlock rd lock void rdunlock() { unlock(); } //! unlock rw lock void wrunlock() { unlock(); } private: //! the lock itself pthread_rwlock_t rwlock_; }; #endif /*! @brief Class to provide a ScopedReadLock. The lock is applied by the constructor and released by the destructor. */ class ScopedReadLock { public: //! constructor - locks the object explicit ScopedReadLock(RWLock &rwlock): rwlock_(rwlock) { rwlock_.rdlock(); } //! destructor - unlocks the object used in constructor ~ScopedReadLock() { rwlock_.rdunlock(); } private: //! object locked by the constructor (and released by destructor) RWLock &rwlock_; }; /*! @brief Class to provide a ScopedWriteLock. The lock is applied by the constructor and released by the destructor. */ class ScopedWriteLock { public: //! constructor - locks the object explicit ScopedWriteLock(RWLock &rwlock): rwlock_(rwlock) { rwlock_.wrlock(); } //! destructor - unlocks the object used in constructor ~ScopedWriteLock() { rwlock_.wrunlock(); } private: //! object locked by the constructor (and released by destructor) RWLock &rwlock_; }; } #endif // RW_LOCK_HPP