Home | History | Annotate | Download | only in vhal_v2_0
      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 
     40     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 
     50     Deleter(const OnDeleteFunc& f) : mOnDelete(f) {};
     51 
     52     Deleter() = default;
     53     Deleter(const Deleter&) = default;
     54 
     55     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 
     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 
    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:
    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 
    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) :
    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:
    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:
    205         InternalPool(VehiclePropertyType type, size_t vectorSize)
    206             : mPropType(type), mVectorSize(vectorSize) {}
    207 
    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>
    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