dispenso
1.4.1
A library for task parallelism
Loading...
Searching...
No Matches
resource_pool.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) Meta Platforms, Inc. and affiliates.
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
*/
7
15
#pragma once
16
17
#include <
dispenso/platform.h
>
18
#include <
dispenso/tsan_annotations.h
>
19
#include <moodycamel/blockingconcurrentqueue.h>
20
21
namespace
dispenso {
22
23
template
<
typename
T>
24
class
ResourcePool;
25
30
template
<
typename
T>
31
class
Resource
{
32
public
:
33
Resource
(
Resource
&& other) : resource_(other.resource_), pool_(other.pool_) {
34
other.resource_ =
nullptr
;
35
}
36
37
Resource
& operator=(
Resource
&& other) {
38
if
(&other !=
this
) {
39
recycle();
40
resource_ = other.resource_;
41
pool_ = other.pool_;
42
other.resource_ =
nullptr
;
43
}
44
return
*
this
;
45
}
46
52
T&
get
() {
53
return
*resource_;
54
}
55
56
~Resource
() {
57
recycle();
58
}
59
60
private
:
61
Resource(T* res, ResourcePool<T>* pool) : resource_(res), pool_(pool) {}
62
63
void
recycle();
64
65
T* resource_;
66
ResourcePool<T>* pool_;
67
68
friend
class
ResourcePool<T>;
69
};
70
75
template
<
typename
T>
76
class
ResourcePool
{
77
public
:
85
template
<
typename
F>
86
ResourcePool
(
size_t
size,
const
F& init)
87
: pool_(size),
88
backingResources_(
89
reinterpret_cast<char*>(
90
detail::alignedMalloc(size * detail::alignToCacheLine(sizeof(T))))),
91
size_(size) {
92
char
* buf = backingResources_;
93
94
// There are three reasons we create our own buffer and use placement new:
95
// 1. We want to be able to handle non-movable non-copyable objects
96
// * Note that we could do this with std::deque
97
// 2. We want to minimize memory allocations, since that can be a common point of contention in
98
// multithreaded programs.
99
// 3. We can easily ensure that the objects are cache aligned to help avoid false sharing.
100
101
for
(
size_t
i = 0; i < size; ++i) {
102
pool_.enqueue(
new
(buf) T(init()));
103
buf += detail::alignToCacheLine(
sizeof
(T));
104
}
105
}
106
112
Resource<T>
acquire
() {
113
T* t;
114
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
115
pool_.wait_dequeue(t);
116
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
117
return
Resource<T>
(t,
this
);
118
}
119
124
~ResourcePool
() {
125
assert(pool_.size_approx() == size_);
126
for
(
size_t
i = 0; i < size_; ++i) {
127
T* t;
128
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
129
pool_.wait_dequeue(t);
130
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
131
t->~T();
132
}
133
detail::alignedFree(backingResources_);
134
}
135
136
private
:
137
void
recycle(T* t) {
138
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
139
pool_.enqueue(t);
140
DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();
141
}
142
143
moodycamel::BlockingConcurrentQueue<T*> pool_;
144
char
* backingResources_;
145
size_t
size_;
146
147
friend
class
Resource<T>;
148
};
149
150
template
<
typename
T>
151
void
Resource<T>::recycle() {
152
if
(resource_) {
153
pool_->recycle(resource_);
154
}
155
}
156
157
}
// namespace dispenso
dispenso::Resource
Definition
resource_pool.h:31
dispenso::Resource::get
T & get()
Definition
resource_pool.h:52
dispenso::ResourcePool
Definition
resource_pool.h:76
dispenso::ResourcePool::~ResourcePool
~ResourcePool()
Definition
resource_pool.h:124
dispenso::ResourcePool::acquire
Resource< T > acquire()
Definition
resource_pool.h:112
dispenso::ResourcePool::ResourcePool
ResourcePool(size_t size, const F &init)
Definition
resource_pool.h:86
platform.h
tsan_annotations.h
dispenso
resource_pool.h
Generated by
1.12.0