diff options
Diffstat (limited to 'src/OSSupport')
-rw-r--r-- | src/OSSupport/CriticalSection.h | 5 | ||||
-rw-r--r-- | src/OSSupport/Queue.h | 178 | ||||
-rw-r--r-- | src/OSSupport/SocketThreads.h | 3 |
3 files changed, 186 insertions, 0 deletions
diff --git a/src/OSSupport/CriticalSection.h b/src/OSSupport/CriticalSection.h index 1bfe81439..73a71f5e1 100644 --- a/src/OSSupport/CriticalSection.h +++ b/src/OSSupport/CriticalSection.h @@ -14,9 +14,14 @@ public: void Lock(void); void Unlock(void); + // IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined + // The fake versions (in Release) will not effect the program in any way #ifdef _DEBUG bool IsLocked(void); bool IsLockedByCurrentThread(void); + #else + bool IsLocked(void) { return false; } + bool IsLockedByCurrentThread(void) { return false; } #endif // _DEBUG private: diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h new file mode 100644 index 000000000..6c3d58295 --- /dev/null +++ b/src/OSSupport/Queue.h @@ -0,0 +1,178 @@ + +// Queue.h + +// Implements the cQueue class representing a thread safe queue + +#pragma once + +/* +Items can be added multiple times to a queue, there are two functions for +adding, EnqueueItem() and EnqueueItemIfNotPresent(). The first one always +enqueues the specified item, the second one checks if the item is already +present and only queues it if it isn't. + +Usage: +To create a queue of type T, instantiate a cQueue<T> object. You can also +modify the behavior of the queue when deleting items and when adding items +that are already in the queue by providing a second parameter, a class that +implements the functions Delete() and Combine(). An example is given in +cQueueFuncs and is used as the default behavior. +*/ + +/// This empty struct allows for the callback functions to be inlined +template<class T> +struct cQueueFuncs +{ +public: + + /// Called when an Item is deleted from the queue without being returned + static void Delete(T) {}; + + /// Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted + static void Combine(T & a_existing, const T & a_new) {}; +}; + + + + + +template <class ItemType, class Funcs = cQueueFuncs<ItemType> > +class cQueue +{ + // The actual storage type for the queue + typedef typename std::list<ItemType> QueueType; + + // Make iterator an alias for the QueueType's iterator + typedef typename QueueType::iterator iterator; + +public: + cQueue() {} + ~cQueue() {} + + + /// Enqueues an item to the queue, may block if other threads are accessing the queue. + void EnqueueItem(ItemType a_Item) + { + cCSLock Lock(m_CS); + m_Contents.push_back(a_Item); + m_evtAdded.Set(); + } + + + /// Enqueues an item in the queue if not already present (as determined by operator ==). Blocks other threads from accessing the queue. + void EnqueueItemIfNotPresent(ItemType a_Item) + { + cCSLock Lock(m_CS); + + for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr) + { + if ((*itr) == a_Item) + { + Funcs::Combine(*itr, a_Item); + return; + } + } + m_Contents.push_back(a_Item); + m_evtAdded.Set(); + } + + + /// Dequeues an item from the queue if any are present. + /// Returns true if successful. Value of item is undefined if dequeuing was unsuccessful. + bool TryDequeueItem(ItemType & item) + { + cCSLock Lock(m_CS); + if (m_Contents.size() == 0) + { + return false; + } + item = m_Contents.front(); + m_Contents.pop_front(); + m_evtRemoved.Set(); + return true; + } + + + /// Dequeues an item from the queue, blocking until an item is available. + ItemType DequeueItem(void) + { + cCSLock Lock(m_CS); + while (m_Contents.size() == 0) + { + cCSUnlock Unlock(Lock); + m_evtAdded.Wait(); + } + ItemType item = m_Contents.front(); + m_Contents.pop_front(); + m_evtRemoved.Set(); + return item; + } + + + /// Blocks until the queue is empty. + void BlockTillEmpty(void) + { + cCSLock Lock(m_CS); + while (!m_Contents.empty()) + { + cCSUnlock Unlock(Lock); + m_evtRemoved.Wait(); + } + } + + + /// Removes all Items from the Queue, calling Delete on each of them. + void Clear(void) + { + cCSLock Lock(m_CS); + while (!m_Contents.empty()) + { + Funcs::Delete(m_Contents.front()); + m_Contents.pop_front(); + } + } + + + /// Returns the size at time of being called. + /// Do not use to determine whether to call DequeueItem(), use TryDequeueItem() instead + size_t Size(void) + { + cCSLock Lock(m_CS); + return m_Contents.size(); + } + + + /// Removes the item from the queue. If there are multiple such items, only the first one is removed. + /// Returns true if the item has been removed, false if no such item found. + bool Remove(ItemType a_Item) + { + cCSLock Lock(m_CS); + for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr) + { + if ((*itr) == a_Item) + { + m_Contents.erase(itr); + m_evtRemoved.Set(); + return true; + } + } + return false; + } + +private: + /// The contents of the queue + QueueType m_Contents; + + /// Mutex that protects access to the queue contents + cCriticalSection m_CS; + + /// Event that is signalled when an item is added + cEvent m_evtAdded; + + /// Event that is signalled when an item is removed (both dequeued or erased) + cEvent m_evtRemoved; +}; + + + + diff --git a/src/OSSupport/SocketThreads.h b/src/OSSupport/SocketThreads.h index ecbac3aeb..858729c49 100644 --- a/src/OSSupport/SocketThreads.h +++ b/src/OSSupport/SocketThreads.h @@ -61,6 +61,9 @@ public: class cCallback { public: + // Force a virtual destructor in all subclasses: + virtual ~cCallback() {} + /// Called when data is received from the remote party virtual void DataReceived(const char * a_Data, int a_Size) = 0; |