ADTF  3.18.2
signal_listening_intf.h
Go to the documentation of this file.
1 
7 #pragma once
8 
9 #include "signal_registry_intf.h"
10 
12 #include <unordered_set>
13 #include <vector>
14 #include <chrono>
15 #include <optional>
16 
17 namespace adtf
18 {
19 namespace services
20 {
21 namespace ant
22 {
23 
28 {
29  public:
31  ADTF_IID(ISignalListening, "signal_listening.ant.services.adtf.iid");
32 
33  protected:
35  ~ISignalListening() = default;
36 
37  public:
42  {
43  public:
48  virtual void SignalAdded(const ISignalRegistry::tSignalAttributes& sSignalAttributes) = 0;
49 
54  virtual void SignalRemoved(const ISignalRegistry::tSignalAttributes& sSignalAttributes) = 0;
55  };
56 
61  {
62  public:
68  virtual void SignalUpdated(ISignalRegistry::tSignalID nSignalID, const ISignalRegistry::tSignalValue& sValue) = 0;
69  };
70 
71  public:
80 
87 
95 
103 };
104 
105 }
106 
107 namespace flash
108 {
109 
111 {
112  public:
114  ADTF_IID(ISignalListening, "signal_listening.flash.services.adtf.iid");
115 
116  protected:
118  ~ISignalListening() = default;
119 
120  public:
122  {
123  public:
130  {
131  return SignalUpdated(nSignalID, adtf::services::ant::ISignalRegistry::tSignalValue{base::flash::duration_cast<tTimeStamp>(sValue.nTimeStamp),
132  sValue.f64Value,
133  sValue.strTextValue});
134  }
136  {}
137  };
138 
139  public:
142 
150 
158 };
159 
160 }
161 
163 
164 namespace testing
165 {
166 
167 namespace ant
168 {
169 
171 {
172  cTestSignalValueNs() = default;
173  cTestSignalValueNs(const cTestSignalValueNs&) = default;
174  cTestSignalValueNs& operator=(const cTestSignalValueNs&) = default;
176  cTestSignalValueNs& operator=(cTestSignalValueNs&&) = default;
178  ISignalRegistry::tSignalValueNs(oSignalValue)
179  {
180  if (oSignalValue.strTextValue)
181  {
182  m_strTextValueCopy = oSignalValue.strTextValue;
183  }
184  }
185  std::string m_strTextValueCopy;
186 };
187 
190 {
191  public:
192  using tSignal = std::pair<ISignalRegistry::tSignalAttributes, std::vector<cTestSignalValueNs>>;
193  using tSignals = std::map<adtf::util::cString, tSignal>;
194 
195  public:
196  cTestListener()
197  {
198  m_oUpdateCount = 0;
199  THROW_IF_FAILED(_runtime->GetObject(m_pSignalListening));
200  THROW_IF_FAILED(m_pSignalListening->RegisterSignalsListener(*this));
201  }
202 
203  virtual ~cTestListener()
204  {
205  m_pSignalListening->UnregisterSignalsListener(*this);
206 
207  for (const auto& strSignal: m_oRequestedSignals)
208  {
209  const auto itSignal = m_oSignals.find(strSignal.c_str());
210  if (itSignal != m_oSignals.end())
211  {
212  m_pSignalListening->CancelSignalUpdates(itSignal->second.first.nSignalID, *this);
213  }
214  }
215  }
216 
217  virtual void SignalAdded(const ISignalRegistry::tSignalAttributes& sSignalAttributes) override
218  {
219  {
220  std::scoped_lock oSignalsGuard(m_oSignalsMutex);
221 
222  m_oIdMap[sSignalAttributes.nSignalID] = m_oSignals.emplace(adtf::util::cString(sSignalAttributes.strName), tSignal{sSignalAttributes, {}}).first;
223 
224  if (m_oRequestedSignals.find(sSignalAttributes.strName) != m_oRequestedSignals.end())
225  {
226  THROW_IF_FAILED(m_pSignalListening->RequestSignalUpdates(sSignalAttributes.nSignalID, *this));
227  }
228  }
229 
230  m_oSignalsChanged.notify_all();
231  }
232 
233  virtual void SignalRemoved(const ISignalRegistry::tSignalAttributes& sSignalAttributes) override
234  {
235  {
236  std::scoped_lock oGuard(m_oSignalsMutex);
237  m_oSignals.erase(sSignalAttributes.strName);
238  }
239 
240  m_oSignalsChanged.notify_all();
241  }
242 
243  virtual void SignalUpdated(ISignalRegistry::tSignalID nSignalID, const ISignalRegistry::tSignalValueNs& sValue) override
244  {
245  std::scoped_lock oGuard(m_oSignalsMutex);
246  ++m_oUpdateCount;
247  m_oIdMap.at(nSignalID)->second.second.push_back(cTestSignalValueNs(sValue));
248  }
249 
250  const tSignals& GetSignals() const
251  {
252  std::scoped_lock oSignalsGuard(m_oSignalsMutex);
253  return m_oSignals;
254  }
255 
256  tSignals GetCurrentSignals()
257  {
258  std::scoped_lock oSignalsGuard(m_oSignalsMutex);
259  return m_oSignals;
260  }
261 
262  void RequestUpdates(const char* strSignal)
263  {;
264  std::optional<ISignalRegistry::tSignalID> nId;
265 
266  {
267  std::scoped_lock oSignalsGuard(m_oSignalsMutex);
268  m_oRequestedSignals.insert(strSignal);
269 
270  const auto itSignal = m_oSignals.find(strSignal);
271  if (itSignal != m_oSignals.end())
272  {
273  nId = itSignal->second.first.nSignalID;
274  }
275  }
276 
277  if (nId)
278  {
279  THROW_IF_FAILED(m_pSignalListening->RequestSignalUpdates(*nId, *this));
280  }
281  }
282 
283  void CancelUpdates(const char* strSignal)
284  {
285  std::optional<ISignalRegistry::tSignalID> nId;
286 
287  {
288  std::scoped_lock oSignalsGuard(m_oSignalsMutex);
289  m_oRequestedSignals.erase(strSignal);
290  const auto itSignal = m_oSignals.find(strSignal);
291  if (itSignal != m_oSignals.end())
292  {
293  nId = itSignal->second.first.nSignalID;
294  }
295  }
296 
297  if (nId)
298  {
299  m_pSignalListening->CancelSignalUpdates(*nId, *this);
300  }
301  }
302 
303  bool WaitForUpdates(std::chrono::seconds nMaxSeconds, size_t nUpdateCountEachSignal)
304  {
305  auto oBeginTimePoint = std::chrono::steady_clock::now();
306  while (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - oBeginTimePoint) < nMaxSeconds)
307  {
308  const size_t oCurrentCount = m_oUpdateCount;
309  if (oCurrentCount < nUpdateCountEachSignal * m_oSignals.size())
310  {
311  std::this_thread::sleep_for(std::chrono::milliseconds(100));
312  }
313  else
314  {
315  return true;
316  }
317  }
318  const size_t oLastCount = m_oUpdateCount;
319  return (oLastCount >= nUpdateCountEachSignal * m_oSignals.size());
320  }
321 
322  bool WaitForSignal(const char* strName, std::chrono::nanoseconds tmTimeout)
323  {
324  std::unique_lock oLock(m_oSignalsMutex);
325  return m_oSignalsChanged.wait_for(oLock, tmTimeout, [&] { return m_oSignals.count(strName) > 0 ;});
326  }
327 
328  private:
329  adtf::ucom::object_ptr<ISignalListening> m_pSignalListening;
330  mutable std::recursive_mutex m_oSignalsMutex;
331  std::condition_variable_any m_oSignalsChanged;
332  tSignals m_oSignals;
333  std::unordered_map<ISignalRegistry::tSignalID, tSignals::iterator> m_oIdMap;
334  std::unordered_set<std::string> m_oRequestedSignals;
335  std::atomic<size_t> m_oUpdateCount;
336 };
337 
338 }
339 
340 using ant::cTestListener;
341 using ant::cTestSignalValueNs;
342 
343 }
344 
345 }
346 
347 }
Copyright © Audi Electronics Venture GmbH.
Callback interface for signal value updates.
virtual void SignalUpdated(ISignalRegistry::tSignalID nSignalID, const ISignalRegistry::tSignalValue &sValue)=0
Called for each update of a signal.
Callback interface that informs about added and/or removed signals.
virtual void SignalAdded(const ISignalRegistry::tSignalAttributes &sSignalAttributes)=0
Called when a new signal has been added.
virtual void SignalRemoved(const ISignalRegistry::tSignalAttributes &sSignalAttributes)=0
Called when a signal has been removed.
Interface for listening to signals that are available via the signal regsitry.
virtual tResult CancelSignalUpdates(ISignalRegistry::tSignalID nSignalID, ISignalListener &oListener)=0
Cancels a request for signal updates.
virtual tResult RegisterSignalsListener(ISignalsListener &oListener)=0
Registers a new listener for added and removed signals.
~ISignalListening()=default
Protected destructor --> Use implemented Destroy() instead of delete!
ADTF_IID(ISignalListening, "signal_listening.ant.services.adtf.iid")
Interface ID for the interface.
virtual tResult RequestSignalUpdates(ISignalRegistry::tSignalID nSignalID, ISignalListener &oListener)=0
Requests updates for a given signal.
virtual tResult UnregisterSignalsListener(ISignalsListener &oListener)=0
Unregisters a listener for added and removed signals.
size_t tSignalID
unique id for signals
virtual void SignalUpdated(ISignalRegistry::tSignalID nSignalID, const adtf::services::flash::ISignalRegistry::tSignalValueNs &sValue)
Called for each update of a signal.
virtual tResult CancelSignalUpdates(ISignalRegistry::tSignalID nSignalID, ISignalListener &oListener)=0
Cancels a request for signal updates.
~ISignalListening()=default
Protected destructor --> Use implemented Destroy() instead of delete!
virtual tResult RequestSignalUpdates(ISignalRegistry::tSignalID nSignalID, ISignalListener &oListener)=0
Requests updates for a given signal.
ADTF_IID(ISignalListening, "signal_listening.flash.services.adtf.iid")
Interface ID for the interface.
virtual void SignalAdded(const ISignalRegistry::tSignalAttributes &sSignalAttributes) override
Called when a new signal has been added.
virtual void SignalRemoved(const ISignalRegistry::tSignalAttributes &sSignalAttributes) override
Called when a signal has been removed.
virtual void SignalUpdated(ISignalRegistry::tSignalID nSignalID, const ISignalRegistry::tSignalValueNs &sValue) override
Called for each update of a signal.
Base class for every interface type within the uCOM.
Definition: object_intf.h:31
virtual tResult GetObject(iobject_ptr< IObject > &pObject, const char *strNameOID) const =0
Get registered object from object registry.
Object pointer implementation used for reference counting on objects of type IObject.
Definition: object_ptr.h:163
string_base< cStackString > cString
cString implementation for a stack string which works on stack if string is lower than A_UTILS_DEFAUL...
Definition: string.h:2778
Namespace for entire ADTF SDK.
adtf::ucom::IRuntime * _runtime
Global Runtime Pointer to reference to the current runtime.
Copyright © Audi Electronics Venture GmbH.
const char * strName
The name. Separate trees nodes with '/'.
const char * strTextValue
TEXTTABLE value or NULL (text representation of the value).
base::flash::tNanoSeconds nTimeStamp
Timestamp of signal value (-1 == undefined)
double f64Value
Physical signal value (this is where you put the values you want to display)
#define THROW_IF_FAILED(s)
throws if the expression returns a failed tResult