1

次の行に何か長いものを書く必要があります。

  • バッファー内の foreach バッファー:

    • スレッド 0 で OpenGL バッファをマップし、スレッド 1 でバッファにコピーしてから、スレッド 1 でバッファをマップ解除します。
  • すべてのバッファがマップ解除されたら、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