DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
gRPCModule.h
Go to the documentation of this file.
1// This file is part of DynExp.
2
8#pragma once
9
10#include "stdafx.h"
11#include "DynExpCore.h"
12#include "../HardwareAdapters/HardwareAdaptergRPC.h"
13#include "../MetaInstruments/gRPCInstrument.h"
14
15namespace DynExpModule
16{
17 template <typename... gRPCServices>
18 class gRPCModule;
19
24 template <typename... gRPCServices>
26 {
27 public:
29 virtual ~gRPCModuleData() = default;
30
31 private:
35 void ResetImpl(dispatch_tag<ModuleDataBase>) override final { Init(); }
36
41
46 void Init() {}
47 };
48
53 template <typename... gRPCServices>
55 {
56 public:
63
64 virtual ~gRPCModuleParams() = default;
65
69 virtual const char* GetParamClassTag() const noexcept override { return "gRPCModuleParams"; }
70
72
73 private:
78
83
87 virtual const DynExp::NetworkParamsExtension* GetNetworkAddressParamsChild() const noexcept override { return &NetworkParams; }
88 };
89
94 template <typename... gRPCServices>
96 {
97 public:
98 using ObjectType = gRPCModule<gRPCServices...>;
99 using ParamsType = gRPCModuleParams<gRPCServices...>;
100
102 virtual ~gRPCModuleConfigurator() = default;
103 };
104
114 template <typename... gRPCServices>
116 {
121 template <typename gRPCService>
122 using ServicePtrType = std::unique_ptr<typename gRPCService::AsyncService>;
123
124 public:
125 using ParamsType = gRPCModuleParams<gRPCServices...>;
126 using ConfigType = gRPCModuleConfigurator<gRPCServices...>;
127 using ModuleDataType = gRPCModuleData<gRPCServices...>;
128
129 constexpr static auto Name() noexcept { return "gRPC Module"; }
130 constexpr static auto Category() noexcept { return "Network Modules (Servers)"; }
131
138
139 virtual ~gRPCModule() = default;
140
141 virtual std::string GetName() const override { return Name(); }
142 virtual std::string GetCategory() const override { return Category(); }
143
148 bool TreatModuleExceptionsAsWarnings() const override { return ServerRunning; }
149
155 std::chrono::milliseconds GetMainLoopDelay() const override final { return std::chrono::milliseconds(1); }
156
161 grpc::ServerCompletionQueue* GetServerQueue() const noexcept { return ServerQueue.get(); }
162
169 template <size_t Index>
170 auto& GetService() const noexcept { return *std::get<Index>(ServicePtrs); }
171
179 template <typename T>
180 auto& GetService() const noexcept { return *std::get<ServicePtrType<T>>(ServicePtrs); }
181
182 protected:
188 {
193 enum class StateType {
194 Init,
195 Process,
196 Exit
197 };
198
203
204 protected:
211
212 public:
213 virtual ~CallDataBase() {}
214
219 auto GetOwningModule() const noexcept { return OwningModule; }
220
227 void Proceed(DynExp::ModuleInstance& Instance) { StateMachine.Invoke(*this, Instance); }
228
229 protected:
234 auto* GetServerContext() noexcept { return &ServerContext; }
235
236 private:
241
246 virtual void InitChild(DynExp::ModuleInstance& Instance) = 0;
247
255 virtual void ProcessChild(DynExp::ModuleInstance& Instance) = 0;
257
264 {
265 InitChild(Instance);
266
267 return StateType::Process;
268 }
269
276 {
277 ProcessChild(Instance);
278
279 return StateType::Exit;
280 }
281
289 {
290 delete this;
291
292 return StateType::Exit;
293 }
294
299
304
309
312 grpc::ServerContext ServerContext;
313 };
314
326 template <typename DerivedType, typename gRPCService, typename RequestMessageType, typename ResponseMessageType,
327 typename std::enable_if_t<Util::is_contained_in_v<gRPCService, gRPCServices...>, int> = 0>
329 {
330 public:
337 static void MakeCall(const gRPCModule* const OwningModule, DynExp::ModuleInstance& Instance) { (new DerivedType(OwningModule))->Proceed(Instance); }
338
339 private:
341
347 using ResponseWriterType = grpc::ServerAsyncResponseWriter<ResponseMessageType>;
348
353 using RequestFuncType = std::function<void(typename gRPCService::AsyncService*, grpc::ServerContext*,
354 RequestMessageType*, ResponseWriterType*, grpc::CompletionQueue*, grpc::ServerCompletionQueue*, void*)>;
355
362 TypedCallDataBase(const gRPCModule* const OwningModule, const RequestFuncType RequestFunc) noexcept
363 : CallDataBase(OwningModule), RequestFunc(RequestFunc), ResponseWriter(this->GetServerContext()) {}
364
365 virtual ~TypedCallDataBase() = default;
366
370 void InitChild(DynExp::ModuleInstance& Instance) override final
371 {
372 // The address of *this* instance serves as the tag to distinguish multiple remote procedure calls.
373 RequestFunc(&this->GetOwningModule()->template GetService<gRPCService>(), this->GetServerContext(),
374 &RequestMessage, &ResponseWriter, this->GetOwningModule()->GetServerQueue(), this->GetOwningModule()->GetServerQueue(), this);
375 }
376
380 void ProcessChild(DynExp::ModuleInstance& Instance) override final
381 {
382 MakeCall(this->GetOwningModule(), Instance);
383
384 ProcessChildImpl(Instance);
385
386 ResponseWriter.Finish(ResponseMessage, grpc::Status::OK, this);
387 }
388
393
398 virtual void ProcessChildImpl(DynExp::ModuleInstance& Instance) = 0;
400
402 RequestMessageType RequestMessage;
403 ResponseMessageType ResponseMessage;
405 };
406
407 private:
413 auto MakeServicePtrTuple() { return std::make_tuple(std::make_unique<typename ServicePtrType<gRPCServices>::element_type>()...); }
414
419 {
420 void* Tag;
421 bool IsOK;
422
423 auto Result = ServerQueue->AsyncNext(&Tag, &IsOK, std::chrono::system_clock::now() + std::chrono::milliseconds(80));
424
425 if (Result == grpc::CompletionQueue::NextStatus::GOT_EVENT && Tag && IsOK)
426 static_cast<CallDataBase*>(Tag)->Proceed(Instance);
427
429 }
430
435 {
436 ServerQueue.reset();
437 Server.reset();
438
440 ServerRunning = false;
441
443 }
444
449
454
465
471 virtual void OnInitChild(DynExp::ModuleInstance* Instance) const {}
472
478 virtual void OnExitChild(DynExp::ModuleInstance* Instance) const {}
480
485
491 void OnInit(DynExp::ModuleInstance* Instance) const override final
492 {
493 std::string Address;
494 std::string ObjName;
495
496 {
497 auto ModuleParams = DynExp::dynamic_Params_cast<gRPCModule>(Instance->ParamsGetter());
498 Address = ModuleParams->NetworkParams.MakeAddress();
499 ObjName = ModuleParams->ObjectName;
500 } // ModuleParams unlocked here.
501
502 grpc::ServerBuilder ServerBuilder;
503 ServerBuilder.AddListeningPort(Address, grpc::InsecureServerCredentials());
504 std::apply([&ServerBuilder](auto&... ServicePtr) { (ServerBuilder.RegisterService(ServicePtr.get()), ...); }, ServicePtrs);
505 ServerQueue = ServerBuilder.AddCompletionQueue();
506 Server = ServerBuilder.BuildAndStart();
507
509 OnInitChild(Instance);
510
511 ServerRunning = true;
512 Util::EventLog().Log("gRPC server \"" + ObjName + "\" (" + GetCategoryAndName() + ") listening on " + Address + ".");
513 }
514
519 void OnExit(DynExp::ModuleInstance* Instance) const override final
520 {
521 OnExitChild(Instance);
522 Shutdown();
523
524 Util::EventLog().Log("gRPC server \"" + GetObjectName() + "\" (" + GetCategoryAndName() + ") shut down.");
525 }
527
531 void OnErrorChild(DynExp::ModuleInstance& Instance) const override final
532 {
533 Shutdown();
534 }
535
540 void Shutdown() const
541 {
542 if (Server)
543 Server->Shutdown();
544 if (ServerQueue)
545 ServerQueue->Shutdown();
546
548 }
549
554 void DrainServerQueue() const
555 {
556 if (!ServerQueue)
557 return;
558
559 bool Result = true;
560 while (Result)
561 {
562 void* Tag = nullptr;
563 bool IsOK;
564 Result = ServerQueue->Next(&Tag, &IsOK);
565
566 if (Result && Tag)
567 delete static_cast<CallDataBase*>(Tag);
568 }
569 }
570
574 mutable std::unique_ptr<grpc::ServerCompletionQueue> ServerQueue;
575
579 mutable std::unique_ptr<grpc::Server> Server;
580
584 std::tuple<ServicePtrType<gRPCServices>...> ServicePtrs;
585
589 mutable std::atomic<bool> ServerRunning;
590 };
591}
Defines DynExp's core module as an interface between the UI and DynExp objects.
Configurator class for gRPCModule.
Definition gRPCModule.h:96
virtual ~gRPCModuleConfigurator()=default
Data class for gRPCModule.
Definition gRPCModule.h:26
virtual ~gRPCModuleData()=default
void ResetImpl(dispatch_tag< ModuleDataBase >) override final
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition gRPCModule.h:35
void Init()
Called by ResetImpl(dispatch_tag<DynExp::ModuleDataBase>) overridden by this class to initialize the ...
Definition gRPCModule.h:46
virtual void ResetImpl(dispatch_tag< gRPCModuleData >)
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition gRPCModule.h:40
Parameter class for gRPCModule.
Definition gRPCModule.h:55
void ConfigureParamsImpl(dispatch_tag< ModuleParamsBase >) override final
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
Definition gRPCModule.h:77
DynExp::NetworkParamsExtension NetworkParams
Network address the gRPC server listens on.
Definition gRPCModule.h:71
gRPCModuleParams(DynExp::ItemIDType ID, const DynExp::DynExpCore &Core)
Constructs the parameters for a gRPCModule instance.
Definition gRPCModule.h:61
virtual void ConfigureParamsImpl(dispatch_tag< gRPCModuleParams >)
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
Definition gRPCModule.h:82
virtual ~gRPCModuleParams()=default
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...
Definition gRPCModule.h:69
virtual const DynExp::NetworkParamsExtension * GetNetworkAddressParamsChild() const noexcept override
Returns the network address parameters of a derived gRPC instrument. Override GetNetworkAddressParams...
Definition gRPCModule.h:87
Base class for all TypedCallDataBase classes. Instances of this class manage the state of a single re...
Definition gRPCModule.h:188
virtual void InitChild(DynExp::ModuleInstance &Instance)=0
Tells gRPC that this CallDataBase instance is ready to handle a respective (as determined by TypedCal...
static constexpr auto ProcessState
State machine state for the StateType::Process state.
Definition gRPCModule.h:303
StateType InitStateFunc(DynExp::ModuleInstance &Instance)
State function for the CallDataBase::InitState state. Calls InitChild().
Definition gRPCModule.h:263
Util::StateMachine< StateMachineStateType > StateMachine
State machine based on the states listed in StateType to manage this remote procedure call's state.
Definition gRPCModule.h:311
StateType ExitStateFunc(DynExp::ModuleInstance &Instance)
State function for the CallDataBase::ExitState state. Deletes this instance.
Definition gRPCModule.h:288
StateType
Type defining the possible states of remote procedure calls as used by CallDataBase::StateMachine.
Definition gRPCModule.h:193
@ Init
The remote procedure call's waiting state directly after construction.
@ Process
The remote procedure call's state when it was invoked by a client.
@ Exit
The remote procedure call's state after it has been handled by the server.
CallDataBase(const gRPCModule *const OwningModule) noexcept
Constructs a CallDataBase instance.
Definition gRPCModule.h:209
static constexpr auto InitState
State machine state for the StateType::Init state.
Definition gRPCModule.h:298
void Proceed(DynExp::ModuleInstance &Instance)
Calls the state function of the current state of CallDataBase::StateMachine by a call to Util::StateM...
Definition gRPCModule.h:227
virtual void ProcessChild(DynExp::ModuleInstance &Instance)=0
Creates a new TypedCallDataBase instance of the same type to handle a further remote procedure call,...
auto * GetServerContext() noexcept
Getter for the gRPC server context.
Definition gRPCModule.h:234
static constexpr auto ExitState
State machine state for the StateType::Exit state.
Definition gRPCModule.h:308
grpc::ServerContext ServerContext
Information about the remote procedure call. Refer to gRPC documentation.
Definition gRPCModule.h:312
const gRPCModule *const OwningModule
gRPC server this remote procedure call belongs to
Definition gRPCModule.h:310
StateType ProcessStateFunc(DynExp::ModuleInstance &Instance)
State function for the CallDataBase::ProcessState state. Calls ProcessChild().
Definition gRPCModule.h:275
auto GetOwningModule() const noexcept
Getter for the gRPC server this remote procedure call belongs to.
Definition gRPCModule.h:219
Derive from this class to implement a single remote procedure call handled by this gRPC server gRPCMo...
Definition gRPCModule.h:329
virtual void ProcessChildImpl(DynExp::ModuleInstance &Instance)=0
Override to implement the server's action to handle this remote procedure call. Particularly,...
grpc::ServerAsyncResponseWriter< ResponseMessageType > ResponseWriterType
Alias for the gRPC response writer which sends a message of type ResponseMessageType back to the clie...
Definition gRPCModule.h:347
const RequestFuncType RequestFunc
Request function to register the remote procedure call derived from TypedCallDataBase with gRPC.
Definition gRPCModule.h:401
ResponseWriterType ResponseWriter
gRPC response writer to send gRPCModule::ResponseMessage back to the client. Refer to gRPC documentat...
Definition gRPCModule.h:404
static void MakeCall(const gRPCModule *const OwningModule, DynExp::ModuleInstance &Instance)
Creates a new remote procedure call of this type which awaits requests from the client.
Definition gRPCModule.h:337
TypedCallDataBase(const gRPCModule *const OwningModule, const RequestFuncType RequestFunc) noexcept
Constructs a TypedCallDataBase instance.
Definition gRPCModule.h:362
RequestMessageType RequestMessage
Client's message sent along with its invocation of this remote procedure call.
Definition gRPCModule.h:402
void InitChild(DynExp::ModuleInstance &Instance) override final
Tells gRPC that this CallDataBase instance is ready to handle a respective (as determined by TypedCal...
Definition gRPCModule.h:370
ResponseMessageType ResponseMessage
Response the server sends back to the client by finishing the remote procedure call.
Definition gRPCModule.h:403
std::function< void(typename gRPCService::AsyncService *, grpc::ServerContext *, RequestMessageType *, ResponseWriterType *, grpc::CompletionQueue *, grpc::ServerCompletionQueue *, void *)> RequestFuncType
Alias for the remote procedure call function implemented by this class as part of an asynchronous gRP...
Definition gRPCModule.h:354
void ProcessChild(DynExp::ModuleInstance &Instance) override final
Creates a new TypedCallDataBase instance of the same type to handle a further remote procedure call,...
Definition gRPCModule.h:380
void OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
Definition gRPCModule.h:491
virtual void CreateInitialCallDataObjectsImpl(DynExp::Object::dispatch_tag< gRPCModule >, DynExp::ModuleInstance &Instance) const =0
Override by derived classes to let them call TypedCallDataBase::MakeCall of the TypedCallDataBase typ...
static constexpr auto Name() noexcept
Every derived class has to redefine this function.
Definition gRPCModule.h:129
auto MakeServicePtrTuple()
Constructs the gRPC services (gRPCServices) this gRPC server implements and packs them as a tuple.
Definition gRPCModule.h:413
virtual void OnInitChild(DynExp::ModuleInstance *Instance) const
Allows derived classes to lock instruments they are controlling (e.g. with calls to DynExp::RunnableI...
Definition gRPCModule.h:471
std::chrono::milliseconds GetMainLoopDelay() const override final
Specifies in which time intervals the module's event queue runs to handle pending events.
Definition gRPCModule.h:155
void OnErrorChild(DynExp::ModuleInstance &Instance) const override final
This handler gets called just before the module thread terminates due to an exception....
Definition gRPCModule.h:531
void Shutdown() const
Shuts down the gRPC server Server and its request queue ServerQueue. Then, it calls DrainServerQueue(...
Definition gRPCModule.h:540
std::unique_ptr< typename gRPCService::AsyncService > ServicePtrType
Alias for a pointer to a gRPC service.
Definition gRPCModule.h:122
auto & GetService() const noexcept
Returns a reference to a service this gRPC server implements selected by the service index in the gRP...
Definition gRPCModule.h:170
bool TreatModuleExceptionsAsWarnings() const override
Determines whether this module should be terminated if an exception leaves the module's main loop or ...
Definition gRPCModule.h:148
Util::DynExpErrorCodes::DynExpErrorCodes ModuleMainLoop(DynExp::ModuleInstance &Instance) override final
Module main loop. The function is executed periodically by the module thread. Also refer to GetMainLo...
Definition gRPCModule.h:418
static constexpr auto Category() noexcept
Every derived class has to redefine this function.
Definition gRPCModule.h:130
virtual void OnExitChild(DynExp::ModuleInstance *Instance) const
Allows derived classes to unlock instruments they are controlling (e.g. with calls to DynExp::Runnabl...
Definition gRPCModule.h:478
gRPCModule(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Constructs a ModuleBase instance.
Definition gRPCModule.h:135
grpc::ServerCompletionQueue * GetServerQueue() const noexcept
Getter for the gRPC server's request queue.
Definition gRPCModule.h:161
std::unique_ptr< grpc::Server > Server
Pointer to the actual gRPC server.
Definition gRPCModule.h:579
std::tuple< ServicePtrType< gRPCServices >... > ServicePtrs
Tuple of pointers to all the services this gRPC server implements.
Definition gRPCModule.h:584
void ResetImpl(dispatch_tag< ModuleBase >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition gRPCModule.h:434
virtual void ResetImpl(DynExp::Object::dispatch_tag< gRPCModule >)
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition gRPCModule.h:448
virtual ~gRPCModule()=default
std::atomic< bool > ServerRunning
Indicates whether Server is running.
Definition gRPCModule.h:589
virtual std::string GetName() const override
Returns the name of this Object type.
Definition gRPCModule.h:141
virtual std::string GetCategory() const override
Returns the category of this Object type.
Definition gRPCModule.h:142
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
Definition gRPCModule.h:519
std::unique_ptr< grpc::ServerCompletionQueue > ServerQueue
Queue holding the pending requests made to the gRPC server Server.
Definition gRPCModule.h:574
void DrainServerQueue() const
Empties ServerQueue removing every request and deleting associated CallDataBase instances.
Definition gRPCModule.h:554
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
Definition DynExpCore.h:127
Base class for modules. Modules implement programs on their own (e.g. measurement protocols or server...
Definition Module.h:392
ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs a ModuleBase instance.
Definition Module.cpp:189
Configurator class for ModuleBase.
Definition Module.h:374
Data structure to contain data which is synchronized in between different threads....
Definition Module.h:171
Refer to ParamsBase::dispatch_tag.
Definition Module.h:189
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:793
Parameter class for ModuleBase.
Definition Module.h:337
ModuleParamsBase(ItemIDType ID, const DynExpCore &Core)
Constructs the parameters for a ModuleBase instance.
Definition Module.h:348
Bundles several parameters to describe a network connection. Use in parameter classes.
std::string GetCategoryAndName() const
Builds a string from an Object's category and name to allow the user to identify an Object's type.
Definition Object.h:2158
const std::thread::id OwnerThreadID
Thread id of the thread which has constructed (and owns) this Object instance.
Definition Object.h:2302
const ParamsBasePtrType Params
Pointer to the parameter class instance belonging to this Object instance.
Definition Object.h:2303
auto GetObjectName(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns the name of this Object instance.
Definition Object.h:2128
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
const ItemIDType ID
ID of the Object this parameter class instance belongs to.
Definition Object.h:1779
const DynExpCore & Core
Reference to DynExp's core.
Definition Object.h:1780
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition Object.h:349
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
Definition Util.cpp:309
State machine state as used by class StateMachine. A state mainly wraps a state function of the membe...
Definition Util.h:1305
This class models a state machine. It keeps track of the current state and allows to invoke its assoc...
Definition Util.h:1435
DynExp's module namespace contains the implementation of DynExp modules which extend DynExp's core fu...
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
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.
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
constexpr bool is_contained_in_v
Value type of is_contained_in.
Definition Util.h:303
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
Definition Util.cpp:509
Accumulates include statements to provide a precompiled header.