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