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

/* sync_pipe.h
 */

#ifndef __CELL_DAISY_SYNC_PIPE_H__
#define __CELL_DAISY_SYNC_PIPE_H__

#include <cell/daisy/pipe.h>
#include <cell/daisy/sync_pipe_interlock.h>
#include <cell/daisy/seq_data.h>

#undef CELL_DAISY_DEBUG_PRINTF
#define CELL_DAISY_DEBUG_PRINTF(...)
#ifdef CELL_DAISY_DEBUG_SYNC_PIPE
#include <cell/daisy/daisy_debug.h>
#endif

#undef CELL_DAISY_BOOKMARK
#define CELL_DAISY_BOOKMARK(x)
#ifdef CELL_DAISY_BOOKMARK_PIPE
#define __CELL_DAISY_BOOKMARK_PREFIX__ CELL_DAISY_BOOKMARK_PREFIX_PIPE
#include <cell/daisy/daisy_bookmark.h>
#endif

namespace cell {
	namespace Daisy {
		namespace ScatterPipe {

			template<class tBuffer, class tQueueControl, BufferMode tMode = COPY>
			class InPort:
				public Pipe::InPort<tBuffer, tQueueControl, tMode>,
				public ScatterGatherInterlock
			{
		
			public:
      
				typedef typename tBuffer::DataType Type;

				typedef typename tBuffer::DataType GlueDataType;

				const char  *getClassName(){
					static char __buf[64];
					cell::Daisy::_snprintf(__buf, 64,
										   "ScatterPipe::InPort(%s,%s)",
										   this->mBuffer.getClassName(),
										   this->mQueueControl.getClassName()
						);
					return (const char*)__buf;
				}
#ifdef __SPU__
				explicit InPort(tBuffer& buffer, tQueueControl& queueControl, uint64_t shmEa,
								uint64_t eaSignal = 0,
								uint32_t (*fpGetId)(void) = 0,
								int (*fpWaitSignal)(void) = 0,
								int bookmarkId = 0):
					Pipe::InPort<tBuffer, tQueueControl, tMode> (buffer, queueControl, bookmarkId),
					ScatterGatherInterlock                      (shmEa, tQueueControl::sSize,
																 eaSignal, fpGetId, fpWaitSignal)
					{}
#else
				explicit InPort(tBuffer& buffer, tQueueControl& queueControl, AtomicInterlock *shmEa,
								sys_spu_thread_t *ids = 0,
								unsigned int numSpus = 0,
								uint8_t spup = 0,
								int bookmarkId = 0):
					Pipe::InPort<tBuffer, tQueueControl, tMode> (buffer, queueControl, bookmarkId),
					ScatterGatherInterlock                      (shmEa, tQueueControl::sSize,
																 ids, numSpus, spup)
					{}
#endif

				void beginPush(__restrict__ Type *data);

				void beginPush();
      
				int tryBeginPush(__restrict__ Type *data);

				int tryBeginPush();
      
			}; /* class InPort */
    
			/* beginPush (tMode == COPY)
			 * 1.get tail_ptr
			 * 2.initiate transfer
			 * 3.beginCompleteProduce() (tMode == COPY)
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				void InPort<tBuffer,tQueueControl,tMode>::beginPush(__restrict__ Type *data)
			{

				CELL_DAISY_ASSERT_COPY;
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled), 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return;
				}

				register PointerType ptr= this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					ptr = this->mQueueControl.getNextTailPointer(STALL);
				}

				(void)probe(1);
                
				this->mBuffer.beginWrite(ptr, data);
				CELL_DAISY_DEBUG_PRINTF(
					"%s(beginPush): mBuffer.beginWrite(%d, 0x%p)\n",
					getClassName(),ptr, data
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.beginCompleteProduce(ptr); /* tMode == COPY */

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */
				
				proceedSequenceNumber(); /* proceed mSequenceNumber for next time */

				CELL_DAISY_BOOKMARK(0);
			}
    
			/* beginPush (tMode == REFERENCE)
			 * 1.get tail_ptr
			 * 2.initiate transfer
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				void InPort<tBuffer,tQueueControl,tMode>::beginPush()
			{

				CELL_DAISY_ASSERT_REFERENCE;
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return;
				}

				register PointerType ptr= this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					ptr = this->mQueueControl.getNextTailPointer(STALL);
				}

				(void)probe(1);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */

				proceedSequenceNumber(); /* proceed mSequenceNumber for next time */

				CELL_DAISY_BOOKMARK(1);
			}

			/* tryBeginPush (tMode == COPY)
			 * 1.get tail_ptr if possible,otherwise abort
			 * 2.initiate transfer
			 * 3.beginCompleteProduce() (tMode == COPY)
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				int InPort<tBuffer, tQueueControl, tMode>::tryBeginPush(__restrict__ Type *data)
			{
				register int stat;

				CELL_DAISY_ASSERT_COPY;
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return CELL_OK;
				}

				register PointerType ptr = this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					if (__builtin_expect((ptr = this->mQueueControl.getNextTailPointer(NOT_STALL)) < 0, 0)) {
						return QUEUE_IS_BUSY;
					}
					this->mQueueControl.setPointer(ptr);
				}

				if (__builtin_expect(probe(0) != CELL_OK, 0)) {
					return QUEUE_IS_BUSY;
				}

				if (__builtin_expect((stat = this->mBuffer.tryBeginWrite(ptr, data)) != CELL_OK, 0)) {
					return stat; /* write cannot start */
				}

				CELL_DAISY_DEBUG_PRINTF(
					"%s(tryBeginPush): mBuffer.tryBeginWrite(%d, 0x%p)\n",
					getClassName(),ptr,data
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}
				
				this->mQueueControl.beginCompleteProduce(ptr); /* tMode == COPY */

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */

				proceedSequenceNumber(); /* proceed mSequenceNumber for next time */

				CELL_DAISY_BOOKMARK(2);
				return CELL_OK;
			}

			/* tryBeginPush (tMode == REFERENCE)
			 * 1.get tail_ptr if possible,otherwise abort
			 * 2.initiate transfer
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				int InPort<tBuffer, tQueueControl, tMode>::tryBeginPush()
			{
				CELL_DAISY_ASSERT_REFERENCE;
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return CELL_OK;
				}

				register PointerType ptr= this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					if (__builtin_expect((ptr = this->mQueueControl.getNextTailPointer(NOT_STALL)) < 0, 0)) {
						return QUEUE_IS_BUSY;
					}
					this->mQueueControl.setPointer(ptr);
				}
				if (__builtin_expect(probe(0) != CELL_OK, 0)) {
					return QUEUE_IS_BUSY;
				}

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */

				proceedSequenceNumber(); /* proceed mSequenceNumber for next time */

				CELL_DAISY_BOOKMARK(3);
				return CELL_OK;
			}
#ifdef __SPU__    
			template<class tBuffer, class tQueueControl>
			class OutPort:
				public Pipe::OutPort<tBuffer, tQueueControl, COPY>
			{

			public:

				typedef typename tBuffer::DataType Type;

				typedef TaggedData<typename tBuffer::DataType> GlueDataType;

				const char  *getClassName(){
					static char __buf[64];
					cell::Daisy::_snprintf(__buf, 64,
										   "ScatterPipe::OutPort(%s,%s)",
										   this->mBuffer.getClassName(),
										   this->mQueueControl.getClassName()
						);
					return (const char*)__buf;
				}
				explicit OutPort(tBuffer& buffer, tQueueControl& queueControl, int bookmarkId=0):
					Pipe::OutPort<tBuffer, tQueueControl, COPY> (buffer, queueControl, bookmarkId)
					{}
				
				using Pipe::OutPort<tBuffer, tQueueControl, COPY>::beginPop;
				using Pipe::OutPort<tBuffer, tQueueControl, COPY>::tryBeginPop;
				using Pipe::OutPort<tBuffer, tQueueControl, COPY>::getCurrentReference;

				int beginPop(TaggedData<Type> *taggedData);

				int tryBeginPop(TaggedData<Type> *taggedData);

				volatile TaggedData<Type> *getCurrentReference(){return (volatile TaggedData<Type> *)NULL;}

			}; /* class OutPort */

			/* beginPop
			 * 1.get head_ptr
			 * 2.initiate transfer
			 * 3.beginCompleteConsume
			 */
			template<class tBuffer, class tQueueControl>
			CELL_DAISY_INLINE
				int OutPort<tBuffer, tQueueControl>::beginPop(TaggedData<Type> *taggedData)
			{
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return CELL_OK;
				}

				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mIsTerminated) != 0u, 0)) {
					return TERMINATED;
				}

				register PointerType ptr = this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					ptr = this->mQueueControl.getNextHeadPointer(STALL);
					if (__builtin_expect(ptr == PTR_TERMINATED, 0)) {
						__CELL_DAISY_SPU_SET_VAL__(this->mIsTerminated, true);
						return TERMINATED;
					}
				}

				taggedData->mTag = ptr; /* set sequence number */
				this->mBuffer.beginRead(ptr, (Type *)(uintptr_t)&(taggedData->mContent));
				CELL_DAISY_DEBUG_PRINTF(
					"%s(beginScatterPop): mBuffer.beginRead(%d, 0x%p)\n",
					getClassName(),ptr,&(taggedData->mContent)
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.beginCompleteConsume(ptr); /* tMode == COPY */

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */

				CELL_DAISY_BOOKMARK(6);
				return CELL_OK;
			}

			/* tryBeginPop
			 * 1.get head_ptr if possible,otherwise abort
			 * 2.initiate transfer
			 * 3.beginCompleteConsume
			 * @retval CELL_OK, QUEUE_IS_BUSY
			 */
			template<class tBuffer, class tQueueControl>
			CELL_DAISY_INLINE
				int OutPort<tBuffer, tQueueControl>::tryBeginPop(TaggedData<Type> *taggedData)
			{
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return CELL_OK;
				}

				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mIsTerminated) != 0u, 0)) {
					return TERMINATED;
				}

				register PointerType ptr = this->mQueueControl.getPointer();
				if (__builtin_expect(ptr == PTR_UNAVAILABLE, 1)) {
					ptr = this->mQueueControl.getNextHeadPointer(NOT_STALL);
					if (__builtin_expect(ptr == PTR_UNAVAILABLE, 0)) {
						return QUEUE_IS_BUSY;
					} else if (__builtin_expect(ptr == PTR_TERMINATED, 0)) {
						__CELL_DAISY_SPU_SET_VAL__(this->mIsTerminated, true);
						return TERMINATED;
					}
				}

				taggedData->mTag = ptr; /* set sequence number */
				register int stat =
					this->mBuffer.tryBeginRead(ptr, (Type*)(uintptr_t)&(taggedData->mContent));
				if (__builtin_expect(stat != CELL_OK, 0)) {
					return stat; /* read cannot be started */
				}
				CELL_DAISY_DEBUG_PRINTF(
					"%s(tryBeginScatterPop): mBuffer.tryBeginRead(%d, 0x%p)\n",
					getClassName(),ptr, &(taggedData->mContent)
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.beginCompleteConsume(ptr); /* tMode == COPY */

				this->mQueueControl.setPointer(PTR_UNAVAILABLE); /* reset pointer */
      
				CELL_DAISY_BOOKMARK(8);
				return CELL_OK;
			}
#endif /* __SPU__ */

		} /* namespace ScatterPipe */

		namespace GatherPipe {

#ifdef __SPU__
			template<class tBuffer, class tQueueControl>
			class InPort:
				public Pipe::InPort<tBuffer, tQueueControl, COPY>
			{
		
			public:
      
				typedef typename tBuffer::DataType Type;

				typedef TaggedData<typename tBuffer::DataType> GlueDataType;

				const char  *getClassName(){
					static char __buf[64];
					cell::Daisy::_snprintf(__buf, 64,
										   "GatherPipe::InPort(%s,%s)",
										   this->mBuffer.getClassName(),
										   this->mQueueControl.getClassName()
						);
					return (const char*)__buf;
				}

				explicit InPort(tBuffer& buffer, tQueueControl& queueControl, int bookmarkId=0):
					Pipe::InPort<tBuffer, tQueueControl, COPY> (buffer, queueControl, bookmarkId)
					{}

				using Pipe::InPort<tBuffer, tQueueControl, COPY>::beginPush;
				using Pipe::InPort<tBuffer, tQueueControl, COPY>::tryBeginPush;

				void beginPush(TaggedData<Type> *taggedData);

				int tryBeginPush(TaggedData<Type> *taggedData);

			}; /* class InPort */
    
			/* beginPush
			 * 1.get tail_ptr
			 * 2.initiate transfer
			 * 3.beginCompleteProduce()
			 */
			template<class tBuffer, class tQueueControl>
			CELL_DAISY_INLINE
				void InPort<tBuffer,tQueueControl>::beginPush(TaggedData<Type> *taggedData)
			{
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled) != 0u, 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return;
				}
				
				this->mQueueControl.is1stVisitor(); /* dummy call to set startFlag */
				register PointerType ptr = taggedData->mTag;
				(void)this->mQueueControl.setNextTailPointer(STALL, ptr);

				this->mBuffer.beginWrite(ptr, (Type *)(uintptr_t)&(taggedData->mContent));
				CELL_DAISY_DEBUG_PRINTF(
					"%s(beginGatherPush): mBuffer.beginWrite(%d, 0x%p)\n",
					getClassName(),ptr, &(taggedData->mContent)
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}

				this->mQueueControl.beginCompleteProduce(ptr); /* tMode == COPY */
				CELL_DAISY_BOOKMARK(0);
			}
    
			/* tryBeginPush
			 * 1.get tail_ptr if possible,otherwise abort
			 * 2.initiate transfer
			 * 3.beginCompleteProduce()
			 */
			template<class tBuffer, class tQueueControl>
			CELL_DAISY_INLINE
				int InPort<tBuffer, tQueueControl>::tryBeginPush(TaggedData<Type> *taggedData)
			{
				register int stat;
				if (__builtin_expect(__CELL_DAISY_SPU_GET_VAL__(this->mCancelled), 0)) {
					__CELL_DAISY_SPU_SET_VAL__(this->mCancelled, false);
					return CELL_OK;
				}

				this->mQueueControl.is1stVisitor(); /* dummy call to set startFlag */
				register PointerType ptr = taggedData->mTag;
				if (__builtin_expect(this->mQueueControl.setNextTailPointer(NOT_STALL, ptr), 0)) {
					return QUEUE_IS_BUSY;
				}

				if (__builtin_expect((stat =
									  this->mBuffer.tryBeginWrite(ptr, (Type*)(uintptr_t)&(taggedData->mContent)))
									 != CELL_OK, 0)) {
					return stat; /* write cannot start */
				}

				CELL_DAISY_DEBUG_PRINTF(
					"%s(tryBeginGatherPush): mBuffer.tryBeginWrite(%d, 0x%p)\n",
					getClassName(),ptr,&(taggedData->mContent)
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.pushPtr(ptr);
				} else {
					this->mLastPointer = ptr;
					this->mPendingCount++;
				}
				
				this->mQueueControl.beginCompleteProduce(ptr); /* tMode == COPY */

				CELL_DAISY_BOOKMARK(2);
				return CELL_OK;

			}
#endif /* __SPU__ */

			template<class tBuffer, class tQueueControl, BufferMode tMode = COPY>
			class OutPort:
				public Pipe::OutPort<tBuffer, tQueueControl, tMode>,
				public ScatterGatherInterlock
			{

			public:
      
				typedef typename tBuffer::DataType Type;

				typedef typename tBuffer::DataType GlueDataType;

				const char  *getClassName(){
					static char __buf[64];
					cell::Daisy::_snprintf(__buf, 64,
										   "GatherPipe::OutPort(%s,%s)",
										   this->mBuffer.getClassName(),
										   this->mQueueControl.getClassName()
						);
					return (const char*)__buf;
				}
#ifdef __SPU__
				explicit OutPort(tBuffer& buffer, tQueueControl& queueControl, uint64_t shmEa,
								 uint64_t eaSignal = 0,
								 int (*fpSendSignal)(uint64_t, uint32_t) = 0,
								 int bookmarkId = 0):
					Pipe::OutPort<tBuffer, tQueueControl, tMode> (buffer, queueControl, bookmarkId),
					ScatterGatherInterlock                       (shmEa, tQueueControl::sSize,
																  eaSignal, fpSendSignal)
					{}
#else
				explicit OutPort(tBuffer& buffer, tQueueControl& queueControl, AtomicInterlock *shmEa,
								 void *eaSignal = 0,
								 int (*fpSendSignal)(void *, uint32_t) = 0,
								 int bookmarkId = 0):
					Pipe::OutPort<tBuffer, tQueueControl, tMode> (buffer, queueControl, bookmarkId),
					ScatterGatherInterlock                       (shmEa, tQueueControl::sSize,
																  eaSignal, fpSendSignal)
					{}
#endif

				int endPop();
      
				int tryEndPop();

			}; /* class OutPort */

			/* endPop
			 * 1.transfer end
			 * 2.beginCompleteConsume (if tMode==REFERENCE)
			 * 3.endCompleteConsume()
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				int OutPort<tBuffer, tQueueControl, tMode>::endPop()
			{
				if (__builtin_expect(!this->hasPendingEntry(),0)) {
					CELL_ERROR_CHECK_ERROR(CELL_DAISY_ERROR_NO_BEGIN);
					return CELL_DAISY_ERROR_NO_BEGIN; /* unexpected endPop() */
				}

				register PointerType ptr;
				if (this->mQueueControl.isOutOfOrder()) {
					ptr = this->mPendingFifo.getFront();
				} else {
					ptr = this->mQueueControl.getPointerFromSequenceNumber(this->mLastPointer - (this->mPendingCount - 1));
				}

				this->mBuffer.endRead(ptr);
				CELL_DAISY_DEBUG_PRINTF(
					"%s(endPop): mBuffer.endRead(%d)\n",
					getClassName(),ptr
					);
      
				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.popPtr();
				} else {
					this->mPendingCount--;
				}

				if (tMode == REFERENCE) {
					this->mQueueControl.beginCompleteConsume(ptr);
				}
				this->mQueueControl.endCompleteConsume(ptr);

				release(); /* update compeleNumber */
				CELL_DAISY_BOOKMARK(10);

				return CELL_OK;
			}
    
			/* tryEndPop
			 * 1.transfer end if possible, otherwise abort
			 * 2.beginCompleteConsume (if tMode==REFERENCE)
			 * 3.endCompleteConsume()
			 * @retval CELL_OK, QUEUE_IS_BUSY or CELL_DAISY_ERROR_NO_BEGIN
			 */
			template<class tBuffer, class tQueueControl, BufferMode tMode>
			CELL_DAISY_INLINE
				int OutPort<tBuffer, tQueueControl, tMode>::tryEndPop()
			{

				if (__builtin_expect(!this->hasPendingEntry(),0)) {
					CELL_ERROR_CHECK_ERROR(CELL_DAISY_ERROR_NO_BEGIN);
					return CELL_DAISY_ERROR_NO_BEGIN; /* unexpected tryEndPop() */
				}

				register PointerType ptr;
				if (this->mQueueControl.isOutOfOrder()) {
					ptr = this->mPendingFifo.getFront();
				} else {
					ptr = this->mQueueControl.getPointerFromSequenceNumber(this->mLastPointer - (this->mPendingCount - 1));
				}

				register int stat = this->mBuffer.tryEndRead(ptr);
				if (__builtin_expect(stat != CELL_OK, 0)) {
					return stat; /* read not completed */
				}
				CELL_DAISY_DEBUG_PRINTF(
					"%s(tryEndPop): mBuffer.tryEndRead(%d)\n",
					getClassName(),ptr
					);

				if (this->mQueueControl.isOutOfOrder()) {
					this->mPendingFifo.popPtr();
				} else {
					this->mPendingCount--;
				}

				if (tMode == REFERENCE) {
					this->mQueueControl.beginCompleteConsume(ptr);
				}
				this->mQueueControl.endCompleteConsume(ptr);
                
				release(); /* update completeNumber */
			
				CELL_DAISY_BOOKMARK(11);
				return CELL_OK;
			}

		} /* namespace GatherPipe */
	} /* namespace Daisy */
} /* namespace cell */

#endif /* __CELL_DAISY_SYNC_PIPE_H__ */

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