/*=============================================================================
	TStack.h
	
	$Log: CAAtomicFIFO.h,v $
	Revision 1.3.4.1  2005/04/21 19:28:35  dwyatt
	bring over a few things from TOT for the benefit of test tools
	
	Revision 1.4  2005/03/11 01:41:01  dwyatt
	renaming
	
	Revision 1.3  2004/09/30 21:02:59  jcm10
	add missing includes
	
	Revision 1.2  2004/06/02 22:39:45  dwyatt
	add empty()
	
	Revision 1.1  2004/05/26 00:33:09  dwyatt
	moved from Source/CAServices/AudioUnits/Generators/TStack.h
	
	Revision 1.2  2004/01/07 22:29:00  dwyatt
	work in progress
	
	Revision 1.1  2003/12/12 22:16:25  dwyatt
	initial checkin
	
	created Tue Oct 28 2003, Doug Wyatt
	Copyright (c) 2003 Apple Computer, Inc.  All Rights Reserved

	$NoKeywords: $
=============================================================================*/

#ifndef __TStack_h__
#define __TStack_h__

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
	#include <CoreServices/CoreServices.h>
#else
	#include <DriverSynchronization.h>
#endif

//  linked list FIFO stack, elements are pushed and popped atomically
//  class T must implement set_next() and get_next()
template <class T>
class TAtomicStack {
public:
	TAtomicStack() : mHead(NULL) { }
	
	// non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
	void	push_NA(T *item)
	{
		item->set_next(mHead);
		mHead = item;
	}
	
	T *		pop_NA()
	{
		T *result = mHead;
		if (result)
			mHead = result->get_next();
		return result;
	}
	
	bool	empty() { return mHead == NULL; }
	
	// atomic routines
	void	push_atomic(T *item)
	{
		T *head;
		do {
			head = mHead;
			item->set_next(head);
		} while (!CompareAndSwap(UInt32(head), UInt32(item), (UInt32 *)&mHead));
	}
	
	T *		pop_atomic()
	{
		T *result;
		do {
			if ((result = mHead) == NULL)
				break;
		} while (!CompareAndSwap(UInt32(result), UInt32(result->get_next()), (UInt32 *)&mHead));
		return result;
	}
	
	T *		pop_all()
	{
		T *result;
		do {
			if ((result = mHead) == NULL)
				break;
		} while (!CompareAndSwap(UInt32(result), 0L, (UInt32 *)&mHead));
		return result;
	}
	
protected:
	T *		mHead;
};

#endif // __TStack_h__
