// bslmt_recursivemutex.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_RECURSIVEMUTEX #define INCLUDED_BSLMT_RECURSIVEMUTEX #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a platform-independent recursive mutex. // //@CLASSES: // bslmt::RecursiveMutex: platform-independent recursive mutex // //@SEE_ALSO: bslmt_mutex // //@DESCRIPTION: This component provides a mutually exclusive lock primitive // ("mutex") that is "recursive" - a given thread can lock a recursive mutex // multiple times, and then release it by unlocking it the same number of // times. The 'bslmt::RecursiveMutex' class provides the following operations: // 'lock', 'tryLock', and 'unlock'. // // The non-recursive mutex 'bslmt::Mutex' has substantially lower overhead than // 'bslmt::RecursiveMutex', and should be used instead if at all possible. In // particular, it is rare to need a recursive mutex. // // The behavior is undefined if 'unlock' is invoked on a // 'bslmt::RecursiveMutex' object from a thread that does not currently own the // lock. // ///Usage ///----- // As the name implies, 'bslmt::RecursiveMutex' supports multiple calls to // 'lock', which *must* be balanced by a corresponding number of calls to // 'unlock'. Suppose that we are using a 'bslmt::RecursiveMutex' object to // guarantee exclusive access to some object. The following sketches the // "recursive" nature of 'bslmt::RecursiveMutex': //.. // bslmt::RecursiveMutex recMutex; //.. // Assume that we do not have exclusive access to the object. //.. // recMutex.lock(); // first level of locking //.. // We have exclusive access here. //.. // recMutex.lock(); // second level of locking //.. // We still have exclusive access. //.. // recMutex.unlock(); // release second level lock -- mutex stays locked //.. // We *still* have exclusive access. //.. // recMutex.unlock(); // release first level lock -- mutex is unlocked //.. // The two calls to 'unlock' have balanced the two earlier calls to 'lock'. // Consequently, we no longer have exclusive access. // // Note that 'bslmt::RecursiveMutex' has substantially more overhead than does // 'bslmt::Mutex'. Consequently, the latter should be used unless recursive // locking is truly warranted. #include <bslscm_version.h> #include <bslmt_recursivemuteximpl_pthread.h> #include <bslmt_recursivemuteximpl_win32.h> #include <bslmt_platform.h> namespace BloombergLP { namespace bslmt { template <class THREAD_POLICY> class RecursivemutexImpl; // ==================== // class RecursiveMutex // ==================== class RecursiveMutex { // This 'class' implements a recursive mutex (i.e., a mutex that can be // locked any number of times by a thread, and then released by unlocking // the mutex the same number of times). If there is an efficient native // recursive mutex, this class wraps it. Otherwise, a reasonably efficient // proprietary implementation is used. Note that 'Mutex' should be // preferred if at all possible. // DATA RecursiveMutexImpl<Platform::ThreadPolicy> d_imp; // platform-specific // implementation // NOT IMPLEMENTED RecursiveMutex(const RecursiveMutex&); RecursiveMutex& operator=(const RecursiveMutex&); public: // CREATORS RecursiveMutex(); // Create a recursive mutex object in the unlocked state. ~RecursiveMutex(); // Destroy this recursive mutex object. // MANIPULATORS void lock(); // Acquire a lock on this object. If this object is currently locked, // then suspend execution of the current thread until a lock can be // acquired. Succeed immediately if this thread already holds the // lock. int tryLock(); // Attempt to acquire a lock on this object. Return 0 on success, and // a non-zero value if this object is already locked by another thread, // or if an error occurs. Succeed immediately if this thread already // holds the lock. void unlock(); // Release a lock on this object that was previously acquired through a // call to 'lock', or a successful call to 'tryLock'. To fully release // the lock, a thread must invoke 'unlock' the same number of times it // invoked 'lock' and 'tryLock'. The behavior is undefined unless the // calling thread currently owns the lock on this recursive mutex. }; } // close package namespace // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------- // class RecursiveMutex // -------------------- // CREATORS inline bslmt::RecursiveMutex::RecursiveMutex() { } inline bslmt::RecursiveMutex::~RecursiveMutex() { } // MANIPULATORS inline void bslmt::RecursiveMutex::lock() { d_imp.lock(); } inline int bslmt::RecursiveMutex::tryLock() { return d_imp.tryLock(); } inline void bslmt::RecursiveMutex::unlock() { d_imp.unlock(); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 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 ----------------------------------