// bslmt_rwmutex.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BSLMT_RWMUTEX #define INCLUDED_BSLMT_RWMUTEX #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a platform-independent RW mutex class. // //@DEPRECATED: Use 'bslmt_readerwritermutex' instead. // //@CLASSES: // bslmt::RWMutex: platform-independent wrapper of an RW mutex // //@SEE_ALSO: bslmt_readerwritermutex, bslmt_readerwriterlock, // bslmt_readlockguard, bslmt_writelockguard // //@DESCRIPTION: This component provides a class, 'bslmt::RWMutex', that defines // a platform-independent RW mutex. An RW mutex provides for a shared "read" // lock that may be held simultaneously by any number of threads, and a "write" // lock that is exclusive (i.e., it may be held by only one thread at a time). // The "write" lock is also exclusive with the "read" lock, so that no threads // may hold a "read" lock while the "write" lock is held, and vice versa. // ///Usage ///----- // TBD #include <bslscm_version.h> #include <bslmt_platform.h> #include <bsls_assert.h> #include <bsls_platform.h> #if defined(BSLMT_PLATFORM_WIN32_THREADS) || defined(BSLS_PLATFORM_OS_AIX) #include <bslmt_readerwriterlock.h> #endif #ifdef BSLMT_PLATFORM_POSIX_THREADS #include <pthread.h> #endif #include <bsl_cstddef.h> namespace BloombergLP { namespace bslmt { template <class THREAD_POLICY> struct RWMutexImpl; } // close package namespace #ifdef BSLMT_PLATFORM_POSIX_THREADS namespace bslmt { // ================================ // struct RWMutexImpl<PosixThreads> // ================================ template <> struct RWMutexImpl<Platform::PosixThreads> { // This is a platform-specific implementation detail that is not intended // for use outside of this component. Use the 'RWMutex' class instead. // This structure is a wrapper around a POSIX RW lock on Sun (on AIX the // POSIX RW lock has poor performance and no writer guarantees). private: // DATA pthread_rwlock_t d_lock; public: // CREATORS RWMutexImpl(); ~RWMutexImpl(); // MANIPULATORS void lockRead(); void lockWrite(); int tryLockRead(); int tryLockWrite(); void unlock(); }; } // close package namespace #endif // BSLMT_PLATFORM_POSIX_THREADS namespace bslmt { // ============= // class RWMutex // ============= class RWMutex { // This class is a platform-independent interface to a reader-writer lock // ("RW mutex"). Multiple readers can safely hold the lock simultaneously, // whereas only one writer is allowed to hold the lock at a time. This // class uses the most efficient RW mutex implementation available for the // current platform. Note that the implementation may allow readers to // starve writers. // DATA #if defined(BSLS_PLATFORM_OS_AIX) || defined(BSLMT_PLATFORM_WIN32_THREADS) ReaderWriterLock d_impl; #else RWMutexImpl<Platform::ThreadPolicy> d_impl; #endif // NOT IMPLEMENTED RWMutex(const RWMutex&); RWMutex& operator=(const RWMutex&); public: // CREATORS RWMutex(); // Create an RW mutex initialized to an unlocked state. ~RWMutex(); // Destroy this RW mutex. The behavior is undefined if the mutex // is in a locked state. // MANIPULATORS void lockRead(); // Lock this reader-writer mutex for reading. If there are no active // or pending write locks, lock this mutex for reading and return // immediately. Otherwise, block until the read lock on this mutex is // acquired. Use 'unlock' to release the lock on this mutex. The // behavior is undefined if this method is called from a thread that // already has a lock on this mutex. void lockWrite(); // Lock this reader-writer mutex for writing. If there are no active // or pending locks on this mutex, lock this mutex for writing and // return immediately. Otherwise, block until the write lock on this // mutex is acquired. Use 'unlock' to release the lock on this mutex. // The behavior is undefined if this method is called from a thread // that already has a lock on this mutex. int tryLockRead(); // Attempt to lock this reader-writer mutex for reading. Immediately // return 0 on success, and a non-zero value if there are active or // pending writers. If successful, 'unlock' must be used to release // the lock on this mutex. The behavior is undefined if this method is // called from a thread that already has a lock on this mutex. int tryLockWrite(); // Attempt to lock this reader-writer mutex for writing. Immediately // return 0 on success, and a non-zero value if there are active or // pending locks on this mutex. If successful, 'unlock' must be used // to release the lock on this mutex. The behavior is undefined if // this method is called from a thread that already has a lock on this // mutex. void unlock(); // Release the lock that the calling thread holds on this reader-writer // mutex. The behavior is undefined unless the calling thread // currently has a lock on this mutex. }; } // close package namespace // ============================================================================ // INLINE DEFINITIONS // ============================================================================ #ifdef BSLMT_PLATFORM_POSIX_THREADS // ------------------ // struct RWMutexImpl // ------------------ // CREATORS inline bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::RWMutexImpl() { const int rc = pthread_rwlock_init(&d_lock, NULL); // pthread_rwlock_init should not return a failure code. BSLS_ASSERT_SAFE(0 == rc); (void) rc; // suppress 'unused variable' warnings } inline bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::~RWMutexImpl() { const int rc = pthread_rwlock_destroy(&d_lock); // pthread_rwlock_destroy should not return a failure code. BSLS_ASSERT_SAFE(0 == rc); (void) rc; // suppress 'unused variable' warnings } // MANIPULATORS inline void bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::lockRead() { const int rc = pthread_rwlock_rdlock(&d_lock); // pthread_rwlock_rdlock should not return a failure code. BSLS_ASSERT_SAFE(0 == rc); (void) rc; // suppress 'unused variable' warnings } inline void bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::lockWrite() { const int rc = pthread_rwlock_wrlock(&d_lock); // pthread_rwlock_wrlock should not return a failure code. BSLS_ASSERT_SAFE(0 == rc); (void) rc; // suppress 'unused variable' warnings } inline int bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::tryLockRead() { return pthread_rwlock_tryrdlock(&d_lock) ? 1 : 0; } inline int bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::tryLockWrite() { return pthread_rwlock_trywrlock(&d_lock) ? 1 : 0; } inline void bslmt::RWMutexImpl<bslmt::Platform::PosixThreads>::unlock() { pthread_rwlock_unlock(&d_lock); } #endif // BSLMT_PLATFORM_POSIX_THREADS // ------------- // class RWMutex // ------------- // CREATORS inline bslmt::RWMutex::RWMutex() { } inline bslmt::RWMutex::~RWMutex() { } // MANIPULATORS inline void bslmt::RWMutex::lockRead() { d_impl.lockRead(); } inline void bslmt::RWMutex::lockWrite() { d_impl.lockWrite(); } inline int bslmt::RWMutex::tryLockRead() { return d_impl.tryLockRead(); } inline int bslmt::RWMutex::tryLockWrite() { return d_impl.tryLockWrite(); } inline void bslmt::RWMutex::unlock() { d_impl.unlock(); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2017 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------