cisst-saw
Loading...
Searching...
No Matches
mtsEventReceiver.h
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3
4/*
5
6 Author(s): Peter Kazanzides
7 Created on: 2010-09-24
8
9 (C) Copyright 2010-2026 Johns Hopkins University (JHU), All Rights Reserved.
10
11--- begin cisst license - do not edit ---
12
13This software is provided "as is" under an open source license, with
14no warranty. The complete license can be found in license.txt and
15http://www.cisst.org/cisst/license.txt.
16
17--- end cisst license ---
18*/
19
20
21#ifndef _mtsEventReceiver_h
22#define _mtsEventReceiver_h
23
28
29
85
89
90// Always include last
92
93
94// EventReceivers must be added before Bind (should add check for InterfaceProvidedOrOutput==0)
95// EventHandlers can be added at any time.
96// When Bind called,
97// if no EventReceiver, directly add EventHandler
98// if EventReceiver, set handler in it
99
101protected:
102 std::string Name;
103 mtsInterfaceRequired * Required; // Pointer to the required interface
105 bool OwnEventSignal; // true if we created our own thread signal
106
107 // There are 4 possible wait states.
108 // EVENT_RECEIVER_IDLE and EVENT_RECEIVER_WAITING are the only two that are required; they are
109 // equivalent to the Waiting boolean flag in the previous implementation.
110 // These are sufficient to wait on a stream of events, but not enough if waiting on a single event
111 // that could occur before the Wait is started, in which case the waiting thread could wait forever.
112 // This case could occur with blocking commands, such as VoidReturn and WriteReturn, where the basic
113 // approach is for the client thread to issue the remote command (to the server thread) and then
114 // wait for the server thread to signal when complete. The problem occurs if the server thread signals
115 // completion before the client thread starts waiting. The solution in this case is for the client
116 // thread to call PrepareToWait() before issuing the remote command. In that case, WaitState transitions
117 // to EVENT_RECEIVER_PREPARING. Subsequently, if the signal handler is called it changes WaitState to
118 // EVENT_RECEIVER_SIGNALED to indicate that the event happened before the Wait was called.
119 // Because WaitState is an integral type (enum), we assume that is is updated atomically. Nevertheless,
120 // the WaitMutex is necessary in the following cases:
121 // 1. When the event handler is called (by the server thread), it must check if WaitState is
122 // EVENT_RECEIVER_PREPARING and, if so, transition to EVENT_RECEIVER_SIGNALED. The mutex is needed
123 // to ensure that the client thread does not simultaneous attempt to change the state to
124 // EVENT_RECEIVER_WAITING.
125 // 2. When the client thread calls Wait or WaitWithTimeout and attempts to change WaitState from
126 // EVENT_RECEIVER_PREPARING (or EVENT_RECEIVER_IDLE if PrepareToWait was not called) to
127 // EVENT_RECEIVER_WAITING. Specifically, we do not want the server thread to simultaneously
128 // attempt to change WaitState from EVENT_RECEIVER_PREPARING to EVENT_RECEIVER_SIGNALED.
132
133 bool CheckRequired() const;
136
137public:
140
141 void SetName(const std::string &name) { Name = name; }
142 virtual std::string GetName() const { return Name; }
143
145 virtual void SetRequired(const std::string &name, mtsInterfaceRequired *req);
146
147 virtual void SetThreadSignal(osaThreadSignal *signal);
148
157 virtual bool PrepareToWait();
158
161 virtual bool Wait();
162
165 virtual bool WaitWithTimeout(double timeoutInSec);
166
168 virtual void ClearWait();
169
170 virtual void Detach();
171
173 virtual void ToStream(std::ostream & outputStream) const = 0;
174};
175
176
178inline std::ostream & operator << (std::ostream & output,
179 const mtsEventReceiverBase & receiver) {
180 receiver.ToStream(output);
181 return output;
182}
183
185protected:
186 mtsCommandVoid * Command; // Command object for calling EventHandler method
187 mtsCommandVoid * UserHandler; // User supplied event handler
188
189 // This one always gets added non-queued
190 void EventHandler(void);
191
192public:
195
198
200 void SetHandlerCommand(mtsCommandVoid * commandHandler);
201
202 // Same functionality as mtsInterfaceRequired::AddEventHandlerVoid.
203 template <class __classType>
204 inline mtsCommandVoid * SetHandler(void (__classType::*method)(void),
205 __classType * classInstantiation,
207 return CheckRequired() ? (Required->AddEventHandlerVoid(method, classInstantiation, this->GetName(), queueingPolicy)) : 0;
208 }
209
210 inline mtsCommandVoid * SetHandler(void (*function)(void),
212 return CheckRequired() ? (Required->AddEventHandlerVoid(function, this->GetName(), queueingPolicy)) : 0;
213 }
214
215 bool RemoveHandler(void);
216
218 void ToStream(std::ostream & outputStream) const;
219};
220
222protected:
223 mtsCommandWriteBase *Command; // Command object for calling EventHandler method
224 mtsCommandWriteBase *UserHandler; // User supplied event handler
226
227 // This one always gets added non-queued
229
230public:
233
236
239
240 // Same functionality as mtsInterfaceRequired::AddEventHandlerWrite.
241 template <class __classType, class __argumentType>
242 inline mtsCommandWriteBase * SetHandler(void (__classType::*method)(const __argumentType &),
243 __classType * classInstantiation,
245 return CheckRequired() ? (Required->AddEventHandlerWrite(method, classInstantiation, this->GetName(), queueingPolicy)) : 0;
246 }
247
248 // PK: Do we need the "generic" version (AddEventHandlerWriteGeneric)?
249
250
252 virtual bool PrepareToWait(mtsGenericObject &obj);
253
254 bool IsArgValid() const
255 { return (ArgPtr && ArgPtr->Valid()); }
256
257 // Note that we are using the Wait and WaitWithTimeout member functions from the base class.
260
264 virtual bool Wait();
265 virtual bool WaitWithTimeout(double timeoutInSec);
266
268 virtual void ClearWait();
269
270 //PK: might be nice to have this
271 //const mtsGenericObject *GetArgumentPrototype() const;
272
273 bool RemoveHandler(void);
274
276 void ToStream(std::ostream & outputStream) const;
277};
278
279
280#endif // _mtsEventReceiver_h
Definition mtsCommandVoid.h:44
Definition mtsCommandWriteBase.h:40
Definition mtsEventReceiver.h:100
virtual bool WaitWithTimeout(double timeoutInSec)
bool OwnEventSignal
Definition mtsEventReceiver.h:105
virtual std::string GetName() const
Definition mtsEventReceiver.h:142
virtual void ClearWait()
osaThreadSignal * EventSignal
Definition mtsEventReceiver.h:104
bool CheckRequired() const
void SetName(const std::string &name)
Definition mtsEventReceiver.h:141
virtual bool PrepareToWait()
virtual void SetRequired(const std::string &name, mtsInterfaceRequired *req)
virtual void SetThreadSignal(osaThreadSignal *signal)
virtual void ToStream(std::ostream &outputStream) const =0
osaMutex WaitMutex
Definition mtsEventReceiver.h:131
WaitStates WaitState
Definition mtsEventReceiver.h:130
mtsInterfaceRequired * Required
Definition mtsEventReceiver.h:103
virtual bool Wait()
virtual void Detach()
std::string Name
Definition mtsEventReceiver.h:102
virtual ~mtsEventReceiverBase()
WaitStates
Definition mtsEventReceiver.h:129
@ EVENT_RECEIVER_WAITING
Definition mtsEventReceiver.h:129
@ EVENT_RECEIVER_SIGNALED
Definition mtsEventReceiver.h:129
@ EVENT_RECEIVER_PREPARING
Definition mtsEventReceiver.h:129
@ EVENT_RECEIVER_IDLE
Definition mtsEventReceiver.h:129
mtsCommandVoid * SetHandler(void(__classType::*method)(void), __classType *classInstantiation, mtsEventQueueingPolicy queueingPolicy=MTS_INTERFACE_EVENT_POLICY)
Definition mtsEventReceiver.h:204
void ToStream(std::ostream &outputStream) const
void SetHandlerCommand(mtsCommandVoid *commandHandler)
mtsCommandVoid * Command
Definition mtsEventReceiver.h:186
mtsCommandVoid * UserHandler
Definition mtsEventReceiver.h:187
void EventHandler(void)
mtsCommandVoid * GetCommand(void)
mtsCommandVoid * SetHandler(void(*function)(void), mtsEventQueueingPolicy queueingPolicy=MTS_INTERFACE_EVENT_POLICY)
Definition mtsEventReceiver.h:210
bool RemoveHandler(void)
virtual void ClearWait()
bool RemoveHandler(void)
void SetHandlerCommand(mtsCommandWriteBase *commandHandler)
virtual bool PrepareToWait(mtsGenericObject &obj)
bool IsArgValid() const
Definition mtsEventReceiver.h:254
mtsCommandWriteBase * Command
Definition mtsEventReceiver.h:223
void EventHandler(const mtsGenericObject &arg)
mtsCommandWriteBase * UserHandler
Definition mtsEventReceiver.h:224
virtual bool Wait()
virtual bool WaitWithTimeout(double timeoutInSec)
mtsCommandWriteBase * GetCommand()
mtsGenericObject * ArgPtr
Definition mtsEventReceiver.h:225
void ToStream(std::ostream &outputStream) const
mtsCommandWriteBase * SetHandler(void(__classType::*method)(const __argumentType &), __classType *classInstantiation, mtsEventQueueingPolicy queueingPolicy=MTS_INTERFACE_EVENT_POLICY)
Definition mtsEventReceiver.h:242
Base class for data object in cisstMultiTask.
Definition mtsGenericObject.h:52
Definition mtsInterfaceRequired.h:83
Define a Mutex object.
Definition osaMutex.h:48
Definition osaThreadSignal.h:41
#define CISST_EXPORT
Definition cmnExportMacros.h:50
std::ostream & operator<<(std::ostream &output, const mtsEventReceiverBase &receiver)
Definition mtsEventReceiver.h:178
Rules of exporting.
mtsEventQueueingPolicy
Definition mtsForwardDeclarations.h:48
@ MTS_INTERFACE_EVENT_POLICY
Definition mtsForwardDeclarations.h:48
Declaration of mtsInterfaceRequired.
Forward declarations and #define for cisstOSAbstraction.
Declaration of osaMutex.