Last active
April 16, 2022 04:04
-
-
Save mightbxg/e52d67c2cdcea11ec9ac512b72986090 to your computer and use it in GitHub Desktop.
Object pool in c++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///@brief Object pool that manages objects with std::shared_ptr. | |
///@note The object will be reused only when it's released outside the pool. | |
template <typename T> | |
class SharedPtrObjectPool { | |
protected: | |
struct CalleeHelper { | |
}; | |
public: | |
using Ptr = std::shared_ptr<T>; | |
SharedPtrObjectPool() | |
: iter_(objects_.end()) | |
{ | |
} | |
///@brief Release all objects managed by this pool. | |
void reset() | |
{ | |
objects_.clear(); | |
iter_ = objects_.end(); | |
} | |
///@brief Get num of objects in this pool. | |
[[nodiscard]] size_t capacity() const | |
{ | |
return objects_.size(); | |
} | |
///@brief Retrieve one object with given initializing arguments. | |
/// The arguments will be passed to constructor if a new object is created. | |
/// And if an old object is reused, \p reset function will be called with these args. | |
///@param reset The member function of T that takes the same arguments as the constructor. | |
///@param args The arguments passed to constructor or \p reset. | |
///@return The retrieved object (shared_ptr). | |
template <typename Functor = CalleeHelper, typename... Args> | |
Ptr get(Functor reset = {}, Args&&... args) | |
{ | |
if (objects_.empty()) { | |
return objects_.emplace_back(std::make_shared<T>(std::forward<Args>(args)...)); | |
} | |
if (iter_ == objects_.end()) { | |
// list end reached, move iterator to the beginning. | |
iter_ = objects_.begin(); | |
} | |
// look for a vacant object | |
for (size_t i = 0; i < objects_.size(); ++i) { | |
if (iter_->use_count() == 1) { | |
// call reset function with given parameters | |
if constexpr (!std::is_same_v<Functor, CalleeHelper>) { | |
static_assert(std::is_invocable<Functor, T&, Args...>::value, "Reset function not invocable with given args!"); | |
std::invoke(reset, **iter_, std::forward<Args>(args)...); | |
} | |
break; | |
} | |
if (++iter_ == objects_.end()) { | |
iter_ = objects_.begin(); | |
} | |
} | |
if (iter_->use_count() > 1) { | |
// no vacant object found, construct a new one. | |
iter_ = objects_.emplace(std::next(iter_), std::make_shared<T>(std::forward<Args>(args)...)); | |
} | |
return *(iter_++); | |
} | |
protected: | |
std::list<Ptr> objects_; | |
typename std::list<Ptr>::iterator iter_; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment