brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 09b3aac Raw
102 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9//===----------------------------------------------------------------------===//10 11#ifndef OMPTARGET_EXCLUSIVE_ACCESS12#define OMPTARGET_EXCLUSIVE_ACCESS13 14#include <cassert>15#include <cstddef>16#include <cstdint>17#include <mutex>18 19/// Forward declaration.20template <typename Ty> struct Accessor;21 22/// A protected object is a simple wrapper to allocate an object of type \p Ty23/// together with a mutex that guards accesses to the object. The only way to24/// access the object is through the "exclusive accessor" which will lock the25/// mutex accordingly.26template <typename Ty> struct ProtectedObj {27  using AccessorTy = Accessor<Ty>;28 29  /// Get an exclusive access Accessor object. \p DoNotGetAccess allows to30  /// create an accessor that is not owning anything based on a boolean31  /// condition.32  AccessorTy getExclusiveAccessor(bool DoNotGetAccess = false);33 34private:35  Ty Obj;36  std::mutex Mtx;37  friend struct Accessor<Ty>;38};39 40/// Helper to provide transparent exclusive access to protected objects.41template <typename Ty> struct Accessor {42  /// Default constructor does not own anything and cannot access anything.43  Accessor() : Ptr(nullptr) {}44 45  /// Constructor to get exclusive access by locking the mutex protecting the46  /// underlying object.47  Accessor(ProtectedObj<Ty> &PO) : Ptr(&PO) { lock(); }48 49  /// Constructor to get exclusive access by taking it from \p Other.50  Accessor(Accessor<Ty> &&Other) : Ptr(Other.Ptr) { Other.Ptr = nullptr; }51 52  Accessor(Accessor &Other) = delete;53 54  /// If the object is still owned when the lifetime ends we give up access.55  ~Accessor() { unlock(); }56 57  /// Give up access to the underlying object, virtually "destroying" the58  /// accessor even if the object is still life.59  void destroy() {60    unlock();61    Ptr = nullptr;62  }63 64  /// Provide transparent access to the underlying object.65  Ty &operator*() {66    assert(Ptr && "Trying to access an object through a non-owning (or "67                  "destroyed) accessor!");68    return Ptr->Obj;69  }70  Ty *operator->() {71    assert(Ptr && "Trying to access an object through a non-owning (or "72                  "destroyed) accessor!");73    return &Ptr->Obj;74  }75 76private:77  /// Lock the underlying object if there is one.78  void lock() {79    if (Ptr)80      Ptr->Mtx.lock();81  }82 83  /// Unlock the underlying object if there is one.84  void unlock() {85    if (Ptr)86      Ptr->Mtx.unlock();87  }88 89  /// Pointer to the underlying object or null if the accessor lost access,90  /// e.g., after a destroy call.91  ProtectedObj<Ty> *Ptr;92};93 94template <typename Ty>95Accessor<Ty> ProtectedObj<Ty>::getExclusiveAccessor(bool DoNotGetAccess) {96  if (DoNotGetAccess)97    return Accessor<Ty>();98  return Accessor<Ty>(*this);99}100 101#endif102