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