153ca1f3190680f3e86aebe0f72f7918d63f71e0dCharles Davis//===- llvm/Support/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
14674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_SUPPORT_MUTEX_H
15674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_SUPPORT_MUTEX_H
16b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
17f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper#include "llvm/Support/Compiler.h"
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h"
19cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson#include <cassert>
20b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
21b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencernamespace llvm
22b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer{
23b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  namespace sys
24b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  {
25b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @brief Platform agnostic Mutex class.
26b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    class MutexImpl
27b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    {
28b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Constructors
29b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
30b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    public:
31b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
32b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Initializes the lock but doesn't acquire it. if \p recursive is set
33b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// to false, the lock will not be recursive which makes it cheaper but
34b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// also more likely to deadlock (same thread can't acquire more than
35b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// once).
36b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Default Constructor.
37b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      explicit MutexImpl(bool recursive = true);
38b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
39b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Releases and removes the lock
40b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Destructor
41b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      ~MutexImpl();
42b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
43b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
44b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Methods
45b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
46b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    public:
47b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
48b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to unconditionally acquire the lock. If the lock is held by
49b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// another thread, this method will wait until it can acquire the lock.
50b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs, true otherwise.
51b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Unconditionally acquire the lock.
52b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      bool acquire();
53b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
54b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to release the lock. If the lock is held by the current
55b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// thread, the lock is released allowing other threads to acquire the
569eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen      /// lock.
57b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs, true otherwise.
58b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Unconditionally release the lock.
59e98fc32b0d80663aff215e328bcd297b3141b565Dan Gohman      bool release();
60b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
61b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// Attempts to acquire the lock without blocking. If the lock is not
62b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// available, this function returns false quickly (without blocking). If
63b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// the lock is available, it is acquired.
64b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @returns false if any kind of error occurs or the lock is not
65b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// available, true otherwise.
66b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      /// @brief Try to acquire the lock.
67b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer      bool tryacquire();
689eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen
69b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    //@}
70b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Platform Dependent Data
71b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
72b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    private:
736d2352249af8853c8307a7cf679017b32d27958cJeff Cohen      void* data_; ///< We don't know what the data will be
74b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
75b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
76b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @name Do Not Implement
77b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @{
789eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen    private:
79f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper      MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION;
80f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper      void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION;
81b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    /// @}
82b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer    };
831f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
841f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
851f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer    /// SmartMutex - A mutex with a compile time constant parameter that
86b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// indicates whether this mutex should become a no-op when we're not
87b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// running in multithreaded mode.
88b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    template<bool mt_only>
89f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson    class SmartMutex : public MutexImpl {
90cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      unsigned acquired;
91cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      bool recursive;
92b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    public:
93cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson      explicit SmartMutex(bool rec = true) :
94cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson        MutexImpl(rec), acquired(0), recursive(rec) { }
951f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
96b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool acquire() {
97740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        if (!mt_only || llvm_is_multithreaded()) {
98f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::acquire();
99740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        } else {
100740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // Single-threaded debugging code.  This would be racy in
101740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // multithreaded mode, but provides not sanity checks in single
102740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // threaded mode.
103740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          assert((recursive || acquired == 0) && "Lock already acquired!!");
104740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          ++acquired;
105740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          return true;
106740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        }
107b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
108b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
109b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool release() {
110740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        if (!mt_only || llvm_is_multithreaded()) {
111f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::release();
112740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        } else {
113740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // Single-threaded debugging code.  This would be racy in
114740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // multithreaded mode, but provides not sanity checks in single
115740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          // threaded mode.
116740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          assert(((recursive && acquired) || (acquired == 1)) &&
117740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands                 "Lock not acquired before release!");
118740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          --acquired;
119740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands          return true;
120740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        }
121b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
122b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson
123b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      bool tryacquire() {
124f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson        if (!mt_only || llvm_is_multithreaded())
125f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson          return MutexImpl::tryacquire();
126740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands        else return true;
127b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      }
1281f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
129b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson      private:
130f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson        SmartMutex(const SmartMutex<mt_only> & original);
131b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson        void operator=(const SmartMutex<mt_only> &);
132b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    };
1331f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
134b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    /// Mutex - A standard, always enforced mutex.
135b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson    typedef SmartMutex<false> Mutex;
1361f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1373c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    template<bool mt_only>
1383c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    class SmartScopedLock  {
139a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson      SmartMutex<mt_only>& mtx;
1401f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1413c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    public:
142a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson      SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
143a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson        mtx.acquire();
1443c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      }
1451f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1463c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      ~SmartScopedLock() {
147a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson        mtx.release();
1483c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson      }
1493c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    };
1501f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
1513c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson    typedef SmartScopedLock<false> ScopedLock;
152b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer  }
153b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer}
154b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer
155b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer#endif
156