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