-
Notifications
You must be signed in to change notification settings - Fork 297
Open
Description
目前的lazy local设计性能良好,但用户启动协程时必须事先知道需要访问哪些变量,并事先分配好。
是否能新增一种方式,允许用户动态的创建lazy local变量,并且在协程启动时无需知道需要访问哪些lazy local变量。就像thread_local那样,不要求线程启动时手动创建变量。
一种可能的实现思路:
template<typename T, void(*ID)()=[](){}>
struct LazyLocalVariable {
// 每次初始化LazyLocalVariable都会获得一个不同的ID。
static std::size_t get_ID() noexcept {
return (std::size_t)ID;
}
};
class Lazy {
// ....
class LazyLocal {
// .....
// 在hash表中记录变量地址。
std::unique_ptr<hash_table_t<std::size_t, void*>> hash_table_;
~LazyLocal() {
// free lazy local here
}
};
template<typename T, auto X>
TransformAwaiter<T&> await_transform(LazyLocalVariable<T, X> localVariable) {
if (!lazy_local_.hash_table_) [[unlikely]] {
lazy_local_.hash_table_ =
std::make_unique<hash_table_t<std::size_t, void*>>();
}
// 查找id对应的变量地址
void*& address = lazy_local_.hash_table_[localVariable.get_ID()];
// 如果当前协程还未创建过变量,则创建该对象。
if (address == nullptr) [[unlikely]] {
address = new T{};
}
return TransformAwaiter<T&>{*address};
}
}
Lazy<int> getLocalCounter() {
// 创建lazy local变量。
LazyLocalVariable<int> var;
// 访问lazy local,如果当前协程还不存在这个变量,则立即分配。
int & i = co_await var;
// 该变量会在当前协程析构时被销毁
return i++;
}
Lazy<void> hi() {
while (true) {
std::cout<<"now count:" << getLocalCounter()<<std::endl;
co_await async_simple::coro::Yield{};
}
}
int main() {
async_simple::Executor::SimpleExecutor ex;
for (int i=0;i<1000;++i) {
hi().via(&ex).start([](auto&&){});
}
std::this_thread::sleep_for(100s);
}
性能代价:
每次调用co_await var访问变量,都需要从hash表中查找或插入变量地址。不过用户可以在接下来的访问中缓存该地址。
Metadata
Metadata
Assignees
Labels
No labels