Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / openmp / libomptarget / include / ExclusiveAccess.h
blob33f59903637dbc38d3d582c1ec9b0e70f7f2bf49
1 //===---- ExclusiveAccess.h - Helper for exclusive access data structures -===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //===----------------------------------------------------------------------===//
11 #ifndef OMPTARGET_EXCLUSIVE_ACCESS
12 #define OMPTARGET_EXCLUSIVE_ACCESS
14 #include <cstddef>
15 #include <cstdint>
16 #include <mutex>
18 /// Forward declaration.
19 template <typename Ty> struct Accessor;
21 /// A protected object is a simple wrapper to allocate an object of type \p Ty
22 /// together with a mutex that guards accesses to the object. The only way to
23 /// access the object is through the "exclusive accessor" which will lock the
24 /// mutex accordingly.
25 template <typename Ty> struct ProtectedObj {
26 using AccessorTy = Accessor<Ty>;
28 /// Get an exclusive access Accessor object. \p DoNotGetAccess allows to
29 /// create an accessor that is not owning anything based on a boolean
30 /// condition.
31 AccessorTy getExclusiveAccessor(bool DoNotGetAccess = false);
33 private:
34 Ty Obj;
35 std::mutex Mtx;
36 friend struct Accessor<Ty>;
39 /// Helper to provide transparent exclusive access to protected objects.
40 template <typename Ty> struct Accessor {
41 /// Default constructor does not own anything and cannot access anything.
42 Accessor() : Ptr(nullptr) {}
44 /// Constructor to get exclusive access by locking the mutex protecting the
45 /// underlying object.
46 Accessor(ProtectedObj<Ty> &PO) : Ptr(&PO) { lock(); }
48 /// Constructor to get exclusive access by taking it from \p Other.
49 Accessor(Accessor<Ty> &&Other) : Ptr(Other.Ptr) { Other.Ptr = nullptr; }
51 Accessor(Accessor &Other) = delete;
53 /// If the object is still owned when the lifetime ends we give up access.
54 ~Accessor() { unlock(); }
56 /// Give up access to the underlying object, virtually "destroying" the
57 /// accessor even if the object is still life.
58 void destroy() {
59 unlock();
60 Ptr = nullptr;
63 /// Provide transparent access to the underlying object.
64 Ty &operator*() {
65 assert(Ptr && "Trying to access an object through a non-owning (or "
66 "destroyed) accessor!");
67 return Ptr->Obj;
69 Ty *operator->() {
70 assert(Ptr && "Trying to access an object through a non-owning (or "
71 "destroyed) accessor!");
72 return &Ptr->Obj;
75 private:
76 /// Lock the underlying object if there is one.
77 void lock() {
78 if (Ptr)
79 Ptr->Mtx.lock();
82 /// Unlock the underlying object if there is one.
83 void unlock() {
84 if (Ptr)
85 Ptr->Mtx.unlock();
88 /// Pointer to the underlying object or null if the accessor lost access,
89 /// e.g., after a destroy call.
90 ProtectedObj<Ty> *Ptr;
93 template <typename Ty>
94 Accessor<Ty> ProtectedObj<Ty>::getExclusiveAccessor(bool DoNotGetAccess) {
95 if (DoNotGetAccess)
96 return Accessor<Ty>();
97 return Accessor<Ty>(*this);
100 #endif