1

我需要在以下几行中写一些很长的东西:

  • 缓冲区中的 foreach 缓冲区:

    • 在 thread0 中映射一个 OpenGL 缓冲区,然后复制到 thread1 中的缓冲区,然后在 thread1 中取消映射缓冲区。
  • 当所有缓冲区都未映射时,然后在 thread1 中渲染

这并不像我希望的那样微不足道,future.then而且when_all这将非常简单。然而,目前我有一些相当丑陋的东西,你可以在下面找到,见upload_to_buffers底部。它有点工作,但它很快变得相当难以管理和不可读(一切都需要以相反的顺序编写),我有点不确定这个解决方案的安全性。关于如何以更好的方式实现这一目标的任何想法?

template<typename T>
class async_result
{
public:
    async_result(T value)
        : value_(std::move(value))
    {
    }

    async_result(std::exception_ptr exception)
        : exception_(exception)
    {
    }

    T& get()
    {
        if(exception_)
            std::rethrow_exception(exception_);

        return *value_;
    }

    const T& get() const
    {
        if(exception_)
            std::rethrow_exception(exception_);

        return *value_;
    }

private:
    boost::optional<T> value_;
    std::exception_ptr exception_;
};

template<typename C>
void map(buffer buf, C callback)
{
    thread0.execute([=]
    {
        try
        {
            // Do map.

            callback(async_result<buffer>(std::move(buf)));
        }
        catch(...)
        {
            callback(async_result<buffer>(std::current_exception()));
        }
    });
}

template<typename C>
void copy(buffer buf, C callback)
{
    thread1.execute([=]
    {
        try
        {
            // Do copy.

            callback(async_result<buffer>(std::move(buf)));
        }
        catch(...)
        {
            callback(async_result<buffer>(std::current_exception()));
        }
    });
}

template<typename C>
void unmap(buffer buf, C callback)
{
    thread0.execute([=]
    {
        try
        {
            // Do unmap.

            callback(async_result<buffer>(std::move(buf)));
        }
        catch(...)
        {
            callback(async_result<buffer>(std::current_exception()));
        }
    });
}

template<typename C>
void upload_to_buffers(std::vector<buffer> buffers, C callback)
{
    auto unmap_buffer_results = std::make_shared<std::vector<async_result<buffer>>();
    auto unmap_buffer_results_count = buffers.size();

    auto on_unmap_buffer = [=](async_result<buffer> result)
    {
        unmap_buffer_results->push_back(std::move(result));
        if(unmap_buffer_results->size() != unmap_buffer_results_count )
            return;

        std::vector<buffer> buffers;
        for(auto& result : *unmap_buffer_results)
            buffers.push_back(std::move(result.get()));

        callback(std::move(buffers);
    };  

    auto copy_buffer_results = std::make_shared<std::vector<async_result<buffer>>();
    auto copy_buffer_results_count = buffers.size();

    auto on_copy_buffer = [=](async_result<buffer> result)
    {
        copy_buffer_results->push_back(std::move(result));
        if(copy_buffer_results->size() != copy_buffer_results_count)
            return;

        std::vector<buffer> buffers;
        for(auto& result : *copy_buffer_results)
            buffers.push_back(std::move(result.get()));

        for(auto& buf: buffers)
            unmap(std::move(buf), on_unmap_buffer);
    };

    auto map_buffer_results = std::make_shared<std::vector<async_result<buffer>>();
    auto map_buffer_results_count = buffers.size();

    auto on_mapped_buffer = [=](async_result<buffer> result)
    {
        map_buffer_results->push_back(std::move(result));
        if(map_buffer_results->size() != map_buffer_results_count)
            return;

        std::vector<buffer> buffers;
        for(auto& result : *map_buffer_results)
            buffers.push_back(std::move(result.get()));

        for(auto& buf: buffers)
            copy(std::move(buf), on_copy_buffer);       
    };

    for(auto& buf : buffers)
        map(std::move(buf), on_mapped_buffer);
}
4

0 回答 0