1bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski/*
2bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * Copyright (C) 2017 The Android Open Source Project
3bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski *
4bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * you may not use this file except in compliance with the License.
6bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * You may obtain a copy of the License at
7bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski *
8bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski *
10bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * See the License for the specific language governing permissions and
14bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski * limitations under the License.
15bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski */
16bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
17bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#ifndef ANDROIDFW_MUTEXGUARD_H
18bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#define ANDROIDFW_MUTEXGUARD_H
19bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
20bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#include <mutex>
21bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#include <type_traits>
22bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
23bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#include "android-base/macros.h"
24bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
25bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskinamespace android {
26bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
27bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskitemplate <typename T>
28bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskiclass ScopedLock;
29bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
30bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// Owns the guarded object and protects access to it via a mutex.
31bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// The guarded object is inaccessible via this class.
32bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// The mutex is locked and the object accessed via the ScopedLock<T> class.
33bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//
34bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// NOTE: The template parameter T should not be a raw pointer, since ownership
35bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// is ambiguous and error-prone. Instead use an std::unique_ptr<>.
36bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//
37bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski// Example use:
38bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//
39bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//   Guarded<std::string> shared_string("hello");
40bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//   {
41bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//     ScopedLock<std::string> locked_string(shared_string);
42bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//     *locked_string += " world";
43bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//   }
44bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski//
45bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskitemplate <typename T>
46bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskiclass Guarded {
47bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
48bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
49bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski public:
50bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  explicit Guarded() : guarded_() {
51bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
52bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
53bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  template <typename U = T>
54bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  explicit Guarded(const T& guarded,
55bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski                   typename std::enable_if<std::is_copy_constructible<U>::value>::type = void())
56bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski      : guarded_(guarded) {
57bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
58bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
59bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  template <typename U = T>
60bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  explicit Guarded(T&& guarded,
61bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski                   typename std::enable_if<std::is_move_constructible<U>::value>::type = void())
62bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski      : guarded_(std::move(guarded)) {
63bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
64bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
65bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski private:
66bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  friend class ScopedLock<T>;
67bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
68bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(Guarded);
69bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
70bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  std::mutex lock_;
71bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  T guarded_;
72bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski};
73bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
74bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskitemplate <typename T>
75bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinskiclass ScopedLock {
76bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski public:
77bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  explicit ScopedLock(Guarded<T>& guarded) : lock_(guarded.lock_), guarded_(guarded.guarded_) {
78bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
79bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
80bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  T& operator*() {
81bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski    return guarded_;
82bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
83bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
84bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  T* operator->() {
85bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski    return &guarded_;
86bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
87bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
88bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  T* get() {
89bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski    return &guarded_;
90bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  }
91bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
92bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski private:
93bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
94bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
95bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  std::lock_guard<std::mutex> lock_;
96bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski  T& guarded_;
97bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski};
98bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
99bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski}  // namespace android
100bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski
101bebfcc46a249a70af04bc18490a897888a142fb8Adam Lesinski#endif  // ANDROIDFW_MUTEXGUARD_H
102