1*8222fbe1SAndroid Build Coastguard Worker /* 2*8222fbe1SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*8222fbe1SAndroid Build Coastguard Worker * 4*8222fbe1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*8222fbe1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*8222fbe1SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*8222fbe1SAndroid Build Coastguard Worker * 8*8222fbe1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*8222fbe1SAndroid Build Coastguard Worker * 10*8222fbe1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*8222fbe1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*8222fbe1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*8222fbe1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*8222fbe1SAndroid Build Coastguard Worker * limitations under the License. 15*8222fbe1SAndroid Build Coastguard Worker */ 16*8222fbe1SAndroid Build Coastguard Worker #ifndef ANDROID_HIDL_CONCURRENT_MAP_H 17*8222fbe1SAndroid Build Coastguard Worker #define ANDROID_HIDL_CONCURRENT_MAP_H 18*8222fbe1SAndroid Build Coastguard Worker 19*8222fbe1SAndroid Build Coastguard Worker #include <mutex> 20*8222fbe1SAndroid Build Coastguard Worker #include <map> 21*8222fbe1SAndroid Build Coastguard Worker 22*8222fbe1SAndroid Build Coastguard Worker namespace android { 23*8222fbe1SAndroid Build Coastguard Worker namespace hardware { 24*8222fbe1SAndroid Build Coastguard Worker 25*8222fbe1SAndroid Build Coastguard Worker template<typename K, typename V> 26*8222fbe1SAndroid Build Coastguard Worker class ConcurrentMap { 27*8222fbe1SAndroid Build Coastguard Worker private: 28*8222fbe1SAndroid Build Coastguard Worker using size_type = typename std::map<K, V>::size_type; 29*8222fbe1SAndroid Build Coastguard Worker using iterator = typename std::map<K, V>::iterator; 30*8222fbe1SAndroid Build Coastguard Worker using const_iterator = typename std::map<K, V>::const_iterator; 31*8222fbe1SAndroid Build Coastguard Worker 32*8222fbe1SAndroid Build Coastguard Worker public: set(K && k,V && v)33*8222fbe1SAndroid Build Coastguard Worker void set(K &&k, V &&v) { 34*8222fbe1SAndroid Build Coastguard Worker std::unique_lock<std::mutex> _lock(mMutex); 35*8222fbe1SAndroid Build Coastguard Worker mMap[std::forward<K>(k)] = std::forward<V>(v); 36*8222fbe1SAndroid Build Coastguard Worker } 37*8222fbe1SAndroid Build Coastguard Worker 38*8222fbe1SAndroid Build Coastguard Worker // get with the given default value. get(const K & k,const V & def)39*8222fbe1SAndroid Build Coastguard Worker const V &get(const K &k, const V &def) const { 40*8222fbe1SAndroid Build Coastguard Worker std::unique_lock<std::mutex> _lock(mMutex); 41*8222fbe1SAndroid Build Coastguard Worker const_iterator iter = mMap.find(k); 42*8222fbe1SAndroid Build Coastguard Worker if (iter == mMap.end()) { 43*8222fbe1SAndroid Build Coastguard Worker return def; 44*8222fbe1SAndroid Build Coastguard Worker } 45*8222fbe1SAndroid Build Coastguard Worker return iter->second; 46*8222fbe1SAndroid Build Coastguard Worker } 47*8222fbe1SAndroid Build Coastguard Worker erase(const K & k)48*8222fbe1SAndroid Build Coastguard Worker size_type erase(const K &k) { 49*8222fbe1SAndroid Build Coastguard Worker std::unique_lock<std::mutex> _lock(mMutex); 50*8222fbe1SAndroid Build Coastguard Worker return mMap.erase(k); 51*8222fbe1SAndroid Build Coastguard Worker } 52*8222fbe1SAndroid Build Coastguard Worker eraseIfEqual(const K & k,const V & v)53*8222fbe1SAndroid Build Coastguard Worker size_type eraseIfEqual(const K& k, const V& v) { 54*8222fbe1SAndroid Build Coastguard Worker std::unique_lock<std::mutex> _lock(mMutex); 55*8222fbe1SAndroid Build Coastguard Worker const_iterator iter = mMap.find(k); 56*8222fbe1SAndroid Build Coastguard Worker if (iter == mMap.end()) { 57*8222fbe1SAndroid Build Coastguard Worker return 0; 58*8222fbe1SAndroid Build Coastguard Worker } 59*8222fbe1SAndroid Build Coastguard Worker if (iter->second == v) { 60*8222fbe1SAndroid Build Coastguard Worker mMap.erase(iter); 61*8222fbe1SAndroid Build Coastguard Worker return 1; 62*8222fbe1SAndroid Build Coastguard Worker } else { 63*8222fbe1SAndroid Build Coastguard Worker return 0; 64*8222fbe1SAndroid Build Coastguard Worker } 65*8222fbe1SAndroid Build Coastguard Worker } 66*8222fbe1SAndroid Build Coastguard Worker lock()67*8222fbe1SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(mMutex); } 68*8222fbe1SAndroid Build Coastguard Worker setLocked(const K & k,V && v)69*8222fbe1SAndroid Build Coastguard Worker void setLocked(const K& k, V&& v) { mMap[k] = std::forward<V>(v); } setLocked(const K & k,const V & v)70*8222fbe1SAndroid Build Coastguard Worker void setLocked(const K& k, const V& v) { mMap[k] = v; } 71*8222fbe1SAndroid Build Coastguard Worker getLocked(const K & k,const V & def)72*8222fbe1SAndroid Build Coastguard Worker const V& getLocked(const K& k, const V& def) const { 73*8222fbe1SAndroid Build Coastguard Worker const_iterator iter = mMap.find(k); 74*8222fbe1SAndroid Build Coastguard Worker if (iter == mMap.end()) { 75*8222fbe1SAndroid Build Coastguard Worker return def; 76*8222fbe1SAndroid Build Coastguard Worker } 77*8222fbe1SAndroid Build Coastguard Worker return iter->second; 78*8222fbe1SAndroid Build Coastguard Worker } 79*8222fbe1SAndroid Build Coastguard Worker eraseLocked(const K & k)80*8222fbe1SAndroid Build Coastguard Worker size_type eraseLocked(const K& k) { return mMap.erase(k); } 81*8222fbe1SAndroid Build Coastguard Worker 82*8222fbe1SAndroid Build Coastguard Worker // the concurrent map must be locked in order to iterate over it begin()83*8222fbe1SAndroid Build Coastguard Worker iterator begin() { return mMap.begin(); } end()84*8222fbe1SAndroid Build Coastguard Worker iterator end() { return mMap.end(); } begin()85*8222fbe1SAndroid Build Coastguard Worker const_iterator begin() const { return mMap.begin(); } end()86*8222fbe1SAndroid Build Coastguard Worker const_iterator end() const { return mMap.end(); } 87*8222fbe1SAndroid Build Coastguard Worker 88*8222fbe1SAndroid Build Coastguard Worker private: 89*8222fbe1SAndroid Build Coastguard Worker mutable std::mutex mMutex; 90*8222fbe1SAndroid Build Coastguard Worker std::map<K, V> mMap; 91*8222fbe1SAndroid Build Coastguard Worker }; 92*8222fbe1SAndroid Build Coastguard Worker 93*8222fbe1SAndroid Build Coastguard Worker namespace details { 94*8222fbe1SAndroid Build Coastguard Worker 95*8222fbe1SAndroid Build Coastguard Worker // TODO(b/69122224): remove this type and usages of it 96*8222fbe1SAndroid Build Coastguard Worker // DO NOT ADD USAGES 97*8222fbe1SAndroid Build Coastguard Worker template <typename T> 98*8222fbe1SAndroid Build Coastguard Worker class DoNotDestruct { 99*8222fbe1SAndroid Build Coastguard Worker public: DoNotDestruct()100*8222fbe1SAndroid Build Coastguard Worker DoNotDestruct() { new (buffer) T(); } get()101*8222fbe1SAndroid Build Coastguard Worker T& get() { return *reinterpret_cast<T*>(buffer); } 102*8222fbe1SAndroid Build Coastguard Worker T* operator->() { return reinterpret_cast<T*>(buffer); } 103*8222fbe1SAndroid Build Coastguard Worker 104*8222fbe1SAndroid Build Coastguard Worker private: 105*8222fbe1SAndroid Build Coastguard Worker alignas(T) char buffer[sizeof(T)]; 106*8222fbe1SAndroid Build Coastguard Worker }; 107*8222fbe1SAndroid Build Coastguard Worker 108*8222fbe1SAndroid Build Coastguard Worker } // namespace details 109*8222fbe1SAndroid Build Coastguard Worker 110*8222fbe1SAndroid Build Coastguard Worker } // namespace hardware 111*8222fbe1SAndroid Build Coastguard Worker } // namespace android 112*8222fbe1SAndroid Build Coastguard Worker 113*8222fbe1SAndroid Build Coastguard Worker 114*8222fbe1SAndroid Build Coastguard Worker #endif // ANDROID_HIDL_CONCURRENT_MAP_H 115