DynExp
Highly flexible laboratory automation for dynamically changing experiments.
gRPCInstrument.h
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
9 #pragma once
10 
11 #include "stdafx.h"
12 #include "DynExpCore.h"
15 
16 #include "Common.pb.h"
17 #include "Common.grpc.pb.h"
18 
19 namespace DynExpInstr
20 {
21  template <typename BaseInstr, typename std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
22  class gRPCInstrument;
23 
27  namespace gRPCInstrumentTasks
28  {
33  template <typename BaseInstr, std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
34  class InitTask : public BaseInstr::InitTaskType
35  {
36  protected:
40  template <typename Type>
42 
43  private:
49  {
50  {
51  auto InstrParams = DynExp::dynamic_Params_cast<gRPCInstrument<BaseInstr, 0, gRPCStubs...>>(Instance.ParamsGetter());
52  auto InstrData = DynExp::dynamic_InstrumentData_cast<gRPCInstrument<BaseInstr, 0, gRPCStubs...>>(Instance.InstrumentDataGetter());
53 
54  // TODO: Offer SSL credentials.
55  InstrData->StubPtrs = std::make_tuple(gRPCStubs::NewStub(grpc::CreateChannel(InstrParams->NetworkParams.MakeAddress(), grpc::InsecureChannelCredentials()))...);
56  } // InstrParams and InstrData unlocked here.
57 
59  }
60 
65  };
66 
71  template <typename BaseInstr, std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
72  class ExitTask : public BaseInstr::ExitTaskType
73  {
74  protected:
78  template <typename Type>
80 
81  private:
86  {
87  try
88  {
90 
91  auto InstrData = DynExp::dynamic_InstrumentData_cast<gRPCInstrument<BaseInstr, 0, gRPCStubs...>>(Instance.InstrumentDataGetter());
92 
93  InstrData->ResetStubPtrs();
94  } // InstrData unlocked here.
95  catch (...)
96  {
97  // Swallow any exception which might arise from instrument shutdown since a failure
98  // of this function is not considered a severe error.
99  }
100  }
101 
106  };
107 
112  template <typename BaseInstr, std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
113  class UpdateTask : public BaseInstr::UpdateTaskType
114  {
115  protected:
119  template <typename Type>
121 
122  private:
127  {
129  }
130 
134  virtual void UpdateFuncImpl(dispatch_tag<UpdateTask>, DynExp::InstrumentInstance& Instance) {}
135  };
136  }
137 
142  template <typename gRPCStub>
143  using StubPtrType = std::shared_ptr<typename gRPCStub::Stub>;
144 
149  template <typename BaseInstr, typename std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
150  class gRPCInstrumentData : public BaseInstr::InstrumentDataType
151  {
152  friend class gRPCInstrumentTasks::InitTask<BaseInstr, 0, gRPCStubs...>;
153  friend class gRPCInstrumentTasks::ExitTask<BaseInstr, 0, gRPCStubs...>;
154 
155  public:
162  template <typename... ArgTs>
163  gRPCInstrumentData(ArgTs&& ...Args) : BaseInstr::InstrumentDataType(std::forward<ArgTs>(Args)...) {}
164 
165  virtual ~gRPCInstrumentData() = default;
166 
173  template <size_t Index>
174  auto GetStub() const noexcept { return std::get<Index>(StubPtrs); }
175 
182  template <typename T>
183  auto GetStub() const noexcept { return std::get<StubPtrType<T>>(StubPtrs); }
184 
185  private:
189  void ResetStubPtrs() { std::apply([](auto&... StubPtr) { (StubPtr.reset(), ...); }, StubPtrs); }
190 
195  {
196  ResetStubPtrs();
197 
199  }
200 
205 
209  std::tuple<StubPtrType<gRPCStubs>...> StubPtrs;
210  };
211 
216  template <typename BaseInstr, typename std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
217  class gRPCInstrumentParams : public BaseInstr::ParamsType
218  {
219  public:
225  : BaseInstr::ParamsType(ID, Core), NetworkParams(*this) {}
226 
227  virtual ~gRPCInstrumentParams() = default;
228 
232  virtual const char* GetParamClassTag() const noexcept override { return "gRPCInstrumentParams"; }
233 
235 
236  private:
241  {
243  }
244 
249 
253  virtual const DynExp::NetworkParamsExtension* GetNetworkAddressParamsChild() const noexcept override { return &NetworkParams; }
254  };
255 
260  template <typename BaseInstr, typename std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
261  class gRPCInstrumentConfigurator : public BaseInstr::ConfigType
262  {
263  public:
264  using ObjectType = gRPCInstrument<BaseInstr, 0, gRPCStubs...>;
265  using ParamsType = gRPCInstrumentParams<BaseInstr, 0, gRPCStubs...>;
266 
268  virtual ~gRPCInstrumentConfigurator() = default;
269 
270  private:
274  virtual DynExp::ParamsBasePtrType MakeParams(DynExp::ItemIDType ID, const DynExp::DynExpCore& Core) const override { return DynExp::MakeParams<gRPCInstrumentConfigurator>(ID, Core); }
275  };
276 
291  template <typename BaseInstr, typename std::enable_if_t<std::is_base_of_v<DynExp::InstrumentBase, BaseInstr>, int>, typename... gRPCStubs>
292  class gRPCInstrument : public BaseInstr
293  {
294  public:
295  using ParamsType = gRPCInstrumentParams<BaseInstr, 0, gRPCStubs...>;
296  using ConfigType = gRPCInstrumentConfigurator<BaseInstr, 0, gRPCStubs...>;
297  using InstrumentDataType = gRPCInstrumentData<BaseInstr, 0, gRPCStubs...>;
298 
299  constexpr static auto Name() noexcept { return "gRPC Instrument"; }
300  constexpr static auto Category() noexcept { return "Network Instruments (Clients)"; }
301 
302  protected:
306  gRPCInstrument(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
307  : BaseInstr(OwnerThreadID, std::move(Params)) {}
308 
309  public:
310  virtual ~gRPCInstrument() {}
311 
312  virtual std::string GetName() const override { return Name(); }
313  virtual std::string GetCategory() const override { return Category(); }
314 
315  private:
320 
325 
329  virtual std::unique_ptr<DynExp::InitTaskBase> MakeInitTask() const override { return DynExp::MakeTask<gRPCInstrumentTasks::InitTask<BaseInstr, 0, gRPCStubs...>>(); }
330 
334  virtual std::unique_ptr<DynExp::ExitTaskBase> MakeExitTask() const override { return DynExp::MakeTask<gRPCInstrumentTasks::ExitTask<BaseInstr, 0, gRPCStubs...>>(); }
335 
339  virtual std::unique_ptr<DynExp::UpdateTaskBase> MakeUpdateTask() const override { return DynExp::MakeTask<gRPCInstrumentTasks::UpdateTask<BaseInstr, 0, gRPCStubs...>>(); }
340  };
341 
351  template <typename gRPCStub, typename RequestMsgType, typename ResponseMsgType>
352  using StubFuncPtrType = grpc::Status(gRPCStub::*)(grpc::ClientContext*, const RequestMsgType&, ResponseMsgType*);
353 
372  template <typename gRPCStub, typename RequestMsgType, typename ResponseMsgType>
373  inline ResponseMsgType InvokeStubFunc(StubPtrType<gRPCStub> StubPtr, StubFuncPtrType<gRPCStub, RequestMsgType, ResponseMsgType> StubFunc, const RequestMsgType& RequestMsg)
374  {
375  grpc::ClientContext Context;
376  ResponseMsgType ReplyMsg;
377 
378  if (!StubPtr)
379  throw Util::InvalidStateException("A stub pointer has not been initialized yet.");
380  if (!StubFunc)
381  throw Util::InvalidArgException("StubFunc must not be nullptr.");
382 
383  static const auto Timeout = std::chrono::milliseconds(2000);
384  Context.set_deadline(std::chrono::system_clock::now() + Timeout);
385 
386  auto Result = (*StubPtr.*StubFunc)(&Context, RequestMsg, &ReplyMsg);
387  if (!Result.ok())
388  throw DynExpHardware::gRPCException(Result);
389 
390  return ReplyMsg;
391  }
392 }
Implementation of a data stream meta instrument and of data streams input/output devices might work o...
Defines DynExp's core module as an interface between the UI and DynExp objects.
Implementation of a hardware adapter to communicate over TCP sockets using gRPC.
Defines an exception caused by an operation involving the gRPC library and communication over a TCP s...
Configurator class for gRPCInstrument.
virtual DynExp::ParamsBasePtrType MakeParams(DynExp::ItemIDType ID, const DynExp::DynExpCore &Core) const override
Override to make derived classes call DynExp::MakeParams with the correct configurator type derived f...
Data class for gRPCInstrument.
virtual ~gRPCInstrumentData()=default
virtual void ResetImpl(DynExp::InstrumentDataBase::dispatch_tag< gRPCInstrumentData >)
Refer to DynExp::InstrumentDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl()...
gRPCInstrumentData(ArgTs &&...Args)
Constructs a gRPCInstrumentData instance and forwards all arguments passed to the constructor to the ...
auto GetStub() const noexcept
Returns a stub pointer this gRPCInstrument uses selected by the stub index in the gRPCStubs list of g...
void ResetImpl(DynExp::InstrumentDataBase::dispatch_tag< typename BaseInstr::InstrumentDataType >) override final
Refer to DynExp::InstrumentDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl()...
void ResetStubPtrs()
Sets all pointers contained in StubPtrs to nullptr.
std::tuple< StubPtrType< gRPCStubs >... > StubPtrs
Tuple of pointers to all the stubs this gRPCInstrument uses.
Parameter class for gRPCInstrument.
virtual ~gRPCInstrumentParams()=default
gRPCInstrumentParams(DynExp::ItemIDType ID, const DynExp::DynExpCore &Core)
Constructs the parameters for a gRPCInstrument instance.
DynExp::NetworkParamsExtension NetworkParams
Network address of the gRPC server to connect to.
virtual const char * GetParamClassTag() const noexcept override
This function is intended to be overridden once in each derived class returning the name of the respe...
virtual const DynExp::NetworkParamsExtension * GetNetworkAddressParamsChild() const noexcept override
Returns the network address parameters of a derived gRPC instrument. Override GetNetworkAddressParams...
virtual void ConfigureParamsImpl(DynExp::InstrumentParamsBase::dispatch_tag< gRPCInstrumentParams >)
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
void ConfigureParamsImpl(DynExp::InstrumentParamsBase::dispatch_tag< typename BaseInstr::ParamsType >) override final
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
Defines a task for deinitializing an instrument within an instrument inheritance hierarchy....
virtual void ExitFuncImpl(dispatch_tag< ExitTask >, DynExp::InstrumentInstance &Instance)
Deinitializes the respective instrument within the instrument inheritance hierarchy....
void ExitFuncImpl(dispatch_tag< typename BaseInstr::ExitTaskType >, DynExp::InstrumentInstance &Instance) override final
Deinitializes the respective instrument within the instrument inheritance hierarchy....
Defines a task for initializing an instrument within an instrument inheritance hierarchy....
void InitFuncImpl(dispatch_tag< typename BaseInstr::InitTaskType >, DynExp::InstrumentInstance &Instance) override final
Initializes the respective instrument within the instrument inheritance hierarchy....
virtual void InitFuncImpl(dispatch_tag< InitTask< BaseInstr, 0, gRPCStubs... >>, DynExp::InstrumentInstance &Instance)
Initializes the respective instrument within the instrument inheritance hierarchy....
Defines a task for updating an instrument within an instrument inheritance hierarchy....
void UpdateFuncImpl(dispatch_tag< typename BaseInstr::UpdateTaskType >, DynExp::InstrumentInstance &Instance) override final
Updates the respective instrument within the instrument inheritance hierarchy. Call UpdateFuncImpl() ...
Meta instrument template for transforming meta instruments into network instruments,...
void ResetImpl(DynExp::Object::dispatch_tag< BaseInstr >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual std::unique_ptr< DynExp::UpdateTaskBase > MakeUpdateTask() const override
Factory function for an update task (UpdateTaskBase). Override to define the desired update task in d...
virtual void ResetImpl(DynExp::Object::dispatch_tag< gRPCInstrument >)
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual std::string GetCategory() const override
Returns the category of this Object type.
virtual std::unique_ptr< DynExp::InitTaskBase > MakeInitTask() const override
Factory function for an init task (InitTaskBase). Override to define the desired initialization task ...
virtual std::unique_ptr< DynExp::ExitTaskBase > MakeExitTask() const override
Factory function for an exit task (ExitTaskBase). Override to define the desired deinitialization tas...
constexpr static auto Name() noexcept
Every derived class has to redefine this function.
virtual std::string GetName() const override
Returns the name of this Object type.
gRPCInstrument(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Constructs an instrument instance.
constexpr static auto Category() noexcept
Every derived class has to redefine this function.
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
Definition: DynExpCore.h:127
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1151
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1120
Refer to ParamsBase::dispatch_tag.
Definition: Instrument.h:146
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
Definition: Instrument.h:772
Bundles several parameters to describe a network connection. Use in parameter classes.
Refer to ParamsBase::dispatch_tag.
Definition: Object.h:2018
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition: Object.h:349
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1182
An invalid argument like a null pointer has been passed to a function.
Definition: Exception.h:137
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition: Exception.h:150
DynExp's instrument namespace contains the implementation of DynExp instruments which extend DynExp's...
Definition: Instrument.h:1254
ResponseMsgType InvokeStubFunc(StubPtrType< gRPCStub > StubPtr, StubFuncPtrType< gRPCStub, RequestMsgType, ResponseMsgType > StubFunc, const RequestMsgType &RequestMsg)
Invokes a gRPC stub function as a remote procedure call. Waits for a fixed amount of time (2 seconds)...
std::shared_ptr< typename gRPCStub::Stub > StubPtrType
Alias for a pointer to a gRPC stub.
grpc::Status(gRPCStub::*)(grpc::ClientContext *, const RequestMsgType &, ResponseMsgType *) StubFuncPtrType
Alias for a pointer to a gRPC stub function, which can be invoked as a remote procedure call.
std::unique_ptr< TaskT > MakeTask(ArgTs &&...Args)
Factory function to create a task to be enqueued in an instrument's task queue.
Definition: Instrument.h:63
T::ParamsType * dynamic_Params_cast(ParamsBasePtrType::element_type *Params)
Casts the parameter base class to a derived Object's parameter class.
Definition: Object.h:1835
auto dynamic_InstrumentData_cast(Util::SynchronizedPointer< From > &&InstrumentDataPtr)
Casts the data base class From into a derived InstrumentBase's (To) data class keeping the data locke...
Definition: Instrument.h:810
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition: Object.h:1807
size_t ItemIDType
ID type of objects/items managed by DynExp.
Accumulates include statements to provide a precompiled header.