Mutex.h revision 1f6efa3996dd1929fbc129203ce5009b620e6969
1b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//===- llvm/System/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===//
2b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//
3b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//                     The LLVM Compiler Infrastructure
4b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
7b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//
8b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//===----------------------------------------------------------------------===//
9b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//
10b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// This file declares the llvm::sys::Mutex class.
11b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//
12b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//===----------------------------------------------------------------------===//
13b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
14b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer#ifndef LLVM_SYSTEM_MUTEX_H
15b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer#define LLVM_SYSTEM_MUTEX_H
16b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h"
18cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson#include <cassert>
19b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
20b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencernamespace llvm
21b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer{
22b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  namespace sys
23b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  {
24b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @brief Platform agnostic Mutex class.
25b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    class MutexImpl
26b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    {
27b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Constructors
28b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
29b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    public:
30b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
31b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Initializes the lock but doesn't acquire it. if \p recursive is set
32b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// to false, the lock will not be recursive which makes it cheaper but
33b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// also more likely to deadlock (same thread can't acquire more than
34b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// once).
35b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Default Constructor.
36b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      explicit MutexImpl(bool recursive = true);
37b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
38b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Releases and removes the lock
39b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Destructor
40b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      ~MutexImpl();
41b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
42b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
43b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Methods
44b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
45b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    public:
46b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
47b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to unconditionally acquire the lock. If the lock is held by
48b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// another thread, this method will wait until it can acquire the lock.
49b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs, true otherwise.
50b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Unconditionally acquire the lock.
51b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      bool acquire();
52b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
53b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to release the lock. If the lock is held by the current
54b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// thread, the lock is released allowing other threads to acquire the
559eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen      /// lock.
56b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs, true otherwise.
57b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Unconditionally release the lock.
58e98fc32b0d80663aff215e328bcd297b3141b565Dan Gohman      bool release();
59b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
60b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to acquire the lock without blocking. If the lock is not
61b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// available, this function returns false quickly (without blocking). If
62b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// the lock is available, it is acquired.
63b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs or the lock is not
64b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// available, true otherwise.
65b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Try to acquire the lock.
66b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      bool tryacquire();
679eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen
68b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    //@}
69b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Platform Dependent Data
70b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
71b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    private:
726d2352249af8853c8307a7cf679017b32d27958cJeff Cohen      void* data_; ///< We don't know what the data will be
73b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
74b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
75b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Do Not Implement
76b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
779eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen    private:
78b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      MutexImpl(const MutexImpl & original);
79b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      void operator=(const MutexImpl &);
80b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
81b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    };
821f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
831f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
841f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer    /// SmartMutex - A mutex with a compile time constant parameter that
85b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// indicates whether this mutex should become a no-op when we're not
86b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// running in multithreaded mode.
87b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    template<bool mt_only>
88f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson    class SmartMutex : public MutexImpl {
89cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      unsigned acquired;
90cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      bool recursive;
91b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    public:
92cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      explicit SmartMutex(bool rec = true) :
93cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson        MutexImpl(rec), acquired(0), recursive(rec) { }
941f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
95b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool acquire() {
96740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        if (!mt_only || llvm_is_multithreaded()) {
97f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::acquire();
98740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        } else {
99740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // Single-threaded debugging code.  This would be racy in
100740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // multithreaded mode, but provides not sanity checks in single
101740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // threaded mode.
102740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          assert((recursive || acquired == 0) && "Lock already acquired!!");
103740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          ++acquired;
104740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          return true;
105740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        }
106b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
107b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
108b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool release() {
109740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        if (!mt_only || llvm_is_multithreaded()) {
110f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::release();
111740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        } else {
112740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // Single-threaded debugging code.  This would be racy in
113740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // multithreaded mode, but provides not sanity checks in single
114740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // threaded mode.
115740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          assert(((recursive && acquired) || (acquired == 1)) &&
116740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands                 "Lock not acquired before release!");
117740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          --acquired;
118740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          return true;
119740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        }
120b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
121b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
122b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool tryacquire() {
123f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson        if (!mt_only || llvm_is_multithreaded())
124f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::tryacquire();
125740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        else return true;
126b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
1271f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
128b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      private:
129f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson        SmartMutex(const SmartMutex<mt_only> & original);
130b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson        void operator=(const SmartMutex<mt_only> &);
131b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    };
1321f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
133b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// Mutex - A standard, always enforced mutex.
134b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    typedef SmartMutex<false> Mutex;
1351f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1363c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    template<bool mt_only>
1373c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    class SmartScopedLock  {
138a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson      SmartMutex<mt_only>& mtx;
1391f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1403c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    public:
141a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson      SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
142a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson        mtx.acquire();
1433c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      }
1441f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1453c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      ~SmartScopedLock() {
146a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson        mtx.release();
1473c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      }
1483c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    };
1491f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1503c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    typedef SmartScopedLock<false> ScopedLock;
151b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  }
152b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer}
153b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
154b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer#endif
155