1//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a guard for a block of code that ensures a Mutex is locked
11// upon construction and released upon destruction.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H
16#define LLVM_SUPPORT_UNIQUE_LOCK_H
17
18#include "llvm/Support/Mutex.h"
19
20namespace llvm {
21  /// A pared-down imitation of std::unique_lock from C++11. Contrary to the
22  /// name, it's really more of a wrapper for a lock. It may or may not have
23  /// an associated mutex, which is guaranteed to be locked upon creation
24  /// and unlocked after destruction. unique_lock can also unlock the mutex
25  /// and re-lock it freely during its lifetime.
26  /// @brief Guard a section of code with a mutex.
27  template<typename MutexT>
28  class unique_lock {
29    MutexT *M;
30    bool locked;
31
32    unique_lock(const unique_lock &) = delete;
33    void operator=(const unique_lock &) = delete;
34  public:
35    unique_lock() : M(nullptr), locked(false) {}
36    explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
37
38    void operator=(unique_lock &&o) {
39      if (owns_lock())
40        M->unlock();
41      M = o.M;
42      locked = o.locked;
43      o.M = nullptr;
44      o.locked = false;
45    }
46
47    ~unique_lock() { if (owns_lock()) M->unlock(); }
48
49    void lock() {
50      assert(!locked && "mutex already locked!");
51      assert(M && "no associated mutex!");
52      M->lock();
53      locked = true;
54    }
55
56    void unlock() {
57      assert(locked && "unlocking a mutex that isn't locked!");
58      assert(M && "no associated mutex!");
59      M->unlock();
60      locked = false;
61    }
62
63    bool owns_lock() { return locked; }
64  };
65}
66
67#endif // LLVM_SUPPORT_UNIQUE_LOCK_H
68