Code Search for Developers
 
 
  

AtomicMessages.c from redshed at Krugle


Show AtomicMessages.c syntax highlighted

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

#include	"AtomicMessages.h"
#include	"Align.h"
#include	"require.h"

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

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

	void
InitializeAtomicMessageQueue(
	AtomicMessageQueue	*queue )
{
	RequirePtrAlign( queue, kAtomicAlignment );
	
	queue->queue.input.next = queue->queue.output.next = nil;
	queue->incoming = nil;
	queue->allocator = nil;
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Apr 20, 1999	Created.
	wolf		Tue, Apr 11, 2000	AtomicMessageQueue's incoming proc type changed.
									Updated.
	wolf		Sat, Jul 1, 2000	Added explicit cast and RequireBool.
	
	************************************************************************************/

	Boolean
SendAtomicMessage(
	AtomicMessageQueue		*queue,
	AtomicMessageElement	*message )
{
	long	result;
	
	RequirePtrAlign( queue, kAtomicAlignment );
	RequirePtrAlign( message, kAtomicAlignment );
	
	result = (Boolean) PushGuardedAtomicQueueType( message, &queue->queue, AtomicMessageElement, element );
	if( result && queue->incoming ) {
		RequireProcPtr( queue->incoming );
		queue->incoming( message, queue );
	}
	
	RequireBool( result );
	return( (Boolean) result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Apr 20, 1999	Created.
	wolf		Tue, Apr 11, 2000	AtomicMessageQueue's allocator proc type changed.
									Updated.
	
	************************************************************************************/

	OSErr
NewAtomicMessage(
	AtomicMessageQueue	*queue,
	AtomicMessage		message,
	long				data1,
	long				data2,
	long				data3 )
{
	AtomicMessageElement	*element = nil;
	Boolean					sent;
	OSErr					err = noErr;
	
	RequirePtrAlign( queue, kAtomicAlignment );
	
	if( queue->allocator ) {
		RequireProcPtr( queue->allocator );
		element = queue->allocator( nil, queue );
		if( element == nil )
			err = memFullErr;
	} else {
	
		err = NewAlignedPtr( sizeof( AtomicMessageElement ), false, true,
							kAtomicAlignment, (void**) &element );
		err = MemError();
		if( !element && !err )
			err = memFullErr;
		element->disposer = DisposeMessage;
	}
	
	if( !err ) {
		RequirePtrAlign( element, kAtomicAlignment );
		
		element->message = message;
		element->data1 = data1;
		element->data2 = data2;
		element->data3 = data3;
		sent = SendAtomicMessage( queue, element );
		Require( sent );
	}
	
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Apr 11, 2000	Created.
	
	************************************************************************************/

	AtomicMessage
PeekAtomicMessage(
	AtomicMessageQueue	*queue,
	AtomicMessageProc	filterProc,
	AtomicMessage		filterValue,
	long				*data1,
	long				*data2,
	long				*data3 )
{
	DeclareAlignedVariable( AtomicStack, filteredOut, kAtomicAlignment );
	AtomicMessageElement	*element, *element2, *result = nil;
	AtomicMessage			message = kNoAtomicMessage;
	long					put;
	
	RequirePtrAlign( queue, kAtomicAlignment );
	RequireProcPtrIfNotNil( filterProc );
	RequirePtrIfNotNil( data1 );
	RequirePtrIfNotNil( data2 );
	RequirePtrIfNotNil( data3 );
	
	filteredOut->next = nil;
	
	if( filterProc == nil && filterValue == kNoAtomicMessage ) {
		//	The user just wants to peek at the first message.
		result = PeekGuardedAtomicQueueType( &queue->queue, AtomicMessageElement, element );
	} else {
		//	Pop messages from queue and push them onto the filteredOut stack until we either
		//	find what we're looking for or hit the end of the queue.
		element = PopGuardedAtomicQueueType( &queue->queue, AtomicMessageElement, element );
		while( element && !result ) {
			RequirePtrAlign( element, kAtomicAlignment );
			
			//	Save the message onto the filteredOut stack for later restoring.
			put = PushGuardedAtomicStackType( element, filteredOut, AtomicMessageElement,
												element );
			Require( put );
			
			if( filterProc ) {
				//	Filter by callback.
				element2 = filterProc( element, queue );
				Require( element2 == kFilterFoundAtomicMessage
						|| element2 == kFilterNextAtomicMessage );
				
				if( element2 == kFilterFoundAtomicMessage )
					result = element;
			} else {
				//	Filter by value.
				if( element->message == filterValue ) {
					result = element;
				}
			}
			
			if( !result )
				element = PopGuardedAtomicQueueType( &queue->queue, AtomicMessageElement,
														element );
		}
	}
	
	//	If we found the message we're looking for, read its data.
	if( result ) {
		RequirePtrAlign( result, kAtomicAlignment );
		message = result->message;
		if( data1 )
			*data1 = result->data1;
		if( data2 )
			*data2 = result->data2;
		if( data3 )
			*data3 = result->data3;
	}
	
	//	Now put back all the messages that we filtered out.
	element = PopGuardedAtomicStackType( filteredOut, AtomicMessageElement, element );
	while( element ) {
		RequirePtrAlign( element, kAtomicAlignment );
		put = PushFrontGuardedAtomicQueueType( element, &queue->queue, AtomicMessageElement,
												element );
		Require( put );
		element = PopGuardedAtomicStackType( filteredOut, AtomicMessageElement, element );
	}
	
	return( message );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Mar 16, 2000	Created.
	wolf		Tue, Apr 11, 2000	AtomicMessageQueue's disposer proc type changed, as
									did filterProc. Updated.
									Also fixed a bug that I discovered while reading the
									code.
	
	************************************************************************************/

	AtomicMessage
ReceiveAtomicMessage(
	AtomicMessageQueue	*queue,
	AtomicMessageProc	filterProc,
	AtomicMessage		filterValue,
	long				*data1,
	long				*data2,
	long				*data3 )
{
	DeclareAlignedVariable( AtomicStack, filteredOut, kAtomicAlignment );
	AtomicMessageElement	*element, *element2, *result = nil;
	AtomicMessage			message = kNoAtomicMessage;
	long					put;
	
	RequirePtrAlign( queue, kAtomicAlignment );
	RequireProcPtrIfNotNil( filterProc );
	RequirePtrIfNotNil( data1 );
	RequirePtrIfNotNil( data2 );
	RequirePtrIfNotNil( data3 );
	
	filteredOut->next = nil;
	
	if( filterProc == nil && filterValue == kNoAtomicMessage ) {
		result = PopGuardedAtomicQueueType( &queue->queue, AtomicMessageElement, element );
	} else {
		//	Pop messages from queue and push them onto the filteredOut stack until we either
		//	find what we're looking for or hit the end of the queue.
		element = PopGuardedAtomicQueueType( &queue->queue, AtomicMessageElement, element );
		while( element && !result ) {
			RequirePtrAlign( element, kAtomicAlignment );
			
			if( filterProc ) {
				//	Filter by callback.
				element2 = filterProc( element, queue );
				Require( element2 == kFilterFoundAtomicMessage
							|| element2 == kFilterNextAtomicMessage );
				
				if( element2 == kFilterFoundAtomicMessage )
					result = element;
			} else {
				//	Filter by value.
				if( element->message == filterValue ) {
					result = element;
				}
			}
			
			if( !result ) {
				//	Didn't find what we're looking for, push the message onto the filteredOut
				//	stack and grab the next message from the queue.
				put = PushGuardedAtomicStackType( element, filteredOut, AtomicMessageElement,
													element );
				Require( put );
				element = PopGuardedAtomicQueueType( &queue->queue, AtomicMessageElement,
														element );
			}
		}
	}
	
	//	If we found the message we're looking for, read its data and dispose of it.
	if( result ) {
		RequirePtrAlign( result, kAtomicAlignment );
		message = result->message;
		if( data1 )
			*data1 = result->data1;
		if( data2 )
			*data2 = result->data2;
		if( data3 )
			*data3 = result->data3;
		if( result->disposer ) {
			RequireProcPtr( result->disposer );
			result->disposer( result, queue );
		}
	}
	
	//	Now put back all the messages that we filtered out.
	element = PopGuardedAtomicStackType( filteredOut, AtomicMessageElement, element );
	while( element ) {
		RequirePtrAlign( element, kAtomicAlignment );
		put = PushFrontGuardedAtomicQueueType( element, &queue->queue, AtomicMessageElement, element );
		Require( put );
		element = PopGuardedAtomicStackType( filteredOut, AtomicMessageElement, element );
	}
	
	return( message );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Apr 20, 1999	Created.
	
	************************************************************************************/

	void
DumpAtomicMessages(
	AtomicMessageQueue	*queue )
{
	RequirePtrAlign( queue, kAtomicAlignment );
	while( ReceiveAtomicMessage( queue, nil, kNoAtomicMessage, nil, nil, nil )
			!= kNoAtomicMessage ){}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Mon, Apr 26, 1999	Created.
	wolf		Tue, Apr 11, 2000	AtomicMessageQueue's disposer proc type changed.
									Updated.
	
	************************************************************************************/

	AtomicMessageElement*
DisposeMessage(
	AtomicMessageElement	*message,
	AtomicMessageQueue		*/*queue*/ )
{
	Ptr	p = GetUnalignedPtr( message );
	
	RequireMacPtr( p );
	DisposePtr( p );
	return( nil );
}



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

  MacsBug/
    AtomicMessages.mbug
    AtomicMessages.mbug.r
  AtomicMessages.c
  AtomicMessages.h
  TestAtomicMessages.c