sdbusplus:service通过协程完成proxy

有的时候需要在service(记做s1)的method内访问其他service(记做s2)的method,如果s2的method需要较长的时间才能返回,那么通过普通的同步调用,会阻塞住s1,导致s1在此期间无法处理其他请求。那么可否在s1内用普通的异步的方式调用s2的method呢?由于普通的method是通过return返回调用结果的,当通过异步方式调用时,在s1的method的return时,是还没拿到返回值的(因为返回值是在异步调用的回调中获取的),所以也无法return。

这种情况可以使用协程的方式完成。

//sleep_service.cpp
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
string doSleep()
{
    cout<<"doSleep begin"<(io);
    conn->request_name("sleep.service");
    auto server = sdbusplus::asio::object_server(conn);
    shared_ptr iface = server.add_interface("/sleep_obj","sleep_infterface.data");
    iface->register_method("Sleep", doSleep);
    iface->initialize();
    io.run();
    return 0;
}

定义proxy service

//proxy_service.cpp
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
string doCallSleep(boost::asio::yield_context yield, shared_ptr conn)
{
    cout<<"1 proxy dosleep begin"<yield_method_call(yield, ec, 
        "sleep.service", "/sleep_obj",
        "sleep_infterface.data", "Sleep");
    if (ec)
    {
        cout << "call Sleep failed: ec = " << ec << '\n';
        return "Sleep failed";
    }
    cout<<"1 proxy dosleep end"<yield_method_call(yield, ec, 
        "sleep.service", "/sleep_obj",
        "sleep_infterface.data", "Sleep");
    if (ec)
    {
        cout << "call Sleep failed: ec = " << ec << '\n';
        return "Sleep failed";
    }
    cout<<"2 Sleep res="< conn, int d1, int d2)
{
    boost::system::error_code ec;
    int resAdd = conn->yield_method_call(yield, ec, 
        "calculate.service", "/calculate_obj",
        "calculate_infterface.data", "AddInt", d1, d2);
    if (ec)
    {
        cout << "call addAddIntint failed: ec = " << ec << '\n';
        return -1;
    }
    cout<<"AddInt res="<(io);
    conn->request_name("proxy.service");
    auto server = sdbusplus::asio::object_server(conn);
    shared_ptr iface = server.add_interface("/proxy_obj","proxy_infterface.data");
    iface->register_method("CallSleep", [conn](boost::asio::yield_context yield) {
                               return doCallSleep(yield, conn);
                           });
    iface->register_method("CallAddInt", [conn](boost::asio::yield_context yield, int d1, int d2) {
                               return doCallAddInt(yield, conn, d1, d2);
                           });
    iface->initialize();
    io.run();
    return 0;
}

将sleep_service, calculate.service, proxy.service都加载起来,然后通过busctl进行测试:

在shell1里运行:
busctl call proxy.service /proxy_obj proxy_infterface.data CallSleep --user

在shell2里运行:
busctl call proxy.service /proxy_obj proxy_infterface.data CallAddInt ii 1 2 --user

可以看到proxy_service的输出:
1 proxy dosleep begin
AddInt res=3
1 proxy dosleep end
1 Sleep res=Sleep done
2 proxy dosleep begin
2 Sleep res=Sleep done
2proxy dosleep end

可以看出proxy_service可以同时响应多个请求,而不会把自己阻塞。

你可能感兴趣的:(#,sdbusplus,linux)