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