1 /* 2 * Copyright (C) 2016 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 18 #ifndef android_hardware_automotive_vehicle_V2_0_VehicleObjectPool_H_ 19 #define android_hardware_automotive_vehicle_V2_0_VehicleObjectPool_H_ 20 21 #include <deque> 22 #include <map> 23 #include <mutex> 24 25 #include <android/hardware/automotive/vehicle/2.0/types.h> 26 27 namespace android { 28 namespace hardware { 29 namespace automotive { 30 namespace vehicle { 31 namespace V2_0 { 32 33 // Handy metric mostly for unit tests and debug. 34 #define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++; 35 struct PoolStats { 36 std::atomic<uint32_t> Obtained {0}; 37 std::atomic<uint32_t> Created {0}; 38 std::atomic<uint32_t> Recycled {0}; 39 instancePoolStats40 static PoolStats* instance() { 41 static PoolStats inst; 42 return &inst; 43 } 44 }; 45 46 template<typename T> 47 struct Deleter { 48 using OnDeleteFunc = std::function<void(T*)>; 49 DeleterDeleter50 Deleter(const OnDeleteFunc& f) : mOnDelete(f) {}; 51 52 Deleter() = default; 53 Deleter(const Deleter&) = default; 54 operatorDeleter55 void operator()(T* o) { 56 mOnDelete(o); 57 } 58 private: 59 OnDeleteFunc mOnDelete; 60 }; 61 62 /** 63 * This is std::unique_ptr<> with custom delete operation that typically moves 64 * the pointer it holds back to ObjectPool. 65 */ 66 template <typename T> 67 using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>; 68 69 /** 70 * Generic abstract object pool class. Users of this class must implement 71 * #createObject method. 72 * 73 * This class is thread-safe. Concurrent calls to #obtain(...) method from 74 * multiple threads is OK, also client can obtain an object in one thread and 75 * then move ownership to another thread. 76 * 77 */ 78 template<typename T> 79 class ObjectPool { 80 public: 81 ObjectPool() = default; 82 virtual ~ObjectPool() = default; 83 obtain()84 virtual recyclable_ptr<T> obtain() { 85 std::lock_guard<std::mutex> g(mLock); 86 INC_METRIC_IF_DEBUG(Obtained) 87 if (mObjects.empty()) { 88 INC_METRIC_IF_DEBUG(Created) 89 return wrap(createObject()); 90 } 91 92 auto o = wrap(mObjects.front().release()); 93 mObjects.pop_front(); 94 95 return o; 96 } 97 98 ObjectPool& operator =(const ObjectPool &) = delete; 99 ObjectPool(const ObjectPool &) = delete; 100 101 protected: 102 virtual T* createObject() = 0; 103 recycle(T * o)104 virtual void recycle(T* o) { 105 INC_METRIC_IF_DEBUG(Recycled) 106 std::lock_guard<std::mutex> g(mLock); 107 mObjects.push_back(std::unique_ptr<T> { o } ); 108 } 109 110 private: getDeleter()111 const Deleter<T>& getDeleter() { 112 if (!mDeleter.get()) { 113 Deleter<T> *d = new Deleter<T>(std::bind( 114 &ObjectPool::recycle, this, std::placeholders::_1)); 115 mDeleter.reset(d); 116 } 117 return *mDeleter.get(); 118 } 119 wrap(T * raw)120 recyclable_ptr<T> wrap(T* raw) { 121 return recyclable_ptr<T> { raw, getDeleter() }; 122 } 123 124 private: 125 mutable std::mutex mLock; 126 std::deque<std::unique_ptr<T>> mObjects; 127 std::unique_ptr<Deleter<T>> mDeleter; 128 }; 129 130 /** 131 * This class provides a pool of recycable VehiclePropertyValue objects. 132 * 133 * It has only one overloaded public method - obtain(...), users must call this 134 * method when new object is needed with given VehiclePropertyType and vector 135 * size (for vector properties). This method returns a recycable smart pointer 136 * to VehiclePropertyValue, essentially this is a std::unique_ptr with custom 137 * delete function, so recycable object has only one owner and developers can 138 * safely pass it around. Once this object goes out of scope, it will be 139 * returned the the object pool. 140 * 141 * Some objects are not recycable: strings and vector data types with 142 * vector length > maxRecyclableVectorSize (provided in the constructor). These 143 * objects will be deleted immediately once the go out of scope. There's no 144 * synchornization penalty for these objects since we do not store them in the 145 * pool. 146 * 147 * This class is thread-safe. Users can obtain an object in one thread and pass 148 * it to another. 149 * 150 * Sample usage: 151 * 152 * VehiclePropValuePool pool; 153 * auto v = pool.obtain(VehiclePropertyType::INT32); 154 * v->propId = VehicleProperty::HVAC_FAN_SPEED; 155 * v->areaId = VehicleAreaSeat::ROW_1_LEFT; 156 * v->timestamp = elapsedRealtimeNano(); 157 * v->value->int32Values[0] = 42; 158 * 159 * 160 */ 161 class VehiclePropValuePool { 162 public: 163 using RecyclableType = recyclable_ptr<VehiclePropValue>; 164 165 /** 166 * Creates VehiclePropValuePool 167 * 168 * @param maxRecyclableVectorSize - vector value types (e.g. 169 * VehiclePropertyType::INT32_VEC) with size equal or less to this value 170 * will be stored in the pool. If users tries to obtain value with vector 171 * size greater than maxRecyclableVectorSize user will receive appropriate 172 * object, but once it goes out of scope it will be deleted immediately, not 173 * returning back to the object pool. 174 * 175 */ 176 VehiclePropValuePool(size_t maxRecyclableVectorSize = 4) : mMaxRecyclableVectorSize(maxRecyclableVectorSize)177 mMaxRecyclableVectorSize(maxRecyclableVectorSize) {}; 178 179 RecyclableType obtain(VehiclePropertyType type); 180 181 RecyclableType obtain(VehiclePropertyType type, size_t vecSize); 182 RecyclableType obtain(const VehiclePropValue& src); 183 RecyclableType obtainBoolean(bool value); 184 RecyclableType obtainInt32(int32_t value); 185 RecyclableType obtainInt64(int64_t value); 186 RecyclableType obtainFloat(float value); 187 RecyclableType obtainString(const char* cstr); 188 RecyclableType obtainComplex(); 189 190 VehiclePropValuePool(VehiclePropValuePool& ) = delete; 191 VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete; 192 private: isDisposable(VehiclePropertyType type,size_t vecSize)193 bool isDisposable(VehiclePropertyType type, size_t vecSize) const { 194 return vecSize > mMaxRecyclableVectorSize || VehiclePropertyType::STRING == type || 195 VehiclePropertyType::MIXED == type; 196 } 197 198 RecyclableType obtainDisposable(VehiclePropertyType valueType, 199 size_t vectorSize) const; 200 RecyclableType obtainRecylable(VehiclePropertyType type, 201 size_t vecSize); 202 203 class InternalPool: public ObjectPool<VehiclePropValue> { 204 public: InternalPool(VehiclePropertyType type,size_t vectorSize)205 InternalPool(VehiclePropertyType type, size_t vectorSize) 206 : mPropType(type), mVectorSize(vectorSize) {} 207 obtain()208 RecyclableType obtain() { 209 return ObjectPool<VehiclePropValue>::obtain(); 210 } 211 protected: 212 VehiclePropValue* createObject() override; 213 void recycle(VehiclePropValue* o) override; 214 private: 215 bool check(VehiclePropValue::RawValue* v); 216 217 template <typename VecType> check(hidl_vec<VecType> * vec,bool expected)218 bool check(hidl_vec<VecType>* vec, bool expected) { 219 return vec->size() == (expected ? mVectorSize : 0); 220 } 221 private: 222 VehiclePropertyType mPropType; 223 size_t mVectorSize; 224 }; 225 226 private: 227 const Deleter<VehiclePropValue> mDisposableDeleter { 228 [] (VehiclePropValue* v) { 229 delete v; 230 } 231 }; 232 233 private: 234 mutable std::mutex mLock; 235 const size_t mMaxRecyclableVectorSize; 236 std::map<int32_t, std::unique_ptr<InternalPool>> mValueTypePools; 237 }; 238 239 } // namespace V2_0 240 } // namespace vehicle 241 } // namespace automotive 242 } // namespace hardware 243 } // namespace android 244 245 #endif // android_hardware_automotive_vehicle_V2_0_VehicleObjectPool_H_ 246