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