1 /* 2 ** 3 ** Copyright 2018, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_CONCURRENCY_H_ 19 #define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_CONCURRENCY_H_ 20 21 #include <type_traits> 22 23 namespace keystore { 24 25 template <typename LockedType> class UnlockProxyLockHelper { 26 private: 27 std::function<void(LockedType*)> unlock_; 28 LockedType* value_; 29 30 public: 31 using lockedType = LockedType; UnlockProxyLockHelper()32 UnlockProxyLockHelper() : value_(nullptr) {} UnlockProxyLockHelper(LockedType * value,std::function<void (LockedType *)> && unlock)33 UnlockProxyLockHelper(LockedType* value, std::function<void(LockedType*)>&& unlock) 34 : unlock_(std::move(unlock)), value_(value) {} ~UnlockProxyLockHelper()35 ~UnlockProxyLockHelper() { 36 if (unlock_) unlock_(value_); 37 } UnlockProxyLockHelper(UnlockProxyLockHelper && rhs)38 UnlockProxyLockHelper(UnlockProxyLockHelper&& rhs) 39 : unlock_(std::move(rhs.unlock_)), value_(rhs.value_) { 40 rhs.value_ = nullptr; 41 rhs.unlock_ = {}; 42 } 43 UnlockProxyLockHelper& operator=(UnlockProxyLockHelper&& rhs) { 44 if (this != &rhs) { 45 UnlockProxyLockHelper dummy(std::move(*this)); 46 unlock_ = std::move(rhs.unlock_); 47 value_ = std::move(rhs.value_); 48 rhs.value_ = nullptr; 49 rhs.unlock_ = {}; 50 } 51 return *this; 52 } 53 UnlockProxyLockHelper(const UnlockProxyLockHelper& rhs) = delete; 54 UnlockProxyLockHelper& operator=(const UnlockProxyLockHelper& rhs) = delete; 55 56 template <typename T = LockedType> value()57 std::enable_if_t<!std::is_const<LockedType>::value, T*> value() { 58 return value_; 59 } value()60 const LockedType* value() const { return value_; } 61 }; 62 63 template <typename LockedType, typename MutexType, template <typename> class GuardType> 64 class MutexProxyLockHelper { 65 private: 66 GuardType<MutexType> lock_; 67 LockedType* value_; 68 69 public: 70 using lockedType = LockedType; MutexProxyLockHelper()71 MutexProxyLockHelper() : value_(nullptr) {} MutexProxyLockHelper(LockedType * value,GuardType<MutexType> && lock)72 MutexProxyLockHelper(LockedType* value, GuardType<MutexType>&& lock) 73 : lock_(std::move(lock)), value_(value) {} 74 75 template <typename T = LockedType> value()76 std::enable_if_t<!std::is_const<LockedType>::value, T*> value() { 77 return value_; 78 } value()79 const LockedType* value() const { return value_; } 80 }; 81 82 template <typename Implementation> class ProxyLock { 83 private: 84 Implementation impl_; 85 86 public: ProxyLock()87 ProxyLock() : impl_() {} 88 // NOLINTNEXTLINE(google-explicit-constructor) ProxyLock(Args &&...args)89 template <typename... Args> ProxyLock(Args&&... args) : impl_{std::forward<Args>(args)...} {} ProxyLock(Implementation && impl)90 explicit ProxyLock(Implementation&& impl) : impl_(std::move(impl)) {} 91 explicit operator bool() const { return impl_.value() != nullptr; } 92 93 template <typename T = typename Implementation::lockedType> 94 std::enable_if_t<!std::is_const<typename Implementation::lockedType>::value, T*> operator->() { 95 return impl_.value(); 96 } 97 98 template <typename T = typename Implementation::lockedType> 99 std::enable_if_t<!std::is_const<typename Implementation::lockedType>::value, T&> operator*() { 100 return *impl_.value(); 101 } 102 103 const std::remove_const_t<typename Implementation::lockedType>* operator->() const { 104 return impl_.value(); 105 } 106 107 const std::remove_const_t<typename Implementation::lockedType>& operator*() const { 108 return *impl_.value(); 109 } 110 }; 111 112 } // namespace keystore 113 114 #endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_CONCURRENCY_H_ 115