diff --git a/src/clientget.cpp b/src/clientget.cpp index 12904a0..2ba14ff 100644 --- a/src/clientget.cpp +++ b/src/clientget.cpp @@ -327,13 +327,13 @@ void Connection::handle_GET() { handle_GPR(CMD_GET); } void Connection::handle_PUT() { handle_GPR(CMD_PUT); } void Connection::handle_RPC() { handle_GPR(CMD_RPC); } -std::shared_ptr Context::GetBuilder::_exec_get() +std::shared_ptr GetBuilder::_exec_get() { std::shared_ptr ret; assert(_get); - pvt->tcp_loop.call([&ret, this]() { - auto chan = Channel::build(pvt, _name); + ctx->tcp_loop.call([&ret, this]() { + auto chan = Channel::build(ctx, _name); auto op = std::make_shared(Operation::Get, chan); op->done = std::move(_result); @@ -348,15 +348,15 @@ std::shared_ptr Context::GetBuilder::_exec_get() return ret; } -std::shared_ptr Context::PutBuilder::exec() +std::shared_ptr PutBuilder::exec() { std::shared_ptr ret; if(!_builder) throw std::logic_error("put() requires a builder()"); - pvt->tcp_loop.call([&ret, this]() { - auto chan = Channel::build(pvt, _name); + ctx->tcp_loop.call([&ret, this]() { + auto chan = Channel::build(ctx, _name); auto op = std::make_shared(Operation::Put, chan); op->done = std::move(_result); @@ -373,12 +373,12 @@ std::shared_ptr Context::PutBuilder::exec() return ret; } -std::shared_ptr Context::RPCBuilder::exec() +std::shared_ptr RPCBuilder::exec() { std::shared_ptr ret; - pvt->tcp_loop.call([&ret, this]() { - auto chan = Channel::build(pvt, _name); + ctx->tcp_loop.call([&ret, this]() { + auto chan = Channel::build(ctx, _name); auto op = std::make_shared(Operation::Put, chan); op->done = std::move(_result); diff --git a/src/clientintrospect.cpp b/src/clientintrospect.cpp index de2f360..79a2f59 100644 --- a/src/clientintrospect.cpp +++ b/src/clientintrospect.cpp @@ -154,14 +154,14 @@ void Connection::handle_GET_FIELD() } } -std::shared_ptr Context::GetBuilder::_exec_info() +std::shared_ptr GetBuilder::_exec_info() { std::shared_ptr ret; assert(!_get); - pvt->tcp_loop.call([&ret, this]() { - auto chan = Channel::build(pvt, _name); + ctx->tcp_loop.call([&ret, this]() { + auto chan = Channel::build(ctx, _name); auto op = std::make_shared(chan); op->done = std::move(_result); diff --git a/src/pvxs/client.h b/src/pvxs/client.h index bdfded2..9897ed3 100644 --- a/src/pvxs/client.h +++ b/src/pvxs/client.h @@ -108,6 +108,11 @@ struct PVXS_API Subscription { virtual void cancel() =0; }; +class GetBuilder; +class PutBuilder; +class RPCBuilder; +class MonitorBuilder; + /** An independent PVA protocol client instance * * Typically created with Config::build() @@ -135,43 +140,9 @@ public: Request request() const; - //! Options common to all operations - template - class CommonBuilder { - protected: - std::shared_ptr pvt; - std::string _name; - Request _pvRequest; - std::string _server; - int _prio; - CommonBuilder(const std::shared_ptr& pvt, const std::string& name) : pvt(pvt), _name(name), _prio(0) {} - inline SubBuilder& _sb() { return static_cast(*this); } - public: - SubBuilder& priority(int p) { _prio = p; return _sb(); } - SubBuilder& request(const Request& r) { _pvRequest = r; return _sb(); } - SubBuilder& server(const std::string& s) { _server = s; return _sb(); } - }; + inline + GetBuilder get(const std::string& name); - class GetBuilder : public CommonBuilder { - std::function _result; - bool _get; - PVXS_API - std::shared_ptr _exec_info(); - PVXS_API - std::shared_ptr _exec_get(); - public: - GetBuilder(const std::shared_ptr& pvt, const std::string& name, bool get) :CommonBuilder{pvt,name}, _get(get) {} - //! Callback through which result Value will be delivered - GetBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } - - //! Initiate network operation. - inline std::shared_ptr exec() { - return _get ? _exec_get() : _exec_info(); - } - - friend struct Context::Pvt; - }; - GetBuilder get(const std::string& name) { return GetBuilder{pvt, name, true}; } /** Request type information from PV. * Results in a Value with no marked fields. * @@ -184,54 +155,103 @@ public: * .exec(); * @endcode */ - GetBuilder info(const std::string& name) { return GetBuilder{pvt, name, false}; } + inline + GetBuilder info(const std::string& name); - struct PutBuilder : protected CommonBuilder { - bool _doGet = true; - std::function _builder; - std::function _result; - public: - PutBuilder(const std::shared_ptr& pvt, const std::string& name) :CommonBuilder{pvt,name} {} - PutBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } + inline + PutBuilder put(const std::string& name); - PVXS_API - std::shared_ptr exec(); + inline + RPCBuilder rpc(const std::string& name, Value&& arg); - friend struct Context::Pvt; - }; - PutBuilder put(const std::string& name) { return PutBuilder{pvt, name}; } - - struct RPCBuilder : protected CommonBuilder { - Value _argument; - std::function _result; - public: - RPCBuilder(const std::shared_ptr& pvt, const std::string& name, Value&& arg) :CommonBuilder{pvt,name}, _argument(std::move(arg)) {} - RPCBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } - - PVXS_API - std::shared_ptr exec(); - - friend struct Context::Pvt; - }; - RPCBuilder rpc(const std::string& name, Value&& arg) { return RPCBuilder{pvt, name, std::move(arg)}; } - - struct MonitorBuilder : protected CommonBuilder { - std::function&, Subscription::Event)> _event; - public: - MonitorBuilder(const std::shared_ptr& pvt, const std::string& name) :CommonBuilder{pvt,name} {} - - PVXS_API - std::shared_ptr exec(); - - friend struct Context::Pvt; - }; - MonitorBuilder monitor(const std::string& name) { return MonitorBuilder{pvt, name}; } + inline + MonitorBuilder monitor(const std::string& name); explicit operator bool() const { return pvt.operator bool(); } private: std::shared_ptr pvt; }; +//! Options common to all operations +template +class CommonBuilder { +protected: + std::shared_ptr ctx; + std::string _name; + Request _pvRequest; + std::string _server; + int _prio; + CommonBuilder(const std::shared_ptr& ctx, const std::string& name) : ctx(ctx), _name(name), _prio(0) {} + inline SubBuilder& _sb() { return static_cast(*this); } +public: + SubBuilder& priority(int p) { _prio = p; return _sb(); } + SubBuilder& request(const Request& r) { _pvRequest = r; return _sb(); } + SubBuilder& server(const std::string& s) { _server = s; return _sb(); } +}; + +class GetBuilder : public CommonBuilder { + std::function _result; + bool _get; + PVXS_API + std::shared_ptr _exec_info(); + PVXS_API + std::shared_ptr _exec_get(); +public: + GetBuilder(const std::shared_ptr& ctx, const std::string& name, bool get) :CommonBuilder{ctx,name}, _get(get) {} + //! Callback through which result Value will be delivered + GetBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } + + //! Initiate network operation. + inline std::shared_ptr exec() { + return _get ? _exec_get() : _exec_info(); + } + + friend struct Context::Pvt; +}; +GetBuilder Context::info(const std::string& name) { return GetBuilder{pvt, name, false}; } +GetBuilder Context::get(const std::string& name) { return GetBuilder{pvt, name, true}; } + +class PutBuilder : protected CommonBuilder { + bool _doGet = true; + std::function _builder; + std::function _result; +public: + PutBuilder(const std::shared_ptr& ctx, const std::string& name) :CommonBuilder{ctx,name} {} + PutBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } + + PVXS_API + std::shared_ptr exec(); + + friend struct Context::Pvt; +}; +PutBuilder Context::put(const std::string& name) { return PutBuilder{pvt, name}; } + +class RPCBuilder : protected CommonBuilder { + Value _argument; + std::function _result; +public: + RPCBuilder(const std::shared_ptr& ctx, const std::string& name, Value&& arg) :CommonBuilder{ctx,name}, _argument(std::move(arg)) {} + RPCBuilder& result(decltype (_result)&& cb) { _result = std::move(cb); return *this; } + + PVXS_API + std::shared_ptr exec(); + + friend struct Context::Pvt; +}; +RPCBuilder Context::rpc(const std::string& name, Value&& arg) { return RPCBuilder{pvt, name, std::move(arg)}; } + +class MonitorBuilder : protected CommonBuilder { + std::function&, Subscription::Event)> _event; +public: + MonitorBuilder(const std::shared_ptr& ctx, const std::string& name) :CommonBuilder{ctx,name} {} + + PVXS_API + std::shared_ptr exec(); + + friend struct Context::Pvt; +}; +MonitorBuilder Context::monitor(const std::string& name) { return MonitorBuilder{pvt, name}; } + struct PVXS_API Config { //! List of unicast and broadcast addresses std::vector addressList;