Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请求增加使用示例 #96

Open
Lawliet828 opened this issue Nov 21, 2023 · 3 comments
Open

请求增加使用示例 #96

Lawliet828 opened this issue Nov 21, 2023 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@Lawliet828
Copy link

What happened + What you expected to happen

想使用co_context改造之前基于muduo写的小项目,对co_context如何发请求还不太熟悉。

使用muduo发送请求时,函数声明如下

SendRequest(const std::string &ip, int port, const void *buf, size_t buf_len, Callback res_cb, Callback timeout_cb, double time);

包括收到响应后如何处理,超时如何处理两方面。

在看co_context的example后,不太明白使用co_context应该如何处理。

所以可以添加一个发送请求并有超时处理的实例代码嘛

@Codesire-Deng
Copy link
Owner

Codesire-Deng commented Nov 21, 2023

在协程的优势下,一些 callback 是可以省略的,通常的做法是将失败信息 co_return 给上层:

// Return true if successful.
// Return false if timeout or any failure occurs.
task<bool> SendRequest(
    co_context::socket socket, std::span<const char> buf, double time_ms
) {
    auto deadline = std::chrono::steady_clock::now()
                    + std::chrono::duration<double, std::milli>{time_ms};
    while (buf.size() > 0) {
        int result = co_await timeout_at(socket.send(buf), deadline);
        if (result <= 0) {
            // something wrong...
            if (-result == ECANCELED) {
                printf("timeout\n");
            }
            co_return false;
        }
        buf = buf.subspan(result); // move forward `result` bytes.
    }
    co_return true;
}

这里上层收到 false 就能知道是超时或者其他失败,从而不需要 res_cb 或者 timeout_cb 了。

@Codesire-Deng Codesire-Deng added the documentation Improvements or additions to documentation label Nov 21, 2023
@Lawliet828

This comment was marked as duplicate.

@Codesire-Deng
Copy link
Owner

@Lawliet828
一个 io_context 就是严格的一个线程。
最简单的办法,使用 io_context::co_spawn() 来推送任务:

#include <co_context/io_context.hpp>
#include <co_context/lazy_io.hpp>

#include <cassert>
#include <iostream>
using namespace co_context;

io_context manage_ctx;
io_context exec_ctx[2];

task<> workload(std::string message) {
    std::cout << "handling " << message << "...\n";
    co_await timeout(std::chrono::seconds(1));
    std::cout << message << " done.\n";
}

task<> manage_loop(std::vector<io_context *> workers) {
    assert(!workers.empty());
    size_t idx = 0;
    size_t count = 0;
    while (true) {
        workers[idx]->co_spawn(workload("task #" + std::to_string(count)));
        std::cout << "publish task " << count << " to exec_ctx[" << idx
                  << "]\n";
        idx = (idx + 1) % workers.size();
        ++count;
        co_await timeout(std::chrono::seconds(2));
    }
}

int main() {
    manage_ctx.co_spawn(manage_loop({&exec_ctx[0], &exec_ctx[1]}));

    manage_ctx.start();
    exec_ctx[0].start();
    exec_ctx[1].start();

    manage_ctx.join(); // 随便 join 一个,都会永久阻塞。

    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants