/* SCE CONFIDENTIAL
 * PLAYSTATION(R)3 Programmer Tool Runtime Library 084.006
 * Copyright (C) 2006 Sony Computer Entertainment Inc.
 * All Rights Reserved.
 */

/* QueueControl::Abstract - queue control base class
 */

#ifndef __CELL_DAISY_QCTL_H__
#define __CELL_DAISY_QCTL_H__

#include <cell/daisy/daisy_defs.h>
#include <cell/daisy/snprintf.h>

namespace cell {
	namespace Daisy {
		namespace QueueControl {

			template<SizeType tSize, QueueIO tQueueIO>
			class Abstract {
			private:

				/* static assertion */
				static int sAssertDummy[
					(tSize != 0)
					? 1 : -1];

			protected:

				/* current pointer */
#ifdef __SPU__
				qword mPointer;
#else
				int32_t mPointer;
#endif

			public:
	
				CELL_DAISY_INLINE
				uint32_t getTag(){return 0;}

				CELL_DAISY_INLINE
				unsigned int isOutOfOrder() {
					return 0;
				}

				static const QueueControlType sQueueControlType; 
				static const QueueIO sPort = tQueueIO;
				static const SizeType sSize = tSize;
 			    static const SizeType sQueueMaxSize = 0xffffffff;

				/* constructor definition */
				Abstract();

				/* virtual destructor definition */
				virtual ~Abstract(){}

				CELL_DAISY_INLINE
					PointerType getPointerFromSequenceNumber(int sequenceNumber)
					{
						if (tSize == 1 || tSize == 2 || tSize == 4 || tSize == 8 ||
							tSize == 16 || tSize == 32) {
							return (sequenceNumber + tSize) % tSize;
						} else {
							if (__builtin_expect(sequenceNumber < (int)tSize && sequenceNumber >= 0, 1)) {
								return sequenceNumber;
							} else {
								return (sequenceNumber + tSize) % tSize;
							}
						}
					}
      
				CELL_DAISY_INLINE
					PointerType getPointerFromSequenceNumber(uint64_t sequenceNumber)
					{
						if (tSize == 1 || tSize == 2 || tSize == 4 || tSize == 8 ||
							tSize == 16 || tSize == 32) {
							return sequenceNumber % tSize;
						} else {
							if (__builtin_expect(sequenceNumber < tSize, 1)) {
								return sequenceNumber;
							} else {
								return sequenceNumber % tSize;
							}
						}
					}
      
				CELL_DAISY_INLINE
					BitmapType getMask(uint32_t sequenceNumber)
					{
						return 1 << getPointerFromSequenceNumber(sequenceNumber);
					}
      
				CELL_DAISY_INLINE
					BitmapType getMask(uint64_t sequenceNumber)
					{
						return 1 << getPointerFromSequenceNumber(sequenceNumber);
					}
      
				virtual const char *getClassName()
					{
						static char __buf[64];
						cell::Daisy::_snprintf(__buf, 64, "Abstract(%s)[tSize:%d]",
											   tQueueIO == INPUT ? "In" : "Out",
											   tSize);
						return (const char *)__buf;
					}
      
				virtual void dump(const char*) = 0;

				/* get mPointer
				 * @retval mPointer
				 */
				CELL_DAISY_INLINE
				PointerType getPointer(){return (PointerType)__CELL_DAISY_SPU_GET_VAL__(mPointer) ;}

				/* set mPointer
				 * @param pointer
				 */
				CELL_DAISY_INLINE
				void setPointer(PointerType pointer){
					__CELL_DAISY_SPU_SET_VAL__(mPointer, pointer);
				}

				/* get available entry num for getNextTailPointer()
				 * @retval available entry num for getNextTailPointer()
				 */
				CELL_DAISY_INLINE
				uint32_t getCompleteNumber(){return 0;}
      
				/* Consumer packet#=sequenceNumber completed
				 * @param sequenceNumber
				 *    packet# that is completed by Consumer
				 */
				CELL_DAISY_INLINE
				void beginCompleteConsume(uint32_t sequenceNumber){ (void)sequenceNumber; }
      
				/* Consumer packet#=sequenceNumber completed
				 * @param sequenceNumber
				 *    packet# that is completed by Consumer
				 */
				CELL_DAISY_INLINE
				void endCompleteConsume(uint32_t sequenceNumber){ (void)sequenceNumber; }
      
				/* Producer packet#=sequenceNumber completed
				 * @param sequenceNumber
				 *    packet# that is produced by Producer
				 */
				CELL_DAISY_INLINE
				void beginCompleteProduce(uint32_t sequenceNumber){ (void)sequenceNumber; }
      
				/* Producer packet#=sequenceNumber completed
				 * @param sequenceNumber
				 *    packet# that is produced by Producer
				 */
				CELL_DAISY_INLINE
				void endCompleteProduce(uint32_t sequenceNumber){ (void)sequenceNumber; }
      
				/* Get Next Tail pointer
				 * @retval Next tail Abstract pointer if available,
				 *         otherwise PTR_UNAVAILABLE or PTR_TERMINATED
				 * @param stall
				 *    STALL      : stall until pointer becomes available
				 *    NOT_STALL  : not stall until pointer becomes available
				 */
				CELL_DAISY_INLINE
				PointerType getNextTailPointer(BlockMode stall){(void)stall; return 0 ;}

#ifdef __SPU__      
				/* Set Next Tail pointer
				 * @retval CELL_OK or QUEUE_IS_BUSY
				 * @param stall
				 *    STALL      : stall until pointer becomes available
				 *    NOT_STALL  : not stall until pointer becomes available
				 * @param pointer poinnter to be set to tail pointer
				 */
				CELL_DAISY_INLINE
				int setNextTailPointer(BlockMode stall, PointerType pointer){
					(void)stall;
					(void)pointer;
					return CELL_OK ;
				}
#endif /* __SPU__ */
      
				/* Get Next Head pointer
				 * @retval Next head Abstract pointer if available, otherwise PTR_UNAVAILABLE
				 * @param stall
				 *    STALL      : stall until pointer becomes available
				 *    NOT_STALL  : not stall until pointer becomes available
				 */
				CELL_DAISY_INLINE
				PointerType getNextHeadPointer(BlockMode stall){(void)stall; return 0;}
      
				/* Terminate produce */
				CELL_DAISY_INLINE
				void terminate(){}

				/* Check if there are any unfinished consumers
				 * @param isCancelled true if last operation was cancel
				 * @retval true: unfinished consumers exist
				 */
				CELL_DAISY_INLINE
				bool hasUnfinishedConsumer(bool isCancelled){(void)isCancelled; return false;}

			};

			/* constructor description */
			template<SizeType tSize, QueueIO tQueueIO>
			Abstract<tSize, tQueueIO>::Abstract():
#ifdef __SPU__
				mPointer   (si_from_int(PTR_UNAVAILABLE))
#else
				mPointer   (PTR_UNAVAILABLE)
#endif
			{};

		} /* namespace QueueControl */
	} /* namespace Daisy */
} /* namespcae cell */

#endif /* __CELL_DAISY_QCTL_H__ */

/*
 * Local Variables:
 * mode:C++
 * tab-width:4
 * End:
 * vim:ts=4:sw=4:
 */
