You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mitlib.pub/MITLib/Utility/ConcurrentQueue.h

197 lines
4.3 KiB
C

#pragma once
#include <afx.h>
#include <list>
#include "thread.h"
#include "Utility.h"
#define DEFAULT_CAPACITY 1000
template <typename T> class CConcurrentQueue
{
public:
CConcurrentQueue(size_t capacity = DEFAULT_CAPACITY) : m_capacity(capacity)
{
m_spaceAvailableEvent.Set();
}
// Destroy the queue and all it's content
~CConcurrentQueue(void)
{
while(!m_queue.empty()) {
m_queue.pop_front();
}
}
// Pushes object T when space is available
// Throws std::exception on timeout or when interrupted
bool Push(T item, int milliSeconds = INFINITE) {
bool bPushedItem = false;
CSingleLock lock(&m_mutex);
while(!bPushedItem) {
try
{
// Wait for space to be available
m_spaceAvailableEvent.WaitEvtEx(milliSeconds);
} catch(std::exception &e) {
printf("Push failed: %s\n", e.what());
throw;
}
// wait for critical section to become available
lock.Lock();
// inside critical section
{
size_t size = m_queue.size();
// Make sure that nobody else that was waiting pushed first
if( size < m_capacity) {
m_queue.push_back(item);
bPushedItem = true;
if (size == 0)
{
// Queue was empty, now there is one item
m_dataAvailableEvent.Set();
}
size++;
if (size >= m_capacity) {
// Queue is now full
m_spaceAvailableEvent.Reset();
}
}
}
lock.Unlock();
}
return true;
}
// Pushes object T when space is available
// Throws std::exception on timeout or when interrupted
bool PushFront(T item, int milliSeconds = INFINITE) {
bool bPushedItem = false;
CSingleLock lock(&m_mutex);
while(!bPushedItem) {
try
{
// Wait for space to be available
m_spaceAvailableEvent.WaitEvtEx(milliSeconds);
} catch(std::exception &e) {
printf("Push failed: %s\n", e.what());
throw;
}
// wait for critical section to become available
lock.Lock();
// inside critical section
{
size_t size = m_queue.size();
// Make sure that nobody else that was waiting pushed first
if( size < m_capacity) {
m_queue.push_front(item);
bPushedItem = true;
if (size == 0)
{
// Queue was empty, now there is one item
m_dataAvailableEvent.Set();
}
size++;
if (size >= m_capacity) {
// Queue is now full
m_spaceAvailableEvent.Reset();
}
}
}
lock.Unlock();
}
return true;
}
// Returns object T when available
// Throws std::exception on timeout or when interrupted
T Pop(int milliSeconds = INFINITE)
{
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
T item;
PopEx(item, milliSeconds, true);
return item;
}
// Returns object T when available
// Throws std::exception on timeout or when interrupted
bool Pop(T &item, int milliSeconds = INFINITE)
{
return PopEx(item, milliSeconds, false);
}
int Size()
{
int size;
// wait for mutex to become available
CSingleLock lock(&m_mutex, true);
// inside critical section
{
size = m_queue.size();
}
return size;
}
private:
std::list<T> m_queue;
CMutex m_mutex;
CEvt m_dataAvailableEvent;
CEvt m_spaceAvailableEvent;
size_t m_capacity;
bool PopEx(T &item, int milliSeconds = INFINITE, bool bThrowException = true)
{
CHighResPerformanceCounter counter;
counter.StartCnt();
long remaining = milliSeconds;
CSingleLock lock(&m_mutex);
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
while (true)
{
// wait for event to be signaled that there is data
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
if (bThrowException)
{
m_dataAvailableEvent.WaitEvtEx(remaining);
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
}
else if (!m_dataAvailableEvent.WaitEvt(remaining))
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
{
return false;
}
// wait for mutex to become available
lock.Lock();
// inside critical section
{
// try to deque something - it<69>s possible that the queue is empty because another
// thread pre-empted before us and got the last item in the queue
size_t size = m_queue.size();
if (size > 0)
{
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
item = m_queue.front();
m_queue.pop_front();
if (size == 1) {
m_dataAvailableEvent.Reset();
}
if (size <= m_capacity) {
// There was no space, now there is
m_spaceAvailableEvent.Set();
}
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
return true;
}
}
lock.Unlock();
MitLib 1.40.00 The MitLib 1.40 release is the first release using Git and Gerrit. This release branch will be used to push non-breaking changes and as continuation of the MitLib 1.39 branch Changes in MitLib 1.40.00: * (bug 416) Re-authentication to clear messages ** Added option to stop after user has been re-authenticated, default the system will start to run after re-authentication. See the below option that can be added to GuiDll.ini ** Fix bug where the user could open a door while the re-authentication dialog was displayed. After re-authentication the machine would start to run * During development of (bug 419) some issues were found in the MyWait class. Although the fix (bug 419) is not included in this release due to breaking changes, the non-breaking bug fixes have been included * Fix stack overflow in <code>DebugLogTiming</code> when it was called with arguments that would result in a string of more then 100 character * Fix bug where CMyWait would not timeout due to messages being send the calling thread * Fix bug in MySocket where OnReceive could be called if CMyWait was used * Fixed some memory leakes where <code>auto_ptr</code> was used with arrays * Fixed some memory leakes where <code>delete</code> was used with <code>new[]</code> instead of <code>delete []</code> == Configuration Changes == === GuiDll.ini === * Option to stop the machine after the user has re-authenticated, see (bug 416) [Authentication] StopAfterHigherLevelAuthentication = TRUE == Upgrading == Upgrading from [[MitLib 1.39]] does not require any changes. Change-Id: I73b6cb107f7bb84babb2682fa2ee913d6c57974e
12 years ago
remaining = counter.GetTimeRemaining(milliSeconds);
}
}
};