Skip to content

Commit

Permalink
[c++ grpc] Simplify thread pool concept
Browse files Browse the repository at this point in the history
This change removes the unnecessary need for `TThreadPool` type parameter
and instead uses a more simple runtime `std::function` to express a
scheduler concept.
  • Loading branch information
ara-ayvazyan authored and chwarr committed May 15, 2018
1 parent d8f1a80 commit 2685b75
Show file tree
Hide file tree
Showing 25 changed files with 516 additions and 557 deletions.
25 changes: 19 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,25 @@ different versioning scheme, following the Haskell community's
`bond::nullable<T>` and now it is always deduced from `T`.
* **Breaking change** The `bond::capped_allocator` and related types have been
moved to the `bond::ext` namespace and the "bond/ext" include directory.
* **Breaking change** When using Bond-over-gRPC, the generated `ClientCore::Async*`
functions now accept `std::shared_ptr<grpc::ClientContext>`
as the last parameter instead of as the first.
* **Breaking change** When using Bond-over-gRPC, the client callback now directly accepts
`bond::ext::gRPC::unary_call_result<Response>` (drops the `std::shared_ptr`).
Also the `unary_call_result` now exposes read-only getters rather than fields.
* **Breaking changes** in Bond-over-gRPC (based on real-world use and feedback):
- The generated `ClientCore` and `ServiceCore` class templates and the
`Client` and `Service` convenience typedefs have all been replaced with
normal classes named `Client` and `Service`. The `ThreadPool` type parameter
has been removed in favor of simplified runtime representation of a `Scheduler`.
- The `Scheduler` concept and the `bond::ext::gRPC::thread_pool` implementation
now use `operator()` instead of a `schedule()` member function.
- The `bond::ext::gRPC::server_core` class template and the `bond::ext::gRPC::server`
convenience typedef have been replaced with the normal classes bond::ext::gRPC::server.
- The `bond::ext::gRPC::server_builder_core` class template and the
`bond::ext::gRPC::server_builder` convenience typedef have been replaced
with the normal class `bond::ext::gRPC::server_builder`.
Also the `bond::ext::gRPC::server_builder::SetThreadPool` has been
renamed to `SetScheduler` and now takes the revised `Scheduler`.
- The generated `Client::Async*` functions now accept `std::shared_ptr<grpc::ClientContext>`
as the last parameter instead of as the first.
- The client callback now directly accepts `bond::ext::gRPC::unary_call_result<Response>`
(drops the `std::shared_ptr`). Also the `unary_call_result` now exposes
read-only getters rather than fields.
* gRPC v1.10.0 is now required to use Bond-over-gRPC.
* This version include a number of memory leak fixes that users of Bond-over-gRPC were encountering. [Issue #810](https://github.com/Microsoft/bond/issues/810)
* Fixed includes for gRPC services with events or parameterless methods.
Expand Down
61 changes: 27 additions & 34 deletions compiler/src/Language/Bond/Codegen/Cpp/Grpc_h.hs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,13 @@ grpc_h export_attribute cpp file imports declarations = ("_grpc.h", [lt|
public:
struct Schema;

template <typename TThreadPool>
class #{proxyName}
{
public:
#{proxyName}(
const std::shared_ptr< ::grpc::ChannelInterface>& channel,
std::shared_ptr< ::bond::ext::gRPC::io_manager> ioManager,
std::shared_ptr<TThreadPool> threadPool);
const ::bond::ext::gRPC::Scheduler& scheduler);

#{doubleLineSep 2 publicProxyMethodDecl serviceMethods}

Expand All @@ -113,17 +112,14 @@ public:
#{proxyName}& operator=(#{proxyName}&&) = default;

private:
std::shared_ptr< ::grpc::ChannelInterface> _channel;
std::shared_ptr< ::bond::ext::gRPC::io_manager> _ioManager;
std::shared_ptr<TThreadPool> _threadPool;
::std::shared_ptr< ::grpc::ChannelInterface> _channel;
::std::shared_ptr< ::bond::ext::gRPC::io_manager> _ioManager;
::bond::ext::gRPC::Scheduler _scheduler;

#{newlineSep 2 privateProxyMethodDecl serviceMethods}
};

using Client = #{proxyName}< ::bond::ext::gRPC::thread_pool>;

template <typename TThreadPool>
class #{serviceName} : public ::bond::ext::gRPC::detail::service<TThreadPool>
class #{serviceName} : public ::bond::ext::gRPC::detail::service
{
public:
#{serviceName}()
Expand All @@ -138,20 +134,19 @@ public:
private:
#{newlineSep 2 serviceMethodReceiveData serviceMethods}
};

using Service = #{serviceName}< ::bond::ext::gRPC::thread_pool>;
};

#{template}template <typename TThreadPool>
inline #{className}::#{proxyName}<TThreadPool>::#{proxyName}(
const std::shared_ptr< ::grpc::ChannelInterface>& channel,
std::shared_ptr< ::bond::ext::gRPC::io_manager> ioManager,
std::shared_ptr<TThreadPool> threadPool)
#{template}inline #{className}::#{proxyName}::#{proxyName}(
const ::std::shared_ptr< ::grpc::ChannelInterface>& channel,
::std::shared_ptr< ::bond::ext::gRPC::io_manager> ioManager,
const ::bond::ext::gRPC::Scheduler& scheduler)
: _channel(channel)
, _ioManager(ioManager)
, _threadPool(threadPool)
, _scheduler(scheduler)
#{newlineSep 1 proxyMethodMemberInit serviceMethods}
{ }
{
BOOST_ASSERT(_scheduler);
}

#{doubleLineSep 0 methodDecl serviceMethods}

Expand Down Expand Up @@ -217,8 +212,8 @@ inline #{className}::#{proxyName}<TThreadPool>::#{proxyName}(
result Event{} = "void"
result Function{..} = bonded (methodTypeToMaybe methodResult)

proxyName = "ClientCore" :: String
serviceName = "ServiceCore" :: String
proxyName = "Client" :: String
serviceName = "Service" :: String

methodNames :: [String]
methodNames = map methodName serviceMethods
Expand All @@ -245,31 +240,29 @@ inline #{className}::#{proxyName}<TThreadPool>::#{proxyName}(
proxyMethodMemberInit Function{..} = [lt|, rpcmethod_#{methodName}_("/#{getDeclTypeName idl s}/#{methodName}", ::grpc::internal::RpcMethod::NORMAL_RPC, channel)|]
proxyMethodMemberInit Event{..} = [lt|, rpcmethod_#{methodName}_("/#{getDeclTypeName idl s}/#{methodName}", ::grpc::internal::RpcMethod::NORMAL_RPC, channel)|]

methodDecl Function{..} = [lt|#{template}template <typename TThreadPool>
inline void #{className}::#{proxyName}<TThreadPool>::Async#{methodName}(
methodDecl Function{..} = [lt|#{template}inline void #{className}::#{proxyName}::Async#{methodName}(
#{voidParam (methodTypeToMaybe methodInput)}
const ::std::function<void(::bond::ext::gRPC::unary_call_result< #{payload (methodTypeToMaybe methodResult)}>)>& cb,
::std::shared_ptr< ::grpc::ClientContext> context)
{
#{voidRequest (methodTypeToMaybe methodInput)}
auto calldata = std::make_shared< ::bond::ext::gRPC::detail::client_unary_call_data< #{payload (methodTypeToMaybe methodInput)}, #{payload (methodTypeToMaybe methodResult)}, TThreadPool>>(
auto calldata = std::make_shared< ::bond::ext::gRPC::detail::client_unary_call_data< #{payload (methodTypeToMaybe methodInput)}, #{payload (methodTypeToMaybe methodResult)}>>(
_channel,
_ioManager,
_threadPool,
_scheduler,
context ? ::std::move(context) : ::std::make_shared< ::grpc::ClientContext>(),
cb);
calldata->dispatch(rpcmethod_#{methodName}_, request);
}|]
methodDecl Event{..} = [lt|#{template}template <typename TThreadPool>
inline void #{className}::#{proxyName}<TThreadPool>::Async#{methodName}(
methodDecl Event{..} = [lt|#{template}inline void #{className}::#{proxyName}::Async#{methodName}(
#{voidParam (methodTypeToMaybe methodInput)}
::std::shared_ptr< ::grpc::ClientContext> context)
{
#{voidRequest (methodTypeToMaybe methodInput)}
auto calldata = std::make_shared< ::bond::ext::gRPC::detail::client_unary_call_data< #{payload (methodTypeToMaybe methodInput)}, #{payload Nothing}, TThreadPool>>(
auto calldata = std::make_shared< ::bond::ext::gRPC::detail::client_unary_call_data< #{payload (methodTypeToMaybe methodInput)}, #{payload Nothing}>>(
_channel,
_ioManager,
_threadPool,
_scheduler,
context ? ::std::move(context) : ::std::make_shared< ::grpc::ClientContext>());
calldata->dispatch(rpcmethod_#{methodName}_, request);
}|]
Expand All @@ -284,26 +277,26 @@ inline void #{className}::#{proxyName}<TThreadPool>::Async#{methodName}(

serviceStartMethod = [lt|virtual void start(
::grpc::ServerCompletionQueue* #{cqParam},
std::shared_ptr<TThreadPool> #{tpParam}) override
const ::bond::ext::gRPC::Scheduler& #{schedulerParam}) override
{
BOOST_ASSERT(#{cqParam});
BOOST_ASSERT(#{tpParam});
BOOST_ASSERT(#{schedulerParam});

#{newlineSep 3 initMethodReceiveData serviceMethodsWithIndex}
}|]
where cqParam = uniqueName "cq" methodNames
tpParam = uniqueName "tp" methodNames
schedulerParam = uniqueName "scheduler" methodNames
initMethodReceiveData (index,Function{..}) = initMethodReceiveDataContent index methodName
initMethodReceiveData (index,Event{..}) = initMethodReceiveDataContent index methodName
initMethodReceiveDataContent index methodName = [lt|#{serviceRdMember methodName}.emplace(
*this,
#{index},
#{cqParam},
#{tpParam},
#{schedulerParam},
std::bind(&#{serviceName}::#{methodName}, this, std::placeholders::_1));|]

serviceMethodReceiveData Function{..} = [lt|::boost::optional< ::bond::ext::gRPC::detail::service_unary_call_data< #{bonded (methodTypeToMaybe methodInput)}, #{payload (methodTypeToMaybe methodResult)}, TThreadPool>> #{serviceRdMember methodName};|]
serviceMethodReceiveData Event{..} = [lt|::boost::optional< ::bond::ext::gRPC::detail::service_unary_call_data< #{bonded (methodTypeToMaybe methodInput)}, #{payload Nothing}, TThreadPool>> #{serviceRdMember methodName};|]
serviceMethodReceiveData Function{..} = [lt|::boost::optional< ::bond::ext::gRPC::detail::service_unary_call_data< #{bonded (methodTypeToMaybe methodInput)}, #{payload (methodTypeToMaybe methodResult)}>> #{serviceRdMember methodName};|]
serviceMethodReceiveData Event{..} = [lt|::boost::optional< ::bond::ext::gRPC::detail::service_unary_call_data< #{bonded (methodTypeToMaybe methodInput)}, #{payload Nothing}>> #{serviceRdMember methodName};|]

serviceVirtualMethod Function{..} = [lt|virtual void #{methodName}(::bond::ext::gRPC::unary_call< #{bonded (methodTypeToMaybe methodInput)}, #{payload (methodTypeToMaybe methodResult)}>) = 0;|]
serviceVirtualMethod Event{..} = [lt|virtual void #{methodName}(::bond::ext::gRPC::unary_call< #{bonded (methodTypeToMaybe methodInput)}, #{payload Nothing}>) = 0;|]
Expand Down
Loading

0 comments on commit 2685b75

Please sign in to comment.