Code Search for Developers
 
 
  

atomicity.h from redshed at Krugle


Show atomicity.h syntax highlighted

/****************************************************************************************
	atomicity.h $Revision: 48 $
		<http://rentzsch.com/atomicity>
	
	Copyright © 1998-2002 Red Shed Software. All rights reserved.
	by Jonathan 'Wolf' Rentzsch (jon at redshed dot net)
		
	This code requires a 68020 or later or any PowerPC. No habla 68000 or x86.
	
	************************************************************************************/

#ifndef		_atomicity_
#define		_atomicity_

#include	<stddef.h>
#include	"atomicity.config.h"

#ifdef		__cplusplus
extern	"C"	{
#endif	//	__cplusplus

#define		kAtomicAlignment	4

/****************************************************************************************
*	
*	Atomic Basis
*	
****************************************************************************************/
#pragma mark	(Atomic Basis)

//	Performs the following atomically:
//	if( *address == oldValue ) {
//		*address = newValue;
//		return 1;
//	} else {
//		return 0;
//	}
//	Resistant to non-modifing preemptions.

	extern
	pascal
	long
MyAtomicStore(
	long	oldValue,
	long	newValue,
	void	*address );

//	Performs the following atomically:
//	if( *address == oldValue ) {
//		*address = newValue;
//		return 1;
//	} else {
//		return 0;
//	}
//	Resistant to non-modifing preemptions.

	extern
	pascal
	long
MyAtomicStorePtr(
	void	*oldValue,
	void	*newValue,
	void	*address );

//	Performs the following atomically:
//	if( *address == oldValue && *address2 == oldValue2 ) {
//		*address = newValue;
//		return 1;
//	} else {
//		return 0;
//	}
//	Resistant to non-modifing preemptions.

	extern
	pascal
	long
AtomicStore2(
	long	oldValue,
	long	newValue,
	void	*address,
	long	oldValue2,
	void	*address2 );

//	Performs the following atomically:
//	if( *address == oldValue && *address2 == oldValue2 ) {
//		*address = newValue;
//		return 1;
//	} else {
//		return 0;
//	}
//	Resistant to non-modifing preemptions.

	extern
	pascal
	long
AtomicStore2Ptr(
	void	*oldValue,
	void	*newValue,
	void	*address,
	void	*oldValue2,
	void	*address2 );

/****************************************************************************************
*	
*	Atomic Stacks
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Atomic Stacks)

typedef	struct	AtomicElement	AtomicElement, AtomicStack;

struct	AtomicElement	{
	volatile	AtomicElement	*next;
	
#ifdef	__cplusplus
	AtomicElement() : next( nil ){}
#endif
};

/**************************
*	
*	Atomic Stack Functions
*
*	An atomic stack is an atomic last-in-first-out list.
*
*	These are the lowest level functions to atomically manipulate stacks.
*	
**************************/
#pragma mark	(Atomic Stack Functions)

//	Atomically set element->next to stack->next, set stack->next to element.

	extern
	void
MyPushAtomicStack(
	AtomicElement	*element,
	AtomicStack		*stack );

//	Atomically store stack->next, set stack->next to stack->next->next, and return the
//	first element. It's okay if stack->next == nil: PopAtomicStack() will return nil.

	extern
	AtomicElement*
MyPopAtomicStack(
	AtomicStack		*stack );

//	Atomically set toStack->next to fromStack->next and set fromStack->next to nil.
//	It's okay if fromStack->next == nil: StealAtomicStack() will return set toStack->next
//	to nil.

	extern
	void
StealAtomicStack(
	AtomicStack		*fromStack,
	AtomicStack		*toStack );

//	Simply returns stack->next.

	extern
	AtomicElement*
PeekAtomicStack(
	AtomicStack		*stack );

/**************************
*	
*	Atomic Stack Offset Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Atomic Stack Offset Functions)

//	Adds offset to element, and calls PushAtomicStack().

	extern
	void
PushAtomicStackOff(
	void			*element,
	AtomicStack		*stack,
	size_t			offset );

//	Calls PopAtomicStack(), if the result is not nil, subtracts offset from the result
//	and returns it.

	extern
	AtomicElement*
PopAtomicStackOff(
	AtomicStack		*stack,
	size_t			offset );

//	Calls PeekAtomicStack(), if the result is not nil, subtracts offset from the result
//	and returns it.

	extern
	AtomicElement*
PeekAtomicStackOff(
	AtomicStack		*stack,
	size_t			offset );

/**************************
*	
*	Atomic Stack Type Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Atomic Stack Type Functions)

#define		PushAtomicStackType( ELEMENT, STACK, STRUCTURE, FIELD )	\
				PushAtomicStackOff( (ELEMENT), (STACK), offsetof( STRUCTURE, FIELD ) )

#define		PopAtomicStackType( STACK, STRUCTURE, FIELD )	\
				((STRUCTURE*) PopAtomicStackOff( (STACK), offsetof( STRUCTURE, FIELD ) ))

#define		PeekAtomicStackType( STACK, STRUCTURE, FIELD )	\
				((STRUCTURE*) PeekAtomicStackOff( (STACK), offsetof( STRUCTURE, FIELD ) ))

/****************************************************************************************
*	
*	Atomic Locks
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Atomic Locks)

typedef	volatile	unsigned	long	AtomicLock;

	extern
	long	//	Non-zero if successfully grabbed.
MyGrabAtomicLock(
	AtomicLock	*lock );

	extern
	void
ReleaseAtomicLock(
	AtomicLock	*lock );

/****************************************************************************************
*	
*	Atomic Flags
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Atomic Flags)

typedef	unsigned long				AtomicFlag;
typedef	volatile	unsigned long	AtomicFlags;

#define	kNoAtomicFlags	(AtomicFlags)0x00000000
#define	kNoAtomicFlag	(AtomicFlag) 0x00000000

#define	kAtomicFlag1	(AtomicFlag) 0x00000001
#define	kAtomicFlag2	(AtomicFlag) 0x00000002
#define	kAtomicFlag3	(AtomicFlag) 0x00000004
#define	kAtomicFlag4	(AtomicFlag) 0x00000008
#define	kAtomicFlag5	(AtomicFlag) 0x00000010
#define	kAtomicFlag6	(AtomicFlag) 0x00000020
#define	kAtomicFlag7	(AtomicFlag) 0x00000040
#define	kAtomicFlag8	(AtomicFlag) 0x00000080
#define	kAtomicFlag9	(AtomicFlag) 0x00000100
#define	kAtomicFlag10	(AtomicFlag) 0x00000200
#define	kAtomicFlag11	(AtomicFlag) 0x00000400
#define	kAtomicFlag12	(AtomicFlag) 0x00000800
#define	kAtomicFlag13	(AtomicFlag) 0x00001000
#define	kAtomicFlag14	(AtomicFlag) 0x00002000
#define	kAtomicFlag15	(AtomicFlag) 0x00004000
#define	kAtomicFlag16	(AtomicFlag) 0x00008000
#define	kAtomicFlag17	(AtomicFlag) 0x00010000
#define	kAtomicFlag18	(AtomicFlag) 0x00020000
#define	kAtomicFlag19	(AtomicFlag) 0x00040000
#define	kAtomicFlag20	(AtomicFlag) 0x00080000
#define	kAtomicFlag21	(AtomicFlag) 0x00100000
#define	kAtomicFlag22	(AtomicFlag) 0x00200000
#define	kAtomicFlag23	(AtomicFlag) 0x00400000
#define	kAtomicFlag24	(AtomicFlag) 0x00800000
#define	kAtomicFlag25	(AtomicFlag) 0x01000000
#define	kAtomicFlag26	(AtomicFlag) 0x02000000
#define	kAtomicFlag27	(AtomicFlag) 0x04000000
#define	kAtomicFlag28	(AtomicFlag) 0x08000000
#define	kAtomicFlag29	(AtomicFlag) 0x10000000
#define	kAtomicFlag30	(AtomicFlag) 0x20000000
#define	kAtomicFlag31	(AtomicFlag) 0x40000000
#define	kAtomicFlag32	(AtomicFlag) 0x80000000

	extern
	Boolean	//	The value of the flag within the flags.
GetAtomicFlag(
	AtomicFlags	*flags,
	AtomicFlag	flag );

	extern
	Boolean	//	True if wasn't already set.
SetAtomicFlag(
	AtomicFlags	*flags,
	AtomicFlag	flag );

	extern
	Boolean	//	True if wasn't already clear.
ClearAtomicFlag(
	AtomicFlags	*flags,
	AtomicFlag	flag );

	extern
	Boolean
FlipAtomicFlag(
	AtomicFlags	*flags,
	AtomicFlag	flag,
	Boolean		value );

/****************************************************************************************
	Open Transport Compatibility Options

	Define DontUseOpenTransport *or* UseOpenTransportIfAvailable *or*
	OnlyUseOpenTransport in the file atomicity.config.h. If you don't define any of
	these, the default is UseOpenTransportIfAvailable.
	
	If you define UseOpenTransportIfAvailable or OnlyUseOpenTransport, you *must* call
	InitOpenTransport() in the beginning of your application. If you don't want to
	juggle whether or not to call InitOpenTransport(), simply always call
	OpenAtomicity(). If you defined UseOpenTransportIfAvailable or OnlyUseOpenTransport,
	it maps to InitOpenTransport(), otherwise it maps to noErr.
	
	DontUseOpenTransport:
		o	Open Transport Libraries: Not Required.
		o	Runtime Overhead: None.
	
	UseOpenTransportIfAvailable:
		o	Open Transport Libraries: Required (preferably weakly imported).
		o	Runtime Overhead: Small (larger if requirements checking is turned on).
	
	OnlyUseOpenTransport:
		o	Open Transport Libraries: Required (preferably strongly imported).
		o	Runtime Overhead: None.
	
	************************************************************************************/
#pragma mark	-
#pragma mark	(Open Transport Compatibility Options)

#if		defined(DontUseOpenTransport)
	#define	AtomicStore( OLD, NEW, ADDRESS )	MyAtomicStore( OLD, NEW, ADDRESS )
	#define	AtomicStorePtr( OLD, NEW, ADDRESS )	MyAtomicStorePtr( OLD, NEW, ADDRESS )
	#define	PushAtomicStack( ELEMENT, STACK )	MyPushAtomicStack( ELEMENT, STACK )
	#define	PopAtomicStack( STACK )				MyPopAtomicStack( STACK )
	#define	GrabAtomicLock( LOCK )				MyGrabAtomicLock( LOCK )

	#if	TARGET_API_MAC_CARBON
		#define	OpenAtomicity( flags, context )	noErr
		#define	CloseAtomicity( context )		
	#else
		#define	OpenAtomicity()					noErr
		#define	CloseAtomicity()				
	#endif
	
	#define	UseOTAtomicity( VALUE )				
#elif	defined(OnlyUseOpenTransport)
	#include	"OpenTransport.h"
	#define	AtomicStore( OLD, NEW, ADDRESS )	OTCompareAndSwap32( (UInt32) OLD, (UInt32) NEW, (UInt32*) ADDRESS )
	#define	AtomicStorePtr( OLD, NEW, ADDRESS )	OTCompareAndSwapPtr( OLD, NEW, (void**)ADDRESS )
	#define	PushAtomicStack( ELEMENT, STACK )	OTLIFOEnqueue( (OTLIFO*) STACK, (OTLink*) ELEMENT )
	#define	PopAtomicStack( STACK )				(AtomicElement*) OTLIFODequeue( (OTLIFO*) STACK );
	#define	GrabAtomicLock( LOCK )				AtomicStore( 0, 1, LOCK )

	#if	TARGET_API_MAC_CARBON
		#define	OpenAtomicity( flags, context )	InitOpenTransportInContext( flags, context )
		#define	CloseAtomicity( context )		CloseOpenTransportInContext( context )
	#else
		#define	OpenAtomicity()					InitOpenTransport()
		#define	CloseAtomicity()				CloseOpenTransport()
	#endif
	
	#define	UseOTAtomicity( VALUE )				
#else	//	UseOpenTransportIfAvailable
	#include	"OpenTransport.h"
	extern	long								AtomicStore( long oldValue, long newValue, void *address );
	extern	long								AtomicStorePtr( void *oldValue, void *newValue, void *address );
	extern	void								PushAtomicStack( AtomicElement *element, AtomicStack *stack );
	extern	AtomicElement* 						PopAtomicStack( AtomicStack *stack );
	extern	Boolean								GrabAtomicLock( AtomicLock *lock );
	
	#if	TARGET_API_MAC_CARBON
		extern	OSStatus						OpenAtomicity( OTInitializationFlags flags, OTClientContextPtr *outClientContext );
		extern	void							CloseAtomicity( OTClientContextPtr clientContext );
	#else
		extern	OSStatus						OpenAtomicity();
		extern	void							CloseAtomicity();
	#endif
	
	extern	void								UseOTAtomicity( Boolean value );
#endif

/****************************************************************************************
*	
*	Guarded Atomic Stacks
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Guarded Atomic Stacks)

typedef	struct	GuardedAtomicElement	GuardedAtomicElement;

struct	GuardedAtomicElement	{
	volatile	GuardedAtomicElement	*next;
	volatile	void					*list;
	
#ifdef	__cplusplus
	GuardedAtomicElement() : next( nil ), list( nil ){}
#endif
};

	extern
	long
GrabAtomicElement(
	GuardedAtomicElement	*element,
	void					*list );

	extern
	void
ReleaseAtomicElement(
	GuardedAtomicElement	*element );

/**************************
*	
*	Guarded Atomic Stack Functions
*
*	A guarded atomic stack doesn't allow an element to be pushed more than once.
*	Pushing an element more than once on a stack corrupts the stack into a nasty
*	circular list. These functions test whether the element in already on a stack
*	before blindly pushing the element, saving your stack from corruption.
*	
**************************/
#pragma mark	(Guarded Atomic Stack Functions)

//	Call GrabAtomicLock() on element->lock. If successful, call PushAtomicStack() and
//	return true. Otherwise return false.

	extern
	long
PushGuardedAtomicStack(
	GuardedAtomicElement	*element,
	AtomicStack				*stack );

//	Call PopAtomicStack(). If the result isn't nil, call ReleaseAtomicLock() on the popped
//	element->lock and return the popped element. Otherwise return nil.

	extern
	GuardedAtomicElement*
PopGuardedAtomicStack(
	AtomicStack				*stack );

//	Atomically set toStack->next to fromStack->next and set fromStack->next to nil.
//	It's okay if fromStack->next == nil: StealAtomicStack() will return set toStack->next
//	to nil. It also sets every element's list field from the stolen stack to toStack.

	extern
	void
StealGuardedAtomicStack(
	AtomicStack		*fromStack,
	AtomicStack		*toStack );

//	Simply returns stack->next.

	extern
	GuardedAtomicElement*
PeekGuardedAtomicStack(
	AtomicStack				*stack );

/**************************
*	
*	Guarded Atomic Stack Offset Functions
*
*	Convenience routines for when the GuardedAtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Guarded Atomic Stack Offset Functions)

//	Adds offset to element, and calls PushGuardedAtomicStack().

	extern
	long
PushGuardedAtomicStackOff(
	void			*element,
	AtomicStack		*stack,
	size_t			offset );

//	Calls PopGuardedAtomicStack(), if the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	GuardedAtomicElement*
PopGuardedAtomicStackOff(
	AtomicStack		*stack,
	size_t			offset );

//	Calls PeekGuardedAtomicStack(), if the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	GuardedAtomicElement*
PeekGuardedAtomicStackOff(
	AtomicStack		*stack,
	size_t			offset );

/**************************
*	
*	Guarded Atomic Stack Type Functions
*
*	Convenience routines for when the GuardedAtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Guarded Atomic Stack Type Functions)

#define		PushGuardedAtomicStackType( ELEMENT, STACK, STRUCTURE, FIELD )	\
				PushGuardedAtomicStackOff( (ELEMENT), (STACK), offsetof( STRUCTURE, FIELD ) )

#define		PopGuardedAtomicStackType( STACK, STRUCTURE, FIELD )	\
				((STRUCTURE*) PopGuardedAtomicStackOff( (STACK), offsetof( STRUCTURE, FIELD ) ))

#define		PeekGuardedAtomicStackType( STACK, STRUCTURE, FIELD )	\
				((STRUCTURE*) PeekGuardedAtomicStackOff( (STACK), offsetof( STRUCTURE, FIELD ) ))

#define		RemoveGuardedAtomicStackType( ELEMENT, STACK, STRUCTURE, FIELD )	\
				RemoveGuardedAtomicStackOff( (ELEMENT), (STACK), offsetof( STRUCTURE, FIELD ) )

/****************************************************************************************
*	
*	Atomic Queues
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Atomic Queues)

typedef	struct	{
	AtomicStack		input;
	AtomicStack		output;
}	AtomicQueue;

/**************************
*	
*	Atomic Queue Functions
*
*	An atomic queue is an atomic first-in-first-out list.
*	
**************************/
#pragma mark	(Atomic Queue Functions)

//	Simply calls PushAtomicStack() with queue->input.

	extern
	void
PushAtomicQueue(
	AtomicElement	*element,
	AtomicQueue		*queue );

//	Simply calls PushAtomicStack() with queue->output.

	extern
	void
PushFrontAtomicQueue(
	AtomicElement	*element,
	AtomicQueue		*queue );

//	Calls PopAtomicStack() with queue->output. If the result is not nil,
//	PopAtomicQueue() returns it. Otherwise PopAtomicQueue() calls
//	StealAtomicList() on queue->input. If the result is not nil,
//	PopAtomicQueue() calls PopAtomicStack() on each element in the stolen stack,
//	then calling PushAtomicStack() with queue->output, effectively "reversing" the
//	stack into a queue.

	extern
	AtomicElement*
PopAtomicQueue(
	AtomicQueue		*queue );

//	Calls PopAtomicQueue(). If the result is not nil, then it calls PushAtomicStack()
//	with the result on queue->output.

	extern
	AtomicElement*
PeekAtomicQueue(
	AtomicQueue		*queue );

/**************************
*	
*	Atomic Queue Offset Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Atomic Queue Offset Functions)

//	Adds offset to element, and calls PushAtomicQueue().

	extern
	void
PushAtomicQueueOff(
	void			*element,
	AtomicQueue		*queue,
	size_t			offset );

//	Adds offset to element, and calls PushFrontAtomicQueue().

	extern
	void
PushFrontAtomicQueueOff(
	void			*element,
	AtomicQueue		*queue,
	size_t			offset );

//	Calls PopAtomicQueue(), if the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	AtomicElement*
PopAtomicQueueOff(
	AtomicQueue		*queue,
	size_t			offset );

//	Calls PeekAtomicStack(). If the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	AtomicElement*
PeekAtomicQueueOff(
	AtomicQueue		*queue,
	size_t			offset );

/**************************
*	
*	Atomic Queue Type Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Atomic Queue Type Functions)

#define		PushAtomicQueueType( ELEMENT, QUEUE, STRUCTURE, FIELD )	\
				PushAtomicQueueOff( (ELEMENT), (QUEUE), offsetof( STRUCTURE, FIELD ) )

#define		PushFrontAtomicQueueType( ELEMENT, QUEUE, STRUCTURE, FIELD )	\
				PushFrontAtomicQueueOff( (ELEMENT), (QUEUE), offsetof( STRUCTURE, FIELD ) )

#define		PopAtomicQueueType( QUEUE, STRUCTURE, FIELD )	\
				((STRUCTURE*) PopAtomicQueueOff( (QUEUE), offsetof( STRUCTURE, FIELD ) ))

#define		PeekAtomicQueueType( QUEUE, STRUCTURE, FIELD )	\
				((STRUCTURE*) PeekAtomicQueueOff( (QUEUE), offsetof( STRUCTURE, FIELD ) ))

/****************************************************************************************
*	
*	Guarded Atomic Queues
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Guarded Atomic Queues)

/**************************
*	
*	Guarded Atomic Queue Functions
*
*	A guarded atomic queue is an atomic queue that doesn't allow an element to be
*	pushed more than once.
*	
**************************/
#pragma mark	(Guarded Atomic Queue Functions)

//	Simply calls PushGuardedAtomicStack() with queue->input.

	extern
	long
PushGuardedAtomicQueue(
	GuardedAtomicElement	*element,
	AtomicQueue				*queue );

//	Simply calls PushGuardedAtomicStack() with queue->output.

	extern
	long
PushFrontGuardedAtomicQueue(
	GuardedAtomicElement	*element,
	AtomicQueue				*queue );

//	Calls PopGuardedAtomicStack() with queue->output. If the result is not nil,
//	PopGuardedAtomicQueue() returns it. Otherwise PopGuardedAtomicQueue() calls
//	StealAtomicList() on queue->input. If the result is not nil,
//	PopGuardedAtomicQueue() calls PopAtomicStack() on each element in the stolen stack,
//	then calling PushAtomicStack() with queue->output, effectively "reversing" the
//	stack into a queue.

	extern
	GuardedAtomicElement*
PopGuardedAtomicQueue(
	AtomicQueue		*queue );

//	If queue->output.next is nil, then PeekGuardedAtomicQueue() calls
//	StealAtomicList() on queue->input. If the result is not nil,
//	PopGuardedAtomicQueue() calls PopAtomicStack() on each element in the stolen stack,
//	then calling PushAtomicStack() with queue->output, effectively "reversing" the
//	stack into a queue. PeekGuardedAtomicQueue() returns queue->output.next.

	extern
	GuardedAtomicElement*
PeekGuardedAtomicQueue(
	AtomicQueue		*queue );

/**************************
*	
*	Guarded Atomic Queue Offset Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Guarded Atomic Queue Offset Functions)

//	Adds offset to element, and calls PushGuardedAtomicQueue().

	extern
	long
PushGuardedAtomicQueueOff(
	void			*element,
	AtomicQueue		*queue,
	size_t			offset );

//	Adds offset to element, and calls PushFrontGuardedAtomicQueue().

	extern
	long
PushFrontGuardedAtomicQueueOff(
	void			*element,
	AtomicQueue		*queue,
	size_t			offset );

//	Calls PopGuardedAtomicQueue(), if the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	GuardedAtomicElement*
PopGuardedAtomicQueueOff(
	AtomicQueue		*queue,
	size_t			offset );

//	Calls PekkGuardedAtomicQueue(), if the result is not nil, subtracts offset from
//	the result and returns it.

	extern
	GuardedAtomicElement*
PeekGuardedAtomicQueueOff(
	AtomicQueue		*queue,
	size_t			offset );

/**************************
*	
*	Guarded Atomic Queue Type Functions
*
*	Convenience routines for when the GuardedAtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Guarded Atomic Queue Type Functions)

#define		PushGuardedAtomicQueueType( ELEMENT, QUEUE, STRUCTURE, FIELD )	\
				PushGuardedAtomicQueueOff( (ELEMENT), (QUEUE), offsetof( STRUCTURE, FIELD ) )

#define		PushFrontGuardedAtomicQueueType( ELEMENT, QUEUE, STRUCTURE, FIELD )	\
				PushFrontGuardedAtomicQueueOff( (ELEMENT), (QUEUE), offsetof( STRUCTURE, FIELD ) )

#define		PopGuardedAtomicQueueType( QUEUE, STRUCTURE, FIELD )	\
				((STRUCTURE*) PopGuardedAtomicQueueOff( (QUEUE), offsetof( STRUCTURE, FIELD ) ))

#define		PeekGuardedAtomicQueueType( QUEUE, STRUCTURE, FIELD )	\
				((STRUCTURE*) PeekGuardedAtomicQueueOff( (QUEUE), offsetof( STRUCTURE, FIELD ) ))

/****************************************************************************************
*	
*	Atomic Lists
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Atomic Lists)

typedef	AtomicElement	AtomicList;

/**************************
*	
*	Atomic List Functions
*	
**************************/
#pragma mark	(Atomic List Functions)

//	Atomically set element->next to list->next, set list->next to element.
//	Constant speed, O(1).

	extern
	void
PutFirstAtomicList(
	AtomicElement	*element,
	AtomicList		*list );

//	Sets element->next to after->next. Atomically set after->next to element.
//	Constant speed, O(1).

	extern
	long
PutAfterAtomicList(
	AtomicElement	*element,
	AtomicElement	*after,
	AtomicElement	*oldElement,
	AtomicList		*list );

//	Set element->next to nil. Atomically walk the list until we find the last element.
//	(we'll call this element "lastElement") and set lastElement->next to element.
//	Linear speed, O(n).

	extern
	void
PutLastAtomicList(
	AtomicElement	*element,
	AtomicList		*list );

//	Atomically store list->next, set list->next to list->next->next, and return the
//	first element. It's okay if list->next == nil: RemoveFirstAtomicList() will return nil.
//	Constant speed, O(1).

	extern
	AtomicElement*
RemoveFirstAtomicList(
	AtomicList		*list );

//	Atomically walk the list until the we find the element before "element" (we'll call
//	this element "previousElement") and set previousElement->next to element->next.
//	Linear speed, O(n).

	extern
	long
RemoveAtomicList(
	AtomicElement	*element,
	AtomicList		*list );

//	Peek at the first element in the list. Only useful in its [Off|Type] varients.
//	Constant speed, O(1).

#define		PeekAtomicList( LIST )	PeekAtomicStack( LIST );

//	Atomically steal an entire list.
//	Constant speed, O(1).

#define		StealAtomicList( FROMLIST, TOLIST )	StealAtomicStack( FROMLIST, TOLIST );

//	Atomically walk the list. Upon beginning, set *current to nil. Returns false (0)
//	if interrupted, true if uninterrupted. You must start over upon an interruption.
//	Constant speed, O(1).

	extern
	long
IterateAtomicList(
	AtomicElement	**current,
	AtomicElement	**next,
	AtomicList		*list );

/**************************
*	
*	Atomic List Offset Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Atomic List Offset Functions)

//	

	extern
	void
PutFirstAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	long
PutAfterAtomicListOff(
	void		*element,
	void		*after,
	void		*oldElement,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	void
PutLastAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	AtomicElement*
RemoveFirstAtomicListOff(
	AtomicList		*list,
	size_t			offset );

//	

	extern
	long
RemoveAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//

#define		PeekAtomicListOff( LIST, OFFSET )	PeekAtomicStackOff( LIST, OFFSET )

//	

	extern
	long
IterateAtomicListOff(
	void		**current,
	void		**next,
	AtomicList	*list,
	size_t		offset );

/**************************
*	
*	Atomic List Type Functions
*
*	Convenience routines for when the AtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Atomic List Type Functions)

#define		PutFirstAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				PutFirstAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PutAfterAtomicListType( ELEMENT, AFTER, OLDELEMENT, LIST, STRUCTURE, FIELD )	\
				PutAfterAtomicListOff( (ELEMENT), (AFTER), (OLDELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PutLastAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				PutLastAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		RemoveFirstAtomicListType( LIST, STRUCTURE, FIELD )	\
				((STRUCTURE*) RemoveFirstAtomicListOff( (LIST), offsetof( STRUCTURE, FIELD ) ))

#define		RemoveAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				RemoveAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PeekAtomicListType( LIST, STRUCTURE, FIELD )	\
				PeekAtomicStackType( LIST, STRUCTURE, FIELD )

#define		IterateAtomicListType( CURRENT, NEXT, LIST, STRUCTURE, FIELD )	\
				IterateAtomicListOff( (CURRENT), (NEXT), (LIST), offsetof( STRUCTURE, FIELD ) )

/****************************************************************************************
*	
*	Guarded Atomic Lists
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Guarded Atomic Lists)

/**************************
*	
*	Guarded Atomic List Functions
*
*	A guarded atomic list doesn't allow an element to be pushed more than once.
*	Pushing an element more than once on a list corrupts the stack into a nasty
*	circular list. These functions test whether the element in already on a list
*	before blindly pushing the element, saving your list from corruption.
*	
**************************/
#pragma mark	(Guarded Atomic List Functions)

//	Call GrabAtomicLock() on element->lock. If successful, call PutFirstAtomicList() and
//	return true. Otherwise return false.

	extern
	long
PutFirstGuardedAtomicList(
	GuardedAtomicElement	*element,
	AtomicList				*list );

//	

	extern
	long
PutAfterGuardedAtomicList(
	GuardedAtomicElement	*element,
	GuardedAtomicElement	*after,
	GuardedAtomicElement	*oldElement,
	AtomicList				*list );

//	Call GrabAtomicLock() on element->lock. If successful, call PutLastAtomicList() and
//	return true. Otherwise return false.

	extern
	long
PutLastGuardedAtomicList(
	GuardedAtomicElement	*element,
	AtomicList				*list );

//	Call RemoveFirstAtomicList(). If the result is not nil, call ReleaseAtomicLock() on
//	it and return it. Otherwise just return nil.

	extern
	GuardedAtomicElement*
RemoveFirstGuardedAtomicList(
	AtomicList		*list );

//	Call RemoveAtomicList(). If the result is not zero, then call ReleaseAtomicLock()
//	on element->lock. Return the result.

	extern
	long
RemoveGuardedAtomicList(
	GuardedAtomicElement	*element,
	AtomicList				*list );

//

#define		PeekGuardedAtomicList( LIST )	PeekGuardedAtomicStack( LIST )

//

#define		StealGuardedAtomicList( FROMLIST, TOLIST )	StealGuardedAtomicStack( FROMLIST, TOLIST )

//	

	extern
	long
IterateGuardedAtomicList(
	GuardedAtomicElement	**current,
	GuardedAtomicElement	**next,
	AtomicList				*list );

/**************************
*	
*	Guarded Atomic List Offset Functions
*
*	Convenience routines for when the GuardedAtomicElement field in your structure
*	can't be the first field. You supply the coercions and field offset.
*	
**************************/
#pragma mark	(Guarded Atomic List Offset Functions)

//	Adds offset to element, and calls PutFirstGuardedAtomicList().

	extern
	long
PutFirstGuardedAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	long
PutAfterGuardedAtomicListOff(
	void		*element,
	void		*after,
	void		*oldElement,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	long
PutLastGuardedAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//	

	extern
	GuardedAtomicElement*
RemoveFirstGuardedAtomicListOff(
	AtomicList		*list,
	size_t			offset );

//	

	extern
	long
RemoveGuardedAtomicListOff(
	void		*element,
	AtomicList	*list,
	size_t		offset );

//

#define		PeekGuardedAtomicListOff( LIST )	PeekGuardedAtomicStackOff( LIST )

//	

	extern
	long
IterateGuardedAtomicListOff(
	void		**current,
	void		**next,
	AtomicList	*list,
	size_t		offset );

/**************************
*	
*	Guarded Atomic List Type Functions
*
*	Convenience routines for when the GuardedAtomicElement field in your structure
*	can't be the first field. You supply the structure and field names. It does
*	the coercions and offsets for you.
*	
**************************/
#pragma mark	(Guarded Atomic List Type Functions)

#define		PutFirstGuardedAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				PutFirstGuardedAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PutAfterGuardedAtomicListType( ELEMENT, AFTER, OLDELEMENT, LIST, STRUCTURE, FIELD )	\
				PutAfterGuardedAtomicListOff( (ELEMENT), (AFTER), (OLDELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PutLastGuardedAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				PutLastGuardedAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		RemoveFirstGuardedAtomicListType( LIST, STRUCTURE, FIELD )	\
				((STRUCTURE*) RemoveFirstGuardedAtomicListOff( (LIST), offsetof( STRUCTURE, FIELD ) ))

#define		RemoveGuardedAtomicListType( ELEMENT, LIST, STRUCTURE, FIELD )	\
				RemoveGuardedAtomicListOff( (ELEMENT), (LIST), offsetof( STRUCTURE, FIELD ) )

#define		PeekGuardedAtomicListType( LIST, STRUCTURE, FIELD )	\
				PeekGuardedAtomicStackType( LIST, STRUCTURE, FIELD )

#define		IterateGuardedAtomicListType( CURRENT, NEXT, LIST, STRUCTURE, FIELD )	\
				IterateGuardedAtomicListOff( (void**)(CURRENT), (void**)(NEXT), (LIST), offsetof( STRUCTURE, FIELD ) )

#ifdef	__cplusplus
}
#endif

#endif	//	_atomicity_



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/
    atomicity.mbug
    atomicity.mbug.r
    mxwt_template.rsrc
  TestAtomicity.cp
  atomicity.c
  atomicity.config.h
  atomicity.h