feat update
Some checks failed
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m26s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Failing after 1m43s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 1m52s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 1m59s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m58s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m24s
Some checks failed
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m26s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Failing after 1m43s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 1m52s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 1m59s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m58s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m24s
This commit is contained in:
parent
794535e9a1
commit
5c1056cbc8
@ -21,41 +21,37 @@ namespace rpc_core {
|
|||||||
* 3. Provide the implementation of sending data, send_package_impl.
|
* 3. Provide the implementation of sending data, send_package_impl.
|
||||||
*/
|
*/
|
||||||
struct connection : detail::noncopyable {
|
struct connection : detail::noncopyable {
|
||||||
std::function<void(std::string)> send_package_impl;
|
std::function<void(std::string)> send_package_impl;
|
||||||
std::function<void(std::string)> on_recv_package;
|
std::function<void(std::string)> on_recv_package;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default connection avoid crash
|
* Default connection avoid crash
|
||||||
*/
|
*/
|
||||||
struct default_connection : connection {
|
struct default_connection : connection {
|
||||||
default_connection() {
|
default_connection()
|
||||||
send_package_impl = [](const std::string &payload) {
|
{
|
||||||
RPC_CORE_LOGE("need send_package_impl: %zu", payload.size());
|
send_package_impl
|
||||||
};
|
= [](const std::string &payload) { RPC_CORE_LOGE("need send_package_impl: %zu", payload.size()); };
|
||||||
on_recv_package = [](const std::string &payload) {
|
on_recv_package
|
||||||
RPC_CORE_LOGE("need on_recv_package: %zu", payload.size());
|
= [](const std::string &payload) { RPC_CORE_LOGE("need on_recv_package: %zu", payload.size()); };
|
||||||
};
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loopback connection for testing
|
* Loopback connection for testing
|
||||||
*/
|
*/
|
||||||
struct loopback_connection : public connection {
|
struct loopback_connection : public connection {
|
||||||
static std::pair<std::shared_ptr<connection>, std::shared_ptr<connection>> create() {
|
static std::pair<std::shared_ptr<connection>, std::shared_ptr<connection>> create()
|
||||||
auto c1 = std::make_shared<connection>();
|
{
|
||||||
auto c1_weak = std::weak_ptr<connection>(c1);
|
auto c1 = std::make_shared<connection>();
|
||||||
auto c2 = std::make_shared<connection>();
|
auto c1_weak = std::weak_ptr<connection>(c1);
|
||||||
auto c2_weak = std::weak_ptr<connection>(c2);
|
auto c2 = std::make_shared<connection>();
|
||||||
c1->send_package_impl = [c2_weak](std::string package) {
|
auto c2_weak = std::weak_ptr<connection>(c2);
|
||||||
c2_weak.lock()->on_recv_package(std::move(package));
|
c1->send_package_impl = [c2_weak](std::string package) { c2_weak.lock()->on_recv_package(std::move(package)); };
|
||||||
};
|
c2->send_package_impl = [c1_weak](std::string package) { c1_weak.lock()->on_recv_package(std::move(package)); };
|
||||||
c2->send_package_impl = [c1_weak](std::string package) {
|
return std::make_pair(c1, c2);
|
||||||
c1_weak.lock()->on_recv_package(std::move(package));
|
}
|
||||||
};
|
|
||||||
return std::make_pair(c1, c2);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,32 +59,27 @@ struct loopback_connection : public connection {
|
|||||||
* for bytes stream: tcp socket, serial port, etc.
|
* for bytes stream: tcp socket, serial port, etc.
|
||||||
*/
|
*/
|
||||||
struct stream_connection : public connection {
|
struct stream_connection : public connection {
|
||||||
explicit stream_connection(uint32_t max_body_size = UINT32_MAX) : data_packer_(max_body_size) {
|
explicit stream_connection(uint32_t max_body_size = UINT32_MAX) : data_packer_(max_body_size)
|
||||||
send_package_impl = [this](const std::string &package) {
|
{
|
||||||
auto payload = data_packer_.pack(package);
|
send_package_impl = [this](const std::string &package) {
|
||||||
send_bytes_impl(std::move(payload));
|
auto payload = data_packer_.pack(package);
|
||||||
};
|
send_bytes_impl(std::move(payload));
|
||||||
data_packer_.on_data = [this](std::string payload) {
|
};
|
||||||
on_recv_package(std::move(payload));
|
data_packer_.on_data = [this](std::string payload) { on_recv_package(std::move(payload)); };
|
||||||
};
|
on_recv_bytes = [this](const void *data, size_t size) { data_packer_.feed(data, size); };
|
||||||
on_recv_bytes = [this](const void *data, size_t size) {
|
}
|
||||||
data_packer_.feed(data, size);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* should call on connected or disconnected
|
* should call on connected or disconnected
|
||||||
*/
|
*/
|
||||||
void reset() {
|
void reset() { data_packer_.reset(); }
|
||||||
data_packer_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::function<void(std::string)> send_bytes_impl;
|
std::function<void(std::string)> send_bytes_impl;
|
||||||
std::function<void(const void *data, size_t size)> on_recv_bytes;
|
std::function<void(const void *data, size_t size)> on_recv_bytes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::data_packer data_packer_;
|
detail::data_packer data_packer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rpc_core
|
}// namespace rpc_core
|
||||||
|
@ -16,152 +16,145 @@
|
|||||||
namespace rpc_core {
|
namespace rpc_core {
|
||||||
|
|
||||||
class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, public request::rpc_proto {
|
class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, public request::rpc_proto {
|
||||||
public:
|
public:
|
||||||
using timeout_cb = detail::msg_dispatcher::timeout_cb;
|
using timeout_cb = detail::msg_dispatcher::timeout_cb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template<typename... Args>
|
||||||
static std::shared_ptr<rpc> create(Args&&... args) {
|
static std::shared_ptr<rpc> create(Args &&...args)
|
||||||
return std::shared_ptr<rpc>(new rpc(std::forward<Args>(args)...), [](rpc* p) {
|
{
|
||||||
delete p;
|
return std::shared_ptr<rpc>(new rpc(std::forward<Args>(args)...), [](rpc *p) { delete p; });
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit rpc(std::shared_ptr<connection> conn = std::make_shared<default_connection>())
|
|
||||||
: conn_(conn), dispatcher_(std::make_shared<detail::msg_dispatcher>(std::move(conn))) {
|
|
||||||
dispatcher_->init();
|
|
||||||
RPC_CORE_LOGD("rpc: %p", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~rpc() override {
|
|
||||||
RPC_CORE_LOGD("~rpc: %p", this);
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline std::shared_ptr<connection> get_connection() const {
|
|
||||||
return conn_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void set_timer(detail::msg_dispatcher::timer_impl timer_impl) {
|
|
||||||
dispatcher_->set_timer_impl(std::move(timer_impl));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void set_ready(bool ready) {
|
|
||||||
is_ready_ = ready;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <typename F>
|
|
||||||
void subscribe(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle) {
|
|
||||||
constexpr bool F_ReturnIsEmpty = std::is_void<typename detail::callable_traits<F>::return_type>::value;
|
|
||||||
constexpr bool F_ParamIsEmpty = detail::callable_traits<F>::argc == 0;
|
|
||||||
subscribe_helper<F, F_ReturnIsEmpty, F_ParamIsEmpty>()(cmd, std::move(handle), dispatcher_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void unsubscribe(const cmd_type& cmd) {
|
|
||||||
dispatcher_->unsubscribe_cmd(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline request_s create_request() {
|
|
||||||
return request::create(shared_from_this());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline request_s cmd(cmd_type cmd) {
|
|
||||||
return create_request()->cmd(std::move(cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline request_s ping(std::string payload = {}) { // NOLINT
|
|
||||||
return create_request()->ping()->msg(std::move(payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
seq_type make_seq() override {
|
|
||||||
return seq_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_request(request const* request) override {
|
|
||||||
if (request->need_rsp_) {
|
|
||||||
dispatcher_->subscribe_rsp(request->seq_, request->rsp_handle_, request->timeout_cb_, request->timeout_ms_);
|
|
||||||
}
|
}
|
||||||
detail::msg_wrapper msg;
|
|
||||||
msg.type = static_cast<detail::msg_wrapper::msg_type>(detail::msg_wrapper::command | (request->is_ping_ ? detail::msg_wrapper::ping : 0) |
|
|
||||||
(request->need_rsp_ ? detail::msg_wrapper::need_rsp : 0));
|
|
||||||
msg.cmd = request->cmd_;
|
|
||||||
msg.seq = request->seq_;
|
|
||||||
msg.request_payload = &request->payload_;
|
|
||||||
RPC_CORE_LOGD("=> seq:%u type:%s %s", msg.seq, (msg.type & detail::msg_wrapper::msg_type::ping) ? "ping" : "cmd", msg.cmd.c_str());
|
|
||||||
conn_->send_package_impl(detail::coder::serialize(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_ready() const override {
|
private:
|
||||||
return is_ready_;
|
explicit rpc(std::shared_ptr<connection> conn = std::make_shared<default_connection>())
|
||||||
}
|
: conn_(conn),
|
||||||
|
dispatcher_(std::make_shared<detail::msg_dispatcher>(std::move(conn)))
|
||||||
|
{
|
||||||
|
dispatcher_->init();
|
||||||
|
RPC_CORE_LOGD("rpc: %p", this);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
~rpc() override { RPC_CORE_LOGD("~rpc: %p", this); };
|
||||||
template <typename F, bool F_ReturnIsEmpty, bool F_ParamIsEmpty>
|
|
||||||
struct subscribe_helper;
|
|
||||||
|
|
||||||
template <typename F>
|
public:
|
||||||
struct subscribe_helper<F, false, false> {
|
inline std::shared_ptr<connection> get_connection() const { return conn_; }
|
||||||
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
|
|
||||||
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
|
|
||||||
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
|
|
||||||
using F_Return = detail::remove_cvref_t<typename detail::callable_traits<F>::return_type>;
|
|
||||||
|
|
||||||
auto r = msg.unpack_as<F_Param>();
|
inline void set_timer(detail::msg_dispatcher::timer_impl timer_impl)
|
||||||
F_Return ret;
|
{
|
||||||
if (r.first) {
|
dispatcher_->set_timer_impl(std::move(timer_impl));
|
||||||
ret = handle(std::move(r.second));
|
}
|
||||||
|
|
||||||
|
inline void set_ready(bool ready) { is_ready_ = ready; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename F>
|
||||||
|
void subscribe(const cmd_type &cmd, RPC_CORE_MOVE_PARAM(F) handle)
|
||||||
|
{
|
||||||
|
constexpr bool F_ReturnIsEmpty = std::is_void<typename detail::callable_traits<F>::return_type>::value;
|
||||||
|
constexpr bool F_ParamIsEmpty = detail::callable_traits<F>::argc == 0;
|
||||||
|
subscribe_helper<F, F_ReturnIsEmpty, F_ParamIsEmpty>()(cmd, std::move(handle), dispatcher_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void unsubscribe(const cmd_type &cmd) { dispatcher_->unsubscribe_cmd(cmd); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline request_s create_request() { return request::create(shared_from_this()); }
|
||||||
|
|
||||||
|
inline request_s cmd(cmd_type cmd) { return create_request()->cmd(std::move(cmd)); }
|
||||||
|
|
||||||
|
inline request_s ping(std::string payload = {})
|
||||||
|
{// NOLINT
|
||||||
|
return create_request()->ping()->msg(std::move(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
seq_type make_seq() override { return seq_++; }
|
||||||
|
|
||||||
|
void send_request(request const *request) override
|
||||||
|
{
|
||||||
|
if (request->need_rsp_) {
|
||||||
|
dispatcher_->subscribe_rsp(request->seq_, request->rsp_handle_, request->timeout_cb_, request->timeout_ms_);
|
||||||
}
|
}
|
||||||
return detail::msg_wrapper::make_rsp(msg.seq, &ret, r.first);
|
detail::msg_wrapper msg;
|
||||||
});
|
msg.type = static_cast<detail::msg_wrapper::msg_type>(
|
||||||
|
detail::msg_wrapper::command | (request->is_ping_ ? detail::msg_wrapper::ping : 0)
|
||||||
|
| (request->need_rsp_ ? detail::msg_wrapper::need_rsp : 0));
|
||||||
|
msg.cmd = request->cmd_;
|
||||||
|
msg.seq = request->seq_;
|
||||||
|
msg.request_payload = &request->payload_;
|
||||||
|
RPC_CORE_LOGD("=> seq:%u type:%s %s",
|
||||||
|
msg.seq,
|
||||||
|
(msg.type & detail::msg_wrapper::msg_type::ping) ? "ping" : "cmd",
|
||||||
|
msg.cmd.c_str());
|
||||||
|
conn_->send_package_impl(detail::coder::serialize(msg));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F>
|
inline bool is_ready() const override { return is_ready_; }
|
||||||
struct subscribe_helper<F, true, false> {
|
|
||||||
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
|
|
||||||
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
|
|
||||||
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
|
|
||||||
|
|
||||||
auto r = msg.unpack_as<F_Param>();
|
private:
|
||||||
if (r.first) {
|
template<typename F, bool F_ReturnIsEmpty, bool F_ParamIsEmpty>
|
||||||
handle(std::move(r.second));
|
struct subscribe_helper;
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
struct subscribe_helper<F, false, false> {
|
||||||
|
void operator()(const cmd_type &cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper &msg) {
|
||||||
|
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
|
||||||
|
using F_Return = detail::remove_cvref_t<typename detail::callable_traits<F>::return_type>;
|
||||||
|
|
||||||
|
auto r = msg.unpack_as<F_Param>();
|
||||||
|
F_Return ret;
|
||||||
|
if (r.first) { ret = handle(std::move(r.second)); }
|
||||||
|
return detail::msg_wrapper::make_rsp(msg.seq, &ret, r.first);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, r.first);
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F>
|
template<typename F>
|
||||||
struct subscribe_helper<F, false, true> {
|
struct subscribe_helper<F, true, false> {
|
||||||
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
|
void operator()(const cmd_type &cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher *dispatcher)
|
||||||
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
|
{
|
||||||
using F_Return = typename detail::callable_traits<F>::return_type;
|
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper &msg) {
|
||||||
|
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
|
||||||
|
|
||||||
F_Return ret = handle();
|
auto r = msg.unpack_as<F_Param>();
|
||||||
return detail::msg_wrapper::make_rsp(msg.seq, &ret, true);
|
if (r.first) { handle(std::move(r.second)); }
|
||||||
});
|
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, r.first);
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename F>
|
template<typename F>
|
||||||
struct subscribe_helper<F, true, true> {
|
struct subscribe_helper<F, false, true> {
|
||||||
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
|
void operator()(const cmd_type &cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher *dispatcher)
|
||||||
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
|
{
|
||||||
handle();
|
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper &msg) {
|
||||||
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, true);
|
using F_Return = typename detail::callable_traits<F>::return_type;
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
F_Return ret = handle();
|
||||||
std::shared_ptr<connection> conn_;
|
return detail::msg_wrapper::make_rsp(msg.seq, &ret, true);
|
||||||
std::shared_ptr<detail::msg_dispatcher> dispatcher_;
|
});
|
||||||
seq_type seq_{0};
|
}
|
||||||
bool is_ready_ = false;
|
};
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
struct subscribe_helper<F, true, true> {
|
||||||
|
void operator()(const cmd_type &cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper &msg) {
|
||||||
|
handle();
|
||||||
|
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<connection> conn_;
|
||||||
|
std::shared_ptr<detail::msg_dispatcher> dispatcher_;
|
||||||
|
seq_type seq_{0};
|
||||||
|
bool is_ready_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rpc_core
|
}// namespace rpc_core
|
||||||
|
Loading…
x
Reference in New Issue
Block a user