2 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
20 * An unbounded pool of resources.
21 * A `ResourcePool<T>` requires a factory function that takes allocates `T*` and
22 * a free function that frees a `T*`.
23 * Calling `ResourcePool::get()` will give you a new `ResourcePool::UniquePtr`
24 * to a `T`, and when it goes out of scope the resource will be returned to the
26 * The `ResourcePool<T>` *must* survive longer than any resources it hands out.
27 * Remember that `ResourcePool<T>` hands out mutable `T`s, so make sure to clean
28 * up the resource before or after every use.
34 using Factory = std::function<T*()>;
35 using Free = std::function<void(T*)>;
36 using UniquePtr = std::unique_ptr<T, Deleter>;
42 std::vector<T*> resources_;
47 * Creates a `ResourcePool`.
49 * @param factory The function to use to create new resources.
50 * @param free The function to use to free resources created by `factory`.
52 ResourcePool(Factory factory, Free free)
53 : factory_(std::move(factory)), free_(std::move(free)), inUse_(0) {}
56 * @returns A unique pointer to a resource. The resource is null iff
57 * there are no available resources and `factory()` returns null.
60 std::lock_guard<std::mutex> lock(mutex_);
61 if (!resources_.empty()) {
62 UniquePtr resource{resources_.back(), Deleter{*this}};
63 resources_.pop_back();
67 UniquePtr resource{factory_(), Deleter{*this}};
72 ~ResourcePool() noexcept {
74 for (const auto resource : resources_) {
82 explicit Deleter(ResourcePool &pool) : pool_(&pool) {}
84 void operator() (T *resource) {
85 std::lock_guard<std::mutex> lock(pool_->mutex_);
86 // Make sure we don't put null resources into the pool
88 pool_->resources_.push_back(resource);
90 assert(pool_->inUse_ > 0);