DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
BlockingCollection.h
Go to the documentation of this file.
1#pragma once
2
3#include "Common.h"
4#include "System/Object.h"
5#include "System/Array.h"
12
13namespace DotNetDupe {
14 namespace System {
15 namespace Collections {
16 namespace Concurrent {
17
24 template <typename T>
25 class BlockingCollection : public Object {
26 private:
27 mutable Threading::CriticalSection m_csLock;
31 int m_iBoundedCapacity;
32 bool m_bIsAddingCompleted;
33
34 public:
36 BlockingCollection() : m_iBoundedCapacity(-1), m_bIsAddingCompleted(false) {}
37
41 explicit BlockingCollection(int iBoundedCapacity) : m_iBoundedCapacity(iBoundedCapacity), m_bIsAddingCompleted(false) {
42 if (iBoundedCapacity <= 0) {
43 throw System::ArgumentException("Bounded capacity must be greater than zero.");
44 }
45 }
46
50 void Add(const T& item) {
51 m_csLock.Enter();
52
53 if (m_bIsAddingCompleted) {
54 m_csLock.Leave();
55 throw System::InvalidOperationException("The collection has been marked as complete for adding.");
56 }
57
58 if (m_iBoundedCapacity > 0) {
59 while (!m_bIsAddingCompleted && m_list.GetCount() >= m_iBoundedCapacity) {
60 m_cvAdd.Wait(m_csLock);
61 }
62
63 if (m_bIsAddingCompleted) {
64 m_csLock.Leave();
65 throw System::InvalidOperationException("The collection has been marked as complete for adding.");
66 }
67 }
68
69 m_list.AddLast(item);
70 m_cvTake.Pulse();
71 m_csLock.Leave();
72 }
73
74 bool TryAdd(const T& item, int iTimeoutMilliseconds = 0) {
75 m_csLock.Enter();
76
77 if (m_bIsAddingCompleted) {
78 m_csLock.Leave();
79 return false;
80 }
81
82 if (m_iBoundedCapacity > 0 && m_list.GetCount() >= m_iBoundedCapacity) {
83 if (iTimeoutMilliseconds <= 0) {
84 m_csLock.Leave();
85 return false;
86 }
87
88 if (m_bIsAddingCompleted || m_list.GetCount() < m_iBoundedCapacity) {
89 // Condition already met
90 } else {
91 bool bWaitResult = m_cvAdd.Wait(m_csLock, iTimeoutMilliseconds);
92 if (!bWaitResult || m_bIsAddingCompleted || m_list.GetCount() >= m_iBoundedCapacity) {
93 m_csLock.Leave();
94 return false;
95 }
96 }
97 }
98
99 m_list.AddLast(item);
100 m_cvTake.Pulse();
101 m_csLock.Leave();
102 return true;
103 }
104
105 T Take() {
106 T item;
107 if (!TryTake(item, -1)) {
108 throw System::InvalidOperationException("The collection is empty and has been marked as complete for adding.");
109 }
110
111 return item;
112 }
113
114 bool TryTake(T& item, int iTimeoutMilliseconds = 0) {
115 m_csLock.Enter();
116
117 if (m_list.GetCount() == 0) {
118 if (m_bIsAddingCompleted) {
119 m_csLock.Leave();
120 return false;
121 }
122
123 if (iTimeoutMilliseconds == 0) {
124 m_csLock.Leave();
125 return false;
126 }
127
128 if (iTimeoutMilliseconds < 0) {
129 while (!m_bIsAddingCompleted && m_list.GetCount() == 0) {
130 m_cvTake.Wait(m_csLock);
131 }
132 } else {
133 if (!m_bIsAddingCompleted && m_list.GetCount() == 0) {
134 m_cvTake.Wait(m_csLock, iTimeoutMilliseconds);
135 }
136 }
137
138 if (m_list.GetCount() == 0) {
139 m_csLock.Leave();
140 return false;
141 }
142 }
143
144 item = m_list.GetFirst()->Value;
145 m_list.RemoveFirst();
146
147 if (m_iBoundedCapacity > 0) {
148 m_cvAdd.Pulse();
149 }
150
151 m_csLock.Leave();
152 return true;
153 }
154
156 Threading::CriticalSectionLock lock(m_csLock);
157 m_bIsAddingCompleted = true;
158 m_cvTake.PulseAll();
159 m_cvAdd.PulseAll();
160 }
161
162 bool IsAddingCompleted() const {
163 Threading::CriticalSectionLock lock(m_csLock);
164 return m_bIsAddingCompleted;
165 }
166
167 bool IsCompleted() const {
168 Threading::CriticalSectionLock lock(m_csLock);
169 return m_bIsAddingCompleted && m_list.GetCount() == 0;
170 }
171
172 int GetCount() const {
173 Threading::CriticalSectionLock lock(m_csLock);
174 return m_list.GetCount();
175 }
176
177 int GetBoundedCapacity() const {
178 return m_iBoundedCapacity;
179 }
180
182 Threading::CriticalSectionLock lock(m_csLock);
183 return m_list.ToArray();
184 }
185 };
186
187 }
188 }
189 }
190}
Defines the exception thrown when an invalid argument is provided to a method.
Provides methods for creating, manipulating, searching, and sorting arrays.
Defines common cross-platform macros, export decorators, and fundamental types.
Provides condition variable synchronization primitive for thread coordination.
Provides a re-entrant mutual exclusion primitive for thread synchronization.
Defines the exception thrown when a method call is invalid for the object's current state.
Provides an RAII-style scoped lock wrapper around synchronization primitives.
Base object class for DotNetDupe mirroring .NET System.Object.
The exception that is thrown when one of the arguments provided to a method is not valid.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition Array.h:29
void Add(const T &item)
Adds an item to the BlockingCollection.
BlockingCollection(int iBoundedCapacity)
Initializes a new instance of the BlockingCollection class with the specified upper-bound.
bool TryAdd(const T &item, int iTimeoutMilliseconds=0)
BlockingCollection()
Initializes a new instance of the BlockingCollection class without an upper-bound.
The exception that is thrown when a method call is invalid for the object's current state.
Supports all classes in the DotNetDupe class hierarchy.
Definition Object.h:18
Provides a synchronization primitive that can be used to block a thread, or multiple threads,...
Provides a re-entrant mutual exclusion primitive for thread synchronization.
Lock< CriticalSection > CriticalSectionLock
Convenience alias for Lock<CriticalSection>.
Definition Lock.h:71