PLCnext API Documentation  22.9.0.33
NonBlockingNotificationRegistration.hpp
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 
7 
8 #pragma once
9 
10 
11 #include "Arp/System/Nm/NonBlockingNotificationSendingAdapter.hpp"
12 #include "Arp/System/Nm/NotificationRegistrationBase.hpp"
13 
14 
15 namespace Arp { namespace System { namespace Nm
16 {
17 
18 
31 template<typename PayloadType>
33  : public NotificationRegistrationBase<NonBlockingNotificationRegistration<PayloadType>>
34 {
35 private:
36  using base_type =
38 
39 public:
40  using payload_type = PayloadType;
41 
46 
53  NonBlockingNotificationRegistration(const String& notificationName, const String& senderName,
54  Severity severity, INonBlockingNotificationSending& notificationSending);
55 
56  NonBlockingNotificationRegistration(const String& notificationName, const String& senderName,
58 
62 
63 
66 
71  template<typename... Args>
73 
78  template<typename... Args>
80  const DateTime& timestamp, Args&& ... args);
81 
84 
87 
89  bool IsCompleted() const;
90 
91 private:
92  void Initialize();
93  void DisposeImpl() override;
94 
95  bool IsNotificationNameIdValid() const;
96 
97 
98 private:
99  INonBlockingNotificationSending* NotificationSending = nullptr;
100  Future<NotificationNameIdType> futureNotificationNameId;
101  Future<NotificationIdType> futureNotificationId;
102  Future<void> futureUnregister;
103 
104  enum class State
105  {
106  Uninitialized,
107  RegisterCalled,
108  SendCalled,
109  UnregisterCalled
110  };
111  State state = State::Uninitialized;
112 };
113 
114 
115 template<typename PayloadType>
117  const String& notificationName, const String& senderName, Severity severity,
118  INonBlockingNotificationSending& notificationSending)
119  : base_type(notificationName, senderName, severity), NotificationSending(&notificationSending)
120 {
121  this->Initialize();
122 }
123 
124 template<typename PayloadType>
126  const String& notificationName, const String& senderName, Severity severity,
128  : base_type(notificationName, senderName, severity),
129  NotificationSending(adapter)
130 {
131  this->Initialize();
132 }
133 
134 
135 template<typename PayloadType>
137  NonBlockingNotificationRegistration<PayloadType>&& other)
138  : base_type(std::move(other)),
139  NotificationSending(std::move(other.NotificationSending)),
140  futureNotificationNameId(std::move(other.futureNotificationNameId)),
141  futureNotificationId(std::move(other.futureNotificationId)),
142  futureUnregister(std::move(other.futureUnregister)),
143  state(std::move(other.state))
144 {
145  other.NotificationSending = nullptr;
146  other.state = State::Uninitialized;
147 }
148 
149 
150 template<typename PayloadType>
151 NonBlockingNotificationRegistration<PayloadType>::~NonBlockingNotificationRegistration()
152 {
153  this->Dispose();
154 }
155 
156 
157 template<typename PayloadType>
158 NonBlockingNotificationRegistration<PayloadType>& NonBlockingNotificationRegistration<PayloadType>::
159 operator=(NonBlockingNotificationRegistration<PayloadType>&& other)
160 {
161  if (this == &other)
162  {
163  return *this;
164  }
165 
166  base_type::operator=(std::move(other));
167 
168  this->NotificationSending = std::move(other.NotificationSending);
169  other.NotificationSending = nullptr;
170 
171  this->futureNotificationNameId = std::move(other.futureNotificationNameId);
172  this->futureNotificationId = std::move(other.futureNotificationId);
173  this->futureUnregister = std::move(other.futureUnregister);
174 
175  this->state = std::move(other.state);
176  other.state = State::Uninitialized;
177 
178  return *this;
179 }
180 
181 
182 template<typename PayloadType>
183 void NonBlockingNotificationRegistration<PayloadType>::Initialize()
184 {
185  if ((this->NotificationSending != nullptr) && (!this->IsNotificationNameIdValid()))
186  {
187  auto* adapterPtr =
188  dynamic_cast<NonBlockingNotificationSendingAdapter*>(this->NotificationSending);
189  if (adapterPtr != nullptr)
190  {
191  adapterPtr->NonBlockingRegisterNotification(this->NotificationName, this->SenderName,
192  this->severity, this->GetPayloadTypeId(), this->futureNotificationNameId);
193  }
194  else
195  {
196  this->futureNotificationNameId =
197  this->NotificationSending->NonBlockingRegisterNotification(this->NotificationName,
198  this->SenderName, this->severity, this->GetPayloadTypeId());
199  }
200  this->state = State::RegisterCalled;
201  }
202 }
203 
204 
205 template<typename PayloadType>
206 void NonBlockingNotificationRegistration<PayloadType>::DisposeImpl()
207 {
208  if ((this->NotificationSending != nullptr) && this->IsNotificationNameIdValid())
209  {
210  auto* adapterPtr =
211  dynamic_cast<NonBlockingNotificationSendingAdapter*>(this->NotificationSending);
212  if (adapterPtr != nullptr)
213  {
214  adapterPtr->NonBlockingUnregisterNotification(
215  this->GetNotificationNameId(), this->futureUnregister);
216  }
217  else
218  {
219  this->futureUnregister = this->NotificationSending->NonBlockingUnregisterNotification(
220  this->GetNotificationNameId());
221  }
222  this->futureNotificationNameId = Future<NotificationNameIdType>();
223  this->futureNotificationId = Future<NotificationIdType>();
224  this->state = State::UnregisterCalled;
225 
226  if (adapterPtr != nullptr)
227  {
228  delete this->NotificationSending;
229  }
230  this->NotificationSending = nullptr;
231  }
232 }
233 
234 
235 template<typename PayloadType>
236 template<typename... Args>
238  Args&& ... args)
239 {
240  return this->SendNotificationWithTimestamp(DateTime::Now(), std::forward<Args>(args)...);
241 }
242 
243 
244 template<typename PayloadType>
245 template<typename... Args>
248  const DateTime& timestamp, Args&& ... args)
249 {
250  if ((this->NotificationSending == nullptr) || (!this->IsNotificationNameIdValid()))
251  {
252  this->futureNotificationId = Future<NotificationIdType>();
253  }
254  else
255  {
256 #ifndef ARP_CXX_COMPILER_MSC
257  // This optimization is not enabled on MSVC++. Capturing an c-string by value does not work.
258  auto adapterPtr =
259  dynamic_cast<NonBlockingNotificationSendingAdapter*>(this->NotificationSending);
260  if (adapterPtr != nullptr)
261  {
262  std::function<RawPayloadType()> createPayloadFunctor = [args...]()
263  {
264  return PayloadType{args...}.MoveOutRawPayload();
265  };
266  adapterPtr->NonBlockingSendNotification(this->futureNotificationNameId.GetValue(),
267  timestamp, std::move(createPayloadFunctor), this->futureNotificationId);
268  }
269  else
270 #endif // #ifndef ARP_CXX_COMPILER_MSC
271  {
272  this->futureNotificationId = this->NotificationSending->NonBlockingSendNotification(
273  this->futureNotificationNameId.GetValue(), timestamp,
274  PayloadType{std::forward<Args>(args)...});
275  }
276  this->state = State::SendCalled;
277  }
278  return this->futureNotificationId;
279 }
280 
281 
282 template<class PayloadType>
285 {
286  return this->futureNotificationNameId.GetValue();
287 }
288 
289 
290 template<class PayloadType>
292 {
293  return this->futureNotificationId.GetValue();
294 }
295 
296 
297 template<class PayloadType>
299 {
300  switch (this->state)
301  {
302  case State::Uninitialized:
303  return true;
304 
305  case State::RegisterCalled:
306  return this->futureNotificationNameId.HasValue();
307 
308  case State::SendCalled:
309  return this->futureNotificationId.HasValue();
310 
311  case State::UnregisterCalled:
312  return this->futureUnregister.HasValue();
313 
314  default:
315  return false;
316  }
317 }
318 
319 
320 template<class PayloadType>
322 {
323  return this->futureNotificationNameId.HasValue() &&
324  this->futureNotificationNameId.GetValue().IsValid();
325 }
326 
327 
328 }}} // namespace Arp::System::Nm
The class contains date and time informations.
Definition: DateTime.hpp:45
static DateTime Now(void)
Gets the current time as DateTime, expressed as the UTC time.
Future object as proxy for return value an asynchronous function call
Definition: Future.hpp:191
Future object as proxy for return value an asynchronous function call
Definition: Future.hpp:114
Interface for non blocking sending of Notifications
Definition: INonBlockingNotificationSending.hpp:22
constexpr T GetValue() const noexcept
Returns the underlying value
Definition: IdType.hpp:94
Proxy object for a non-blocking NotificationRegistration
Definition: NonBlockingNotificationRegistration.hpp:34
NonBlockingNotificationRegistration(const String &notificationName, const String &senderName, Severity severity, INonBlockingNotificationSending &notificationSending)
Creates a NotificationRegistration
Definition: NonBlockingNotificationRegistration.hpp:116
Future< NotificationIdType > SendNotification(Args &&... args)
Sends a notification
Definition: NonBlockingNotificationRegistration.hpp:237
bool IsCompleted() const
Returns true if the last operation is completed
Definition: NonBlockingNotificationRegistration.hpp:298
Future< NotificationIdType > SendNotificationWithTimestamp(const DateTime &timestamp, Args &&... args)
Sends a notification with a specified timestamp
Definition: NonBlockingNotificationRegistration.hpp:247
NotificationNameIdType GetNotificationNameId() const override
Returns the NotificationNameId
Definition: NonBlockingNotificationRegistration.hpp:284
NonBlockingNotificationRegistration()=default
Creates an empty NotificationRegistration
NotificationIdType GetLastNotificationId() const
Returns the id of the last send Notification
Definition: NonBlockingNotificationRegistration.hpp:291
Adapter for INonBlockingNotificationSending with additional functions
Definition: NonBlockingNotificationSendingAdapter.hpp:25
Base class with common behavior of NotificationRegistration and NonBlockingNotificationRegistration
Definition: NotificationRegistrationBase.hpp:22
@ System
System components used by the System, Device, Plc or Io domains.
Severity
Enumeration of Severities for notifications
Definition: Severity.hpp:15
std::vector< Arp::System::Rsc::Services::RscVariant< RawPayloadTypeLength > > RawPayloadType
type for the internally transferred payloads
Definition: NotificationManagerTypes.hpp:34
Root namespace for the PLCnext API
Namespace of the C++ standard library