Mutex.h revision 249423
1169689Skan//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===//
2169689Skan//
3169689Skan//                     The LLVM Compiler Infrastructure
4169689Skan//
5169689Skan// This file is distributed under the University of Illinois Open Source
6169689Skan// License. See LICENSE.TXT for details.
7169689Skan//
8169689Skan//===----------------------------------------------------------------------===//
9169689Skan//
10169689Skan// This file declares the llvm::sys::Mutex class.
11169689Skan//
12169689Skan//===----------------------------------------------------------------------===//
13169689Skan
14169689Skan#ifndef LLVM_SUPPORT_MUTEX_H
15169689Skan#define LLVM_SUPPORT_MUTEX_H
16169689Skan
17169689Skan#include "llvm/Support/Compiler.h"
18169689Skan#include "llvm/Support/Threading.h"
19169689Skan#include <cassert>
20169689Skan
21169689Skannamespace llvm
22169689Skan{
23169689Skan  namespace sys
24169689Skan  {
25169689Skan    /// @brief Platform agnostic Mutex class.
26169689Skan    class MutexImpl
27169689Skan    {
28169689Skan    /// @name Constructors
29169689Skan    /// @{
30169689Skan    public:
31169689Skan
32169689Skan      /// Initializes the lock but doesn't acquire it. if \p recursive is set
33169689Skan      /// to false, the lock will not be recursive which makes it cheaper but
34169689Skan      /// also more likely to deadlock (same thread can't acquire more than
35169689Skan      /// once).
36169689Skan      /// @brief Default Constructor.
37169689Skan      explicit MutexImpl(bool recursive = true);
38169689Skan
39169689Skan      /// Releases and removes the lock
40169689Skan      /// @brief Destructor
41169689Skan      ~MutexImpl();
42169689Skan
43169689Skan    /// @}
44169689Skan    /// @name Methods
45169689Skan    /// @{
46169689Skan    public:
47169689Skan
48169689Skan      /// Attempts to unconditionally acquire the lock. If the lock is held by
49169689Skan      /// another thread, this method will wait until it can acquire the lock.
50169689Skan      /// @returns false if any kind of error occurs, true otherwise.
51169689Skan      /// @brief Unconditionally acquire the lock.
52169689Skan      bool acquire();
53169689Skan
54169689Skan      /// Attempts to release the lock. If the lock is held by the current
55169689Skan      /// thread, the lock is released allowing other threads to acquire the
56169689Skan      /// lock.
57169689Skan      /// @returns false if any kind of error occurs, true otherwise.
58169689Skan      /// @brief Unconditionally release the lock.
59169689Skan      bool release();
60169689Skan
61169689Skan      /// Attempts to acquire the lock without blocking. If the lock is not
62169689Skan      /// available, this function returns false quickly (without blocking). If
63169689Skan      /// the lock is available, it is acquired.
64169689Skan      /// @returns false if any kind of error occurs or the lock is not
65169689Skan      /// available, true otherwise.
66169689Skan      /// @brief Try to acquire the lock.
67169689Skan      bool tryacquire();
68169689Skan
69169689Skan    //@}
70169689Skan    /// @name Platform Dependent Data
71169689Skan    /// @{
72169689Skan    private:
73169689Skan      void* data_; ///< We don't know what the data will be
74169689Skan
75169689Skan    /// @}
76169689Skan    /// @name Do Not Implement
77169689Skan    /// @{
78169689Skan    private:
79169689Skan      MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION;
80169689Skan      void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION;
81169689Skan    /// @}
82169689Skan    };
83169689Skan
84169689Skan
85169689Skan    /// SmartMutex - A mutex with a compile time constant parameter that
86169689Skan    /// indicates whether this mutex should become a no-op when we're not
87169689Skan    /// running in multithreaded mode.
88169689Skan    template<bool mt_only>
89169689Skan    class SmartMutex : public MutexImpl {
90169689Skan      unsigned acquired;
91169689Skan      bool recursive;
92169689Skan    public:
93169689Skan      explicit SmartMutex(bool rec = true) :
94169689Skan        MutexImpl(rec), acquired(0), recursive(rec) { }
95169689Skan
96169689Skan      bool acquire() {
97169689Skan        if (!mt_only || llvm_is_multithreaded()) {
98169689Skan          return MutexImpl::acquire();
99169689Skan        } else {
100169689Skan          // Single-threaded debugging code.  This would be racy in
101169689Skan          // multithreaded mode, but provides not sanity checks in single
102169689Skan          // threaded mode.
103169689Skan          assert((recursive || acquired == 0) && "Lock already acquired!!");
104169689Skan          ++acquired;
105169689Skan          return true;
106169689Skan        }
107169689Skan      }
108169689Skan
109169689Skan      bool release() {
110169689Skan        if (!mt_only || llvm_is_multithreaded()) {
111169689Skan          return MutexImpl::release();
112169689Skan        } else {
113169689Skan          // Single-threaded debugging code.  This would be racy in
114169689Skan          // multithreaded mode, but provides not sanity checks in single
115169689Skan          // threaded mode.
116169689Skan          assert(((recursive && acquired) || (acquired == 1)) &&
117169689Skan                 "Lock not acquired before release!");
118169689Skan          --acquired;
119169689Skan          return true;
120169689Skan        }
121169689Skan      }
122169689Skan
123169689Skan      bool tryacquire() {
124169689Skan        if (!mt_only || llvm_is_multithreaded())
125169689Skan          return MutexImpl::tryacquire();
126169689Skan        else return true;
127169689Skan      }
128169689Skan
129169689Skan      private:
130169689Skan        SmartMutex(const SmartMutex<mt_only> & original);
131169689Skan        void operator=(const SmartMutex<mt_only> &);
132169689Skan    };
133169689Skan
134169689Skan    /// Mutex - A standard, always enforced mutex.
135169689Skan    typedef SmartMutex<false> Mutex;
136169689Skan
137169689Skan    template<bool mt_only>
138169689Skan    class SmartScopedLock  {
139169689Skan      SmartMutex<mt_only>& mtx;
140169689Skan
141169689Skan    public:
142169689Skan      SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
143169689Skan        mtx.acquire();
144169689Skan      }
145169689Skan
146169689Skan      ~SmartScopedLock() {
147169689Skan        mtx.release();
148169689Skan      }
149169689Skan    };
150169689Skan
151169689Skan    typedef SmartScopedLock<false> ScopedLock;
152169689Skan  }
153169689Skan}
154169689Skan
155169689Skan#endif
156169689Skan