PLCnext API Documentation  22.9.0.33
NonBlockingNotificationRegistration3ArgumentsBuffer.hpp
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 #pragma once
7 #include "Arp/System/Commons/Threading/LockGuard.hpp"
8 #include "Arp/System/Commons/Threading/Mutex.hpp"
9 #include "Arp/System/Nm/NonBlockingNotificationRegistration3ArgumentsBufferBase.hpp"
10 #include <algorithm>
11 #include <limits>
12 #include <numeric>
13 
14 namespace Arp { namespace System { namespace Nm
15 {
16 
17 template<typename ArgumentsType>
20 {
21 private:
24 
25 public:
27 
28  InsertResult Insert(const ArgumentsType& argument);
29 
30  struct RemoveResult
31  {
32  ArgumentsType Args{};
33  bool IsValid = false;
34  };
35  RemoveResult Remove(size_t index);
36 
37  bool IsFull() const;
38  bool IsFree(size_t index) const;
39 
40 private:
41  bool IsFullUnsynced() const;
42  bool IsFreeUnsynced(size_t index) const;
43 
44 private:
45  std::vector<ArgumentsType> arguments;
46  std::vector<size_t> freeList;
47  size_t next = 0;
48  mutable Mutex mutex;
49 };
50 
51 template<typename ArgumentsType>
53  size_t capacity)
54  : arguments(capacity), freeList(capacity)
55 {
56  std::iota(freeList.begin(), freeList.end(), 1);
57 }
58 
59 template<typename ArgumentsType>
60 typename NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::InsertResult
61 NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::Insert(const ArgumentsType& argument)
62 {
63  LockGuard lock(this->mutex);
64  if (this->IsFullUnsynced())
65  {
66  return {this->arguments.size(), false};
67  }
68 
69  size_t current = this->next;
70  this->arguments.at(current) = argument;
71  this->next = std::exchange(this->freeList.at(current), this->arguments.size());
72  return {current, true};
73 }
74 
75 template<typename ArgumentsType>
76 typename NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::RemoveResult
77 NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::Remove(size_t index)
78 {
79  LockGuard lock(this->mutex);
80  if ((index >= this->arguments.size()) || this->IsFreeUnsynced(index))
81  {
82  return {{}, false};
83  }
84 
85  this->freeList.at(index) = this->next;
86  this->next = index;
87  return {this->arguments.at(index), true};
88 }
89 
90 template<typename ArgumentsType>
91 bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFull() const
92 {
93  LockGuard lock(this->mutex);
94  return this->IsFullUnsynced();
95 }
96 
97 template<typename ArgumentsType>
98 bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFree(size_t index) const
99 {
100  LockGuard lock(this->mutex);
101  return this->IsFreeUnsynced(index);
102 }
103 
104 template<typename ArgumentsType>
105 bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFullUnsynced() const
106 {
107  return this->next == this->arguments.size();
108 }
109 
110 template<typename ArgumentsType>
111 bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFreeUnsynced(size_t index) const
112 {
113  return (index < this->arguments.size()) &&
114  ((this->next == index) ||
115  (std::find(this->freeList.begin(), this->freeList.end(), index) != this->freeList.end()));
116 }
117 
118 }}} // namespace Arp::System::Nm
Simple lock guard, acquiring lock on construction and release it on destruction.
Definition: LockGuard.hpp:15
Mutual exclusion object to prevent data from concurrent modifications.
Definition: Mutex.hpp:26
Internal base class for ArgumentsBuffer
Definition: NonBlockingNotificationRegistration3ArgumentsBufferBase.hpp:19
Definition: NonBlockingNotificationRegistration3ArgumentsBuffer.hpp:20
@ System
System components used by the System, Device, Plc or Io domains.
Root namespace for the PLCnext API
Definition: NonBlockingNotificationRegistration3ArgumentsBufferBase.hpp:38
Definition: NonBlockingNotificationRegistration3ArgumentsBuffer.hpp:31