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