PLCnext API Documentation 23.0.2.9
NonBlockingNotificationRegistration3ArgumentsBuffer.hpp
1
2//
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
14namespace Arp { namespace System { namespace Nm
15{
16
17template<typename ArgumentsType>
20{
21private:
24
25public:
27
28 InsertResult Insert(const ArgumentsType& argument);
29
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
40private:
41 bool IsFullUnsynced() const;
42 bool IsFreeUnsynced(size_t index) const;
43
44private:
45 std::vector<ArgumentsType> arguments;
46 std::vector<size_t> freeList;
47 size_t next = 0;
48 mutable Mutex mutex;
49};
50
51template<typename ArgumentsType>
53 size_t capacity)
54 : arguments(capacity), freeList(capacity)
55{
56 std::iota(freeList.begin(), freeList.end(), 1);
57}
58
59template<typename ArgumentsType>
60typename NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::InsertResult
61NonBlockingNotificationRegistration3ArgumentsBuffer<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
75template<typename ArgumentsType>
76typename NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::RemoveResult
77NonBlockingNotificationRegistration3ArgumentsBuffer<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
90template<typename ArgumentsType>
91bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFull() const
92{
93 LockGuard lock(this->mutex);
94 return this->IsFullUnsynced();
95}
96
97template<typename ArgumentsType>
98bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFree(size_t index) const
99{
100 LockGuard lock(this->mutex);
101 return this->IsFreeUnsynced(index);
102}
103
104template<typename ArgumentsType>
105bool NonBlockingNotificationRegistration3ArgumentsBuffer<ArgumentsType>::IsFullUnsynced() const
106{
107 return this->next == this->arguments.size();
108}
109
110template<typename ArgumentsType>
111bool 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