Coverage Report

Created: 2025-06-13 06:23

/src/brpc/src/butil/resource_pool.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
// bthread - An M:N threading library to make applications more concurrent.
19
20
// Date: Sun Jul 13 15:04:18 CST 2014
21
22
#ifndef BUTIL_RESOURCE_POOL_H
23
#define BUTIL_RESOURCE_POOL_H
24
25
#include <cstddef>                       // size_t
26
27
// Efficiently allocate fixed-size (small) objects addressable by identifiers
28
// in multi-threaded environment.
29
//
30
// Comparison with new/delete(glibc 2.3.4) under high contention:
31
//   -----------------------------
32
//   get<int>=26.1 return<int>=4.7
33
//   get<int>=46.1 return<int>=5.4
34
//   get<int>=27.5 return<int>=5.3
35
//   get<int>=24.8 return<int>=6.5
36
//   get<int>=26.6 return<int>=5.3
37
//   get<int>=24.7 return<int>=4.9
38
//   get<int>=67.8 return<int>=5.5
39
//   get<int>=36.7 return<int>=5.0
40
//   --------------------------------
41
//   new<int>=295.0 delete<int>=234.5
42
//   new<int>=299.2 delete<int>=359.7
43
//   new<int>=288.1 delete<int>=219.0
44
//   new<int>=298.6 delete<int>=428.0
45
//   new<int>=319.2 delete<int>=426.5
46
//   new<int>=293.9 delete<int>=651.8
47
//   new<int>=304.9 delete<int>=672.8
48
//   new<int>=170.6 delete<int>=292.8
49
//   --------------------------------
50
51
namespace butil {
52
53
// Specialize following classes to override default parameters for type T.
54
//   namespace butil {
55
//     template <> struct ResourcePoolBlockMaxSize<Foo> {
56
//       static const size_t value = 1024;
57
//     };
58
//   }
59
60
// Memory is allocated in blocks, memory size of a block will not exceed:
61
//   min(ResourcePoolBlockMaxSize<T>::value,
62
//       ResourcePoolBlockMaxItem<T>::value * sizeof(T))
63
template <typename T> struct ResourcePoolBlockMaxSize {
64
    static const size_t value = 64 * 1024; // bytes
65
};
66
template <typename T> struct ResourcePoolBlockMaxItem {
67
    static const size_t value = 256;
68
};
69
70
// Free objects of each thread are grouped into a chunk before they are merged
71
// to the global list. Memory size of objects in one free chunk will not exceed:
72
//   min(ResourcePoolFreeChunkMaxItem<T>::value(),
73
//       ResourcePoolBlockMaxSize<T>::value,
74
//       ResourcePoolBlockMaxItem<T>::value * sizeof(T))
75
template <typename T> struct ResourcePoolFreeChunkMaxItem {
76
0
    static size_t value() { return 256; }
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<bthread::TaskMeta>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<bthread::TimerThread::Task>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<brpc::IOEventData>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<brpc::Socket>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<butil::details::ExtendedEndPoint>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<bthread::ExecutionQueueBase>::value()
Unexecuted instantiation: butil::ResourcePoolFreeChunkMaxItem<bthread::Id>::value()
77
};
78
79
// ResourcePool calls this function on newly constructed objects. If this
80
// function returns false, the object is destructed immediately and
81
// get_resource() shall return NULL. This is useful when the constructor
82
// failed internally(namely ENOMEM).
83
template <typename T> struct ResourcePoolValidator {
84
0
    static bool validate(const T*) { return true; }
Unexecuted instantiation: butil::ResourcePoolValidator<bthread::TaskMeta>::validate(bthread::TaskMeta const*)
Unexecuted instantiation: butil::ResourcePoolValidator<bthread::TimerThread::Task>::validate(bthread::TimerThread::Task const*)
Unexecuted instantiation: butil::ResourcePoolValidator<brpc::Socket>::validate(brpc::Socket const*)
Unexecuted instantiation: butil::ResourcePoolValidator<brpc::IOEventData>::validate(brpc::IOEventData const*)
Unexecuted instantiation: butil::ResourcePoolValidator<butil::details::ExtendedEndPoint>::validate(butil::details::ExtendedEndPoint const*)
Unexecuted instantiation: butil::ResourcePoolValidator<bthread::ExecutionQueueBase>::validate(bthread::ExecutionQueueBase const*)
Unexecuted instantiation: butil::ResourcePoolValidator<bthread::Id>::validate(bthread::Id const*)
85
};
86
87
}  // namespace butil
88
89
#include "butil/resource_pool_inl.h"
90
91
namespace butil {
92
93
// Get an object typed |T| and write its identifier into |id|.
94
// The object should be cleared before usage.
95
// NOTE: If there are no arguments, T must be default-constructible.
96
template <typename T, typename... Args>
97
0
inline T* get_resource(ResourceId<T>* id, Args&&... args) {
98
0
    return ResourcePool<T>::singleton()->get_resource(id, std::forward<Args>(args)...);
99
0
}
Unexecuted instantiation: bthread::TaskMeta* butil::get_resource<bthread::TaskMeta>(butil::ResourceId<bthread::TaskMeta>*)
Unexecuted instantiation: bthread::TimerThread::Task* butil::get_resource<bthread::TimerThread::Task>(butil::ResourceId<bthread::TimerThread::Task>*)
Unexecuted instantiation: brpc::Socket* butil::get_resource<brpc::Socket, brpc::VersionedRefWithId<brpc::Socket>::Forbidden>(butil::ResourceId<brpc::Socket>*, brpc::VersionedRefWithId<brpc::Socket>::Forbidden&&)
Unexecuted instantiation: brpc::IOEventData* butil::get_resource<brpc::IOEventData, brpc::VersionedRefWithId<brpc::IOEventData>::Forbidden>(butil::ResourceId<brpc::IOEventData>*, brpc::VersionedRefWithId<brpc::IOEventData>::Forbidden&&)
Unexecuted instantiation: butil::details::ExtendedEndPoint* butil::get_resource<butil::details::ExtendedEndPoint>(butil::ResourceId<butil::details::ExtendedEndPoint>*)
Unexecuted instantiation: bthread::ExecutionQueueBase* butil::get_resource<bthread::ExecutionQueueBase, bthread::ExecutionQueueBase::Forbidden>(butil::ResourceId<bthread::ExecutionQueueBase>*, bthread::ExecutionQueueBase::Forbidden&&)
Unexecuted instantiation: bthread::Id* butil::get_resource<bthread::Id>(butil::ResourceId<bthread::Id>*)
100
101
// Return the object associated with identifier |id| back. The object is NOT
102
// destructed and will be returned by later get_resource<T>. Similar with
103
// free/delete, validity of the id is not checked, user shall not return a
104
// not-yet-allocated or already-returned id otherwise behavior is undefined.
105
// Returns 0 when successful, -1 otherwise.
106
0
template <typename T> inline int return_resource(ResourceId<T> id) {
107
0
    return ResourcePool<T>::singleton()->return_resource(id);
108
0
}
Unexecuted instantiation: int butil::return_resource<bthread::TaskMeta>(butil::ResourceId<bthread::TaskMeta>)
Unexecuted instantiation: int butil::return_resource<bthread::TimerThread::Task>(butil::ResourceId<bthread::TimerThread::Task>)
Unexecuted instantiation: int butil::return_resource<brpc::IOEventData>(butil::ResourceId<brpc::IOEventData>)
Unexecuted instantiation: int butil::return_resource<brpc::Socket>(butil::ResourceId<brpc::Socket>)
Unexecuted instantiation: int butil::return_resource<butil::details::ExtendedEndPoint>(butil::ResourceId<butil::details::ExtendedEndPoint>)
Unexecuted instantiation: int butil::return_resource<bthread::ExecutionQueueBase>(butil::ResourceId<bthread::ExecutionQueueBase>)
Unexecuted instantiation: int butil::return_resource<bthread::Id>(butil::ResourceId<bthread::Id>)
109
110
// Get the object associated with the identifier |id|.
111
// Returns NULL if |id| was not allocated by get_resource<T> or
112
// ResourcePool<T>::get_resource() of a variant before.
113
// Addressing a free(returned to pool) identifier does not return NULL.
114
// NOTE: Calling this function before any other get_resource<T>/
115
//       return_resource<T>/address<T>, even if the identifier is valid,
116
//       may race with another thread calling clear_resources<T>.
117
0
template <typename T> inline T* address_resource(ResourceId<T> id) {
118
0
    return ResourcePool<T>::address_resource(id);
119
0
}
Unexecuted instantiation: bthread::TaskMeta* butil::address_resource<bthread::TaskMeta>(butil::ResourceId<bthread::TaskMeta>)
Unexecuted instantiation: bthread::TimerThread::Task* butil::address_resource<bthread::TimerThread::Task>(butil::ResourceId<bthread::TimerThread::Task>)
Unexecuted instantiation: brpc::IOEventData* butil::address_resource<brpc::IOEventData>(butil::ResourceId<brpc::IOEventData>)
Unexecuted instantiation: brpc::Socket* butil::address_resource<brpc::Socket>(butil::ResourceId<brpc::Socket>)
Unexecuted instantiation: butil::details::ExtendedEndPoint* butil::address_resource<butil::details::ExtendedEndPoint>(butil::ResourceId<butil::details::ExtendedEndPoint>)
Unexecuted instantiation: bthread::ExecutionQueueBase* butil::address_resource<bthread::ExecutionQueueBase>(butil::ResourceId<bthread::ExecutionQueueBase>)
Unexecuted instantiation: bthread::Id* butil::address_resource<bthread::Id>(butil::ResourceId<bthread::Id>)
120
121
// Reclaim all allocated resources typed T if caller is the last thread called
122
// this function, otherwise do nothing. You rarely need to call this function
123
// manually because it's called automatically when each thread quits.
124
template <typename T> inline void clear_resources() {
125
    ResourcePool<T>::singleton()->clear_resources();
126
}
127
128
// Get description of resources typed T.
129
// This function is possibly slow because it iterates internal structures.
130
// Don't use it frequently like a "getter" function.
131
0
template <typename T> ResourcePoolInfo describe_resources() {
132
0
    return ResourcePool<T>::singleton()->describe_resources();
133
0
}
Unexecuted instantiation: butil::ResourcePoolInfo butil::describe_resources<bthread::Id>()
Unexecuted instantiation: butil::ResourcePoolInfo butil::describe_resources<brpc::Socket>()
134
135
}  // namespace butil
136
137
#endif  // BUTIL_RESOURCE_POOL_H