Skip to content

Commit b27c6fc

Browse files
committed
using small buffer optimization in function
1 parent 3660fbe commit b27c6fc

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

include/function.hpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,20 @@ class function<R(Args...)> {
2222
function(const function& other) {
2323
// 类型擦除了怎么知道other中保存的可调用类型具体是什么?
2424
// 使用clone可以通过多态找到实际的类型
25-
f = other.f->clone();
25+
if (other.f->is_small_object()) {
26+
other.f->small_clone(&buffer);
27+
f = &buffer;
28+
} else {
29+
f = other.f->big_clone();
30+
}
2631
}
27-
function(function&& other): f(other.f) {
32+
function(function&& other) {
33+
if (other.f->is_small_object()) {
34+
other.f->small_clone(&buffer);
35+
f = &buffer;
36+
} else {
37+
f = other.f;
38+
}
2839
other.f = nullptr;
2940
}
3041

@@ -47,12 +58,15 @@ class function<R(Args...)> {
4758
return (*f)(hstl::forward<Args>(args)...);
4859
}
4960
private:
61+
static constexpr size_t BufferSize = sizeof(void *) * 3;
5062
struct FuncBase {
5163
virtual R operator()(Args... args) = 0;
5264
// 由于类型擦除,存放的可调用对象F的具体类型是不知道的,
5365
// clone用于实际的可调用对象类型F的拷贝,类似于工厂方法,
5466
// 这里的工厂就是自己
55-
virtual FuncBase* clone() = 0;
67+
virtual FuncBase* big_clone() = 0;
68+
virtual void small_clone(void* buffer) = 0;
69+
virtual constexpr bool is_small_object() = 0;
5670
virtual ~FuncBase() = default;
5771
};
5872
template<typename F>
@@ -62,16 +76,23 @@ class function<R(Args...)> {
6276
FuncType f;
6377
explicit FuncImpl(const FuncType& func): f(func) {}
6478
explicit FuncImpl(FuncType&& func) : f(hstl::move(func)) {}
65-
FuncBase* clone() override {
79+
FuncBase* big_clone() override {
6680
return new FuncImpl(f);
6781
}
82+
void small_clone(void* buffer) override {
83+
::new(buffer) FuncImpl(f);
84+
}
85+
constexpr bool is_small_object() override {
86+
return sizeof(*this) <= BufferSize;
87+
}
88+
6889
FuncImpl(const FuncImpl& fi): f(fi.f) {}
6990
R operator()(Args... args) override {
7091
return f(hstl::forward<Args>(args)...);
7192
}
7293
};
7394

74-
std::aligned_storage<sizeof(void *) * 3> buffer;
95+
std::aligned_storage<BufferSize> buffer;
7596
FuncBase* f;
7697
};
7798

0 commit comments

Comments
 (0)