| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef _FIFO_QUEUE_H_
 | 
					
						
							|  |  |  | #define _FIFO_QUEUE_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // a simple lockless thread-safe,
 | 
					
						
							|  |  |  | // single reader, single writer queue
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | #include "Atomic.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | namespace Common | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | class FifoQueue | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	FifoQueue() : m_size(0) | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		 m_write_ptr = m_read_ptr = new ElementPtr(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~FifoQueue() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// this will empty out the whole queue
 | 
					
						
							|  |  |  | 		delete m_read_ptr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	u32 Size() const | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 		return m_size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool Empty() const | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		//return (m_read_ptr == m_write_ptr);
 | 
					
						
							|  |  |  | 		return (0 == m_size); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-04 19:34:50 -05:00
										 |  |  | 	T& Front() const | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		return *m_read_ptr->current; | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-04 19:34:50 -05:00
										 |  |  | 	template <typename Arg> | 
					
						
							|  |  |  | 	void Push(Arg&& t) | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		// create the element, add it to the queue
 | 
					
						
							| 
									
										
										
										
											2013-04-04 19:34:50 -05:00
										 |  |  | 		m_write_ptr->current = new T(std::forward<Arg>(t)); | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 		// set the next pointer to a new element ptr
 | 
					
						
							|  |  |  | 		// then advance the write pointer 
 | 
					
						
							|  |  |  | 		m_write_ptr = m_write_ptr->next = new ElementPtr(); | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 		Common::AtomicIncrement(m_size); | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	void Pop() | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 		Common::AtomicDecrement(m_size); | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 		ElementPtr *const tmpptr = m_read_ptr; | 
					
						
							|  |  |  | 		// advance the read pointer
 | 
					
						
							|  |  |  | 		m_read_ptr = m_read_ptr->next; | 
					
						
							|  |  |  | 		// set the next element to NULL to stop the recursive deletion
 | 
					
						
							|  |  |  | 		tmpptr->next = NULL; | 
					
						
							|  |  |  | 		delete tmpptr;	// this also deletes the element
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	bool Pop(T& t) | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 		if (Empty()) | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-04 19:34:50 -05:00
										 |  |  | 		t = std::move(Front()); | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 		Pop(); | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	// not thread-safe
 | 
					
						
							|  |  |  | 	void Clear() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_size = 0; | 
					
						
							|  |  |  | 		delete m_read_ptr; | 
					
						
							|  |  |  | 		m_write_ptr = m_read_ptr = new ElementPtr(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	// stores a pointer to element
 | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | 	// and a pointer to the next ElementPtr
 | 
					
						
							|  |  |  | 	class ElementPtr | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		ElementPtr() : current(NULL), next(NULL) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		~ElementPtr() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (current) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				delete current; | 
					
						
							|  |  |  | 				// recusion ftw
 | 
					
						
							|  |  |  | 				if (next) | 
					
						
							|  |  |  | 					delete next; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		T *volatile current; | 
					
						
							|  |  |  | 		ElementPtr *volatile next; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ElementPtr *volatile m_write_ptr; | 
					
						
							|  |  |  | 	ElementPtr *volatile m_read_ptr; | 
					
						
							| 
									
										
										
										
											2010-08-10 04:12:32 +00:00
										 |  |  | 	volatile u32 m_size; | 
					
						
							| 
									
										
										
										
											2010-07-29 10:21:48 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |