Skip to content

支持像thread_local一样的动态lazy local #435

@poor-circle

Description

@poor-circle

目前的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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions