diff options
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | stats/meson.build | 6 | ||||
-rw-r--r-- | stats/shared_item_pool.cpp | 129 | ||||
-rw-r--r-- | stats/shared_item_pool.h | 114 |
4 files changed, 250 insertions, 0 deletions
diff --git a/meson.build b/meson.build index ae51789..5516434 100644 --- a/meson.build +++ b/meson.build @@ -95,6 +95,7 @@ ipu3_ipa_deps = [ subdir('aiq') subdir('data') subdir('src') +subdir('stats') mod = shared_module(ipa_name, [ipu3_ipa_files, libcamera_helpers], diff --git a/stats/meson.build b/stats/meson.build new file mode 100644 index 0000000..9707630 --- /dev/null +++ b/stats/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: CC0-1.0 + +ipu3_ipa_files += files([ + 'shared_item_pool.cpp', +]) + diff --git a/stats/shared_item_pool.cpp b/stats/shared_item_pool.cpp new file mode 100644 index 0000000..326a400 --- /dev/null +++ b/stats/shared_item_pool.cpp @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2014-2018 Intel Corporation + * + * This implementation is highly derived from ChromeOS: + * platform2/camera/hal/intel/ipu3/common/SharedItemPool.cpp + */ + +#include <ia_imaging/ia_aiq_types.h> + +#include <libcamera/base/log.h> + +#include "shared_item_pool.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(SharedItemPool) + +template<class ItemType> +SharedItemPool<ItemType>::SharedItemPool(const char *name) + : allocated_(nullptr), capacity_(0), deleter_(this), poolName_(name), + resetter_(nullptr) +{ +} + +template<class ItemType> +SharedItemPool<ItemType>::~SharedItemPool() +{ + deInit(); +} + +template<class ItemType> +int SharedItemPool<ItemType>::init(int32_t capacity, void (*resetter)(ItemType *)) +{ + if (capacity_ != 0) { + LOG(SharedItemPool, Error) << "Pool initialized already"; + return -ENOSYS; + } + std::lock_guard<std::mutex> l(mutex_); + resetter_ = resetter; + capacity_ = capacity; + available_.reserve(capacity); + allocated_ = new ItemType[capacity]; + + for (int32_t i = 0; i < capacity; i++) + available_.push_back(&allocated_[i]); + + LOG(SharedItemPool, Debug) << "Shared pool " << poolName_ << "init with " << capacity << " items"; + + return 0; +} + +template<class ItemType> +bool SharedItemPool<ItemType>::isFull() +{ + std::lock_guard<std::mutex> l(mutex_); + bool ret = (available_.size() == capacity_); + return ret; +} + +template<class ItemType> +int SharedItemPool<ItemType>::deInit() +{ + std::lock_guard<std::mutex> l(mutex_); + if (capacity_ == 0) { + LOG(SharedItemPool, Debug) << "Shared pool " << poolName_ + << " isn't initialized or already de-initialized"; + return 0; + } + if (available_.size() != capacity_) { + LOG(SharedItemPool, Error) << "Not all items are returned " + << "when destroying pool " << poolName_ + << "(" << available_.size() << "/" << capacity_ << ")"; + } + + delete[] allocated_; + allocated_ = nullptr; + available_.clear(); + capacity_ = 0; + LOG(SharedItemPool, Debug) << "Shared pool " << poolName_ + << " deinit done"; + + return 0; +} + +template<class ItemType> +int SharedItemPool<ItemType>::acquireItem(std::shared_ptr<ItemType> &item) +{ + item.reset(); + std::lock_guard<std::mutex> l(mutex_); + if (available_.empty()) { + LOG(SharedItemPool, Error) << "Shared pool " << poolName_ + << "is empty"; + return -ENOSYS; + } + + std::shared_ptr<ItemType> sh(available_[0], deleter_); + available_.erase(available_.begin()); + item = sh; + LOG(SharedItemPool, Debug) << "Shared pool " << poolName_ + << "acquire items " << sh.get(); + return 0; +} + +template<class ItemType> +size_t SharedItemPool<ItemType>::availableItems() +{ + std::lock_guard<std::mutex> l(mutex_); + size_t ret = available_.size(); + return ret; +} + +template<class ItemType> +int SharedItemPool<ItemType>::_releaseItem(ItemType *item) +{ + std::lock_guard<std::mutex> l(mutex_); + if (resetter_) + resetter_(item); + + LOG(SharedItemPool, Debug) << "Shared pool " << poolName_ + << "returning item " << item; + + available_.push_back(item); + return 0; +} + +template class SharedItemPool<ia_aiq_rgbs_grid>; +template class SharedItemPool<ia_aiq_af_grid>; +} /* namespace libcamera */ diff --git a/stats/shared_item_pool.h b/stats/shared_item_pool.h new file mode 100644 index 0000000..89dc9b3 --- /dev/null +++ b/stats/shared_item_pool.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2014-2018 Intel Corporation + * + * This implementation is highly derived from ChromeOS: + * platform2/camera/hal/intel/ipu3/common/SharedItemPool.h + */ + +#ifndef SHARED_ITEM_POOL_H +#define SHARED_ITEM_POOL_H + +#include <memory> +#include <mutex> +#include <pthread.h> +#include <vector> + +/** + * \class SharedItemPool + * + * Pool of ref counted items. This class creates a pool of items and manages + * the acquisition of them. When all references to this item have disappeared + * The item is returned to the pool. + * + * This class is thread safe, i.e. it can be called from multiple threads. + * When the element is recycled to the pool it can be reset via a client + * provided method. + * + */ + +namespace libcamera { + +template<class ItemType> +class SharedItemPool +{ +public: + SharedItemPool(const char *name = "Unnamed"); + ~SharedItemPool(); + + /** + * Initializes the capacity of the pool. It allocates the objects. + * optionally it will take function to reset the item before recycling + * it to the pool. + * This method is thread safe. + * + * \param capacity[IN]: Number of items the pool will hold + * \param resetter[IN]: Function to reset the item before recycling to the + * pool. + * \return -ENOSYS if trying to initialize twice + * \return 0 If everything went ok. + */ + int init(int32_t capacity, void (*resetter)(ItemType *) = nullptr); + + bool isFull(); + + /** + * Free the resources of the pool + * + * \return 0 on success + */ + int deInit(); + + /** + * Acquire an item from the pool. + * This method is thread safe. Access to the internal acquire/release + * methods are protected. + * BUT the thread-safety for the utilization of the item after it has been + * acquired is the user's responsibility. + * Be careful not to provide the same item to multiple threads that write + * into it. + * + * \param item[OUT] shared pointer to an item. + * \return 0 on success + */ + int acquireItem(std::shared_ptr<ItemType> &item); + + /** + * Returns the number of currently available items + * It there would be issues acquiring the lock the method returns 0 + * available items. + * + * \return item count + */ + size_t availableItems(); + +private: + int _releaseItem(ItemType *item); + + class ItemDeleter + { + public: + ItemDeleter(SharedItemPool *pool) + : mPool(pool) {} + void operator()(ItemType *item) const + { + mPool->_releaseItem(item); + } + + private: + SharedItemPool *mPool; + }; + + std::vector<ItemType *> available_; /* SharedItemPool doesn't have ownership */ + ItemType *allocated_; + size_t capacity_; + ItemDeleter deleter_; + std::mutex mutex_; /* protects available_, allocated_, capacity_ */ + const char *poolName_; + void (*resetter_)(ItemType *); +}; + +} /* namespace libcamera */ + +#endif /* SHARED_ITEM_POOL_H */ + |