Code Search for Developers
 
 
  

WaitRedShedThread.c from redshed at Krugle


Show WaitRedShedThread.c syntax highlighted

/****************************************************************************************
	WaitRedShedThread.c $Revision: 1.2 $
		<http://rentzsch.com/redshedthreads>
	
	Copyright © 2000-2002 Red Shed Software. All rights reserved.
	by Jonathan 'Wolf' Rentzsch (jon at redshed dot net)
	
	************************************************************************************/

#include	"WaitRedShedThread.h"
#include	"EventTasks.h"
#include	"Align.h"
#include	"require.h"
#include	"CFMA5.h"
//#include	"doubt.h"
#include	"Multiprocessing.h"

//#define		kEventTaskMessage			(AtomicMessage)100
//#define		kDeferredTaskMessage		(AtomicMessage)101
#define		kTimeTaskMessage			(AtomicMessage)102
//#define		kTimeDeferredTaskMessage	kDeferredTaskMessage

/**************************
*	
*	Types
*	
**************************/
#pragma mark	(Types)

typedef	struct	{
	EventTask		et;
	RedShedThread	*thread;
}	WEventTask;

typedef	struct	{
	DeferredTask	dt;
	RedShedThread	*thread;
	long			a5;
}	WDeferredTask;

typedef	struct	{
	TMTask			tm;
	RedShedThread	*thread;
	long			a5;
	Boolean			sendMessage;
}	WTMTask;

/**************************
*	
*	Funky Protos
*	
**************************/
#pragma mark	-
#pragma mark	(Funky Protos)

	void
WaitEventTaskProc(
	WEventTask	*task );

	pascal
	void
WaitDeferredTaskProc(
	WDeferredTask	*task );

#if	TARGET_API_MAC_CARBON
	DeferredTaskUPP	gWaitDeferredTaskProc = NewDeferredTaskUPP( (DeferredTaskProcPtr) WaitDeferredTaskProc );
#else
	#if	TARGET_RT_MAC_CFM
		RoutineDescriptor	rdWaitDeferredTaskProc = BUILD_ROUTINE_DESCRIPTOR( uppDeferredTaskProcInfo, WaitDeferredTaskProc );
		DeferredTaskUPP		gWaitDeferredTaskProc = &rdWaitDeferredTaskProc;
	#else
		void	WaitDeferredTaskProcGlue();
		DeferredTaskUPP		gWaitDeferredTaskProc = (DeferredTaskUPP) &WaitDeferredTaskProcGlue;
	#endif
#endif

	pascal
	void
WaitTimeTaskProc(
	WTMTask	*task );

#if	TARGET_API_MAC_CARBON
	TimerUPP	gWaitTimeTaskProc = NewTimerUPP( (TimerProcPtr) WaitTimeTaskProc );
#else
	#if	TARGET_RT_MAC_CFM
		RoutineDescriptor	rdWaitTimeTaskProc = BUILD_ROUTINE_DESCRIPTOR( uppTimerProcInfo, WaitTimeTaskProc );
		TimerUPP			gWaitTimeTaskProc = &rdWaitTimeTaskProc;
	#else
		void	WaitTimeTaskProcGlue();
		TimerUPP		gWaitTimeTaskProc = (TimerUPP) &WaitTimeTaskProc;
	#endif
#endif

	AtomicMessageElement*
WaitOTEventProc(
	AtomicMessageElement	*message,
	AtomicMessageQueue		*queue );

	OSStatus
WaitMPTaskProc(
	void	*parameter );

/****************************************************************************************
*	
*	Public
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Public)

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Feb 2, 2000	Created.
	wolf		Tue, May 1, 2001	Now returns the Boolean from ScheduleEventTask().
	
	************************************************************************************/

	Boolean
WaitEventTask(
	RedShedThread	*thread,
	UInt32			sleep )
{
	Boolean	result;
	DeclareAlignedVariable( WEventTask, task, kAtomicAlignment );
	
	RequireRedShedThread( thread );
	
	InitializeEventTask( (EventTask*) task );
	task->et.proc = (EventTaskProc) WaitEventTaskProc;
	task->thread = thread;
	result = ScheduleEventTask( (EventTask*) task, sleep );
	YieldRedShedThread( thread );
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	wolf		Sun, Apr 9, 2000	Updated for Red Shed Threads Version 6.
	
	************************************************************************************/

	void
WaitDeferredTask(
	RedShedThread	*thread )
{
	WDeferredTask	task;
	OSErr			err;
	
	RequireRedShedThread( thread );
	
	task.dt.qLink = nil;
	task.dt.qType = dtQType;
	task.dt.dtFlags = 0;
	task.dt.dtAddr = gWaitDeferredTaskProc;
	task.dt.dtParam = (long) &task;
	task.dt.dtReserved = 0;
	task.thread = thread;
	task.a5 = GetA5();
	
	ReadyRedShedThread( thread );
	err = DTInstall( (DeferredTaskPtr) &task );
	RequireNoErr( err );
	BlockRedShedThread( thread );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	wolf		Sun, Apr 9, 2000	Updated for Red Shed Threads Version 6.
	
	************************************************************************************/

	void
WaitTimeTask(
	RedShedThread	*thread,
	SInt32			sleep )
{
	WTMTask	task;
	
	RequireRedShedThread( thread );
	
	task.tm.qLink = nil;
	task.tm.qType = 0;
	task.tm.tmAddr = gWaitTimeTaskProc;
	task.tm.tmCount = 0;
	task.tm.tmWakeUp = 0;
	task.tm.tmReserved = 0;
	task.thread = thread;
	task.a5 = GetA5();
	task.sendMessage = false;
	
	ReadyRedShedThread( thread );
	InsTime( (QElemPtr) &task );
	PrimeTime( (QElemPtr) &task, sleep );
	BlockRedShedThread( thread );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	
	************************************************************************************/

	void
WaitTimeDeferredTask(
	RedShedThread	*thread,
	SInt32			sleep )
{
	RequireRedShedThread( thread );
	
	WaitTimeTask( thread, sleep );
	WaitDeferredTask( thread );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Jan 20, 2000	Created.
	
	************************************************************************************/

	OSStatus
WaitOTEvent(
	RedShedThread	*thread,
	OTEventCode		*event,
	long			*cookie,
	SInt32			patience )
{
	WTMTask	task = { nil, 0, nil, 0, 0, 0, nil, 0, true };
	OTEventCode		gotEvent;
	AtomicMessage	message;
	OSStatus		result = kOTNoError;
	
	task.tm.tmAddr = gWaitTimeTaskProc;
	task.thread = thread;
	task.a5 = GetA5();
	
	RequireRedShedThread( thread );
	RequirePtr( event );
	RequirePtrIfNotNil( cookie );
	
	//gDoubt << "thread " << thread << " is waiting for " << (void*) *event << doubt::end;
	
	//	Peek into the queue and see if there is already an OT event message there.
	message = PeekRedShedThreadMessage( thread, nil, kOTEventMessage, (long*) &gotEvent,
										nil, nil );
	
	if( message == kNoAtomicMessage ) {
		//	No message pending.
		if( patience ) {
			//	The user is impatient, start the timer.
			InsTime( (QElemPtr) &task );
			PrimeTime( (QElemPtr) &task, patience );
		}
		//	Wait for either an OT event message or our timer message.
		message = WaitPeekRedShedThreadMessage( thread, WaitOTEventProc,
												kNoAtomicMessage, (long*) &gotEvent, nil, nil );
		//Æ	The following line should only be uncommented for debugging.
		//WaitEventTask( thread, kPriority );
		
		if( (task.tm.qType & kTMTaskActive) == kTMTaskActive ) {
			//	The Time Task is still outstanding, clear it.
			RmvTime( (QElemPtr) &task );
		}
	}
	
	switch( message ) {
		case kOTEventMessage:
			//	We got an OT event message.
			if( *event == 0 || *event == gotEvent ) {
				//	Either the client isn't picky and will accept any OT event (*event == 0)
				//	or it's just the event the client is looking for (*event == gotEvent).
				//	Either way, receive the event message.
				//gDoubt << "thread " << thread << " got " << (void*) *event << doubt::end;
				ReceiveRedShedThreadMessage( thread, nil, kNoAtomicMessage, (long*) event,
												&result, cookie );
			} else {
				//	It's not an event the client is willing to receive.
				result = kOTLookErr;
			}
			break;
		case kTimeTaskMessage:
			//	It's our time-out message, receive it.
			//gDoubt << "thread " << thread << " gave up waiting for " << (void*) *event << doubt::end;
			ReceiveRedShedThreadMessage( thread, nil, kNoAtomicMessage, nil, nil, nil );
			result = kWaitOTMessageTimedOut;
			break;
		default:
			RequireSwitch( message );
	}
	
	//	It is possible that there still may be a kTimeTaskMessage in the queue.
	//	This can happen if the timer fired after the OT event, but before we removed the
	//	timer. Receive the message if it exists.
	if( PeekRedShedThreadMessage( thread, nil, kTimeTaskMessage, nil, nil, nil ) == kTimeTaskMessage ) {
		ReceiveRedShedThreadMessage( thread, nil, kTimeTaskMessage, nil, nil, nil );
	}
	
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Jan 11, 2000	Created.
	wolf		Sat, Jul 1, 2000	Added explicit cast of code to long.
	
	************************************************************************************/

	pascal
	void
NotifyRedShedThread(
	void		*contextPtr,
	OTEventCode	code,
	OTResult	result,
	void		*cookie )
{
	RedShedThread	*thread = (RedShedThread*) contextPtr;
	OSErr			err;
	
	RequireRedShedThread( thread );
	
	/*gDoubt	<< "OT event " << (void*) code << " was sent to thread " << thread
			<< " with the result of " << result << doubt::end;*/
		
	err = NewRedShedThreadMessage( thread, kOTEventMessage, (long) code, result, (long) cookie );
	/*if( err ) {
		gDoubt << "OT event " << (void*) code << " sent to thread " << (long) thread
				<< " was dropped because NewRedShedThreadMessage() failed." << doubt::stop;
	}*/
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Sep 2, 2000	Created.
	
	************************************************************************************/

	OSStatus
WaitMPTask(
	RedShedThread	*thread )
{
	MPTaskID	task;
	OSStatus	err;
	
	RequireRedShedThread( thread );
	
	ReadyRedShedThread( thread );
	err = MPCreateTask( WaitMPTaskProc, thread, 0, 0, nil, nil, 0, &task );
	if( !err ) {
		BlockRedShedThread( thread );
	}
	
	return( err );
}

/****************************************************************************************
*	
*	Private
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Private)

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 4, 2000	Created.
	
	************************************************************************************/

	void
WaitEventTaskProc(
	WEventTask	*task )
{
	RequirePtrAlign( task, kAtomicAlignment );
	RequireRedShedThread( task->thread );
	
	PulseRedShedThread( task->thread );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	
	************************************************************************************/

	pascal
	void
WaitDeferredTaskProc(
	WDeferredTask	*task )
{
	long	oldA5;
	
	RequirePtr( task );
	oldA5 = SwapA5( task->a5 );
	
	RequireRedShedThread( task->thread );
	PulseRedShedThread( task->thread );
	
	RestoreA5( oldA5 );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	
	************************************************************************************/

#if	!TARGET_API_MAC_CARBON && !TARGET_RT_MAC_CFM
	asm
	void
WaitDeferredTaskProcGlue()
{
	movem.l	a4-a6/d4-d7, -(a7)		//	Save registers.
	move.l	a1, -(a7)				//	Push task.
	jsr		WaitDeferredTaskProc	//	Call the real guy.
	movem.l	(a7)+, a4-a6/d4-d7		//	Restore registers.
	rts								//	We're outta here.
}
#endif

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	
	************************************************************************************/

	pascal
	void
WaitTimeTaskProc(
	WTMTask	*task )
{
	long	oldA5;
	
	RequirePtr( task );
	oldA5 = SwapA5( task->a5 );
	RequireRedShedThread( task->thread );
	
	if( task->sendMessage ) {
		OSErr	err = NewRedShedThreadMessage( task->thread, kTimeTaskMessage, 0, 0, 0 );
		Require( !err );
	} else {
		PulseRedShedThread( task->thread );
	}
	
	RestoreA5( oldA5 );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Feb 19, 2000	Created.
	
	************************************************************************************/

#if	!TARGET_API_MAC_CARBON && !TARGET_RT_MAC_CFM
	asm
	void
WaitTimeTaskProcGlue()
{
	movem.l	d4-d7/a4-a6, -(sp)	//	Save registers.
	move.l	a1, -(sp)			//	Push task.
	jsr		WaitTimeTaskProc	//	Call the real guy.
	movem.l	(sp)+, d4-d7/a4-a6	//	Restore registers.
	rts							//	We're outta here.
}
#endif

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, May 18, 2000	Created.
	
	************************************************************************************/

	AtomicMessageElement*
WaitOTEventProc(
	AtomicMessageElement	*message,
	AtomicMessageQueue		*/*queue*/ )
{
	if( message->message == kOTEventMessage || message->message == kTimeTaskMessage ) {
		return( kFilterFoundAtomicMessage );
	} else {
		return( kFilterNextAtomicMessage );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Sep 2, 2000	Created.
	
	************************************************************************************/

	OSStatus
WaitMPTaskProc(
	void	*parameter )
{
	RedShedThread	*thread = (RedShedThread*) parameter;
	
	RequireRedShedThread( thread );
	
	PulseRedShedThread( thread );
	
	return( noErr );
}



See more files for this project here

redshed

Code for Mac+WebObjects.

Project homepage: http://sourceforge.net/projects/redshed
Programming language(s): C,Java,Objective C
License: other

  CFMA5.h
  ThreadedFile.c
  ThreadedFile.h
  ThreadedOT.c
  ThreadedOT.h
  WaitRedShedThread.c
  WaitRedShedThread.h