It's been raining so here you go (completely untested):
type
TEventStack = record
Counter: int64;
Head: PEventItemHolder;
procedure Push(EventItem: PEventItemHolder);
function Pop: PEventItemHolder;
end;
var
EventCache: TEventStack;
...
EventItemHolders: TEventStack;
procedure TEventStack.Push(EventItem: PEventItemHolder);
var
Current, Next: TEventStack;
begin
repeat
// We don't need to copy atomically since the test below will detect tearing
// but since the members should be aligned tearing should not occur anyway.
Current := Self;
EventItem.Next := Current.Head;
Next.Head := EventItem;
Next.Counter := Current.Counter + 1;
// I'm assuming TInterlocked.CompareExchange returns a boolean: True on success.
until TInterlocked.CompareExchange(Self, Next, Current);
end;
function TEventStack.Pop: PEventItemHolder;
var
Current, Next: TEventStack;
begin
repeat
Current := Self;
if (Current.Head = nil) then
Exit(nil);
Next.Head := Current.Head.Next;
Next.Counter := Current.Counter + 1;
until TInterlocked.CompareExchange(Self, Next, Current);
Result := Current.Head;
end;
I've made the two functions members of the record to get rid of the first parameter.
What you (or someone else) need to do is provide an implementation of TInterlocked.CompareExchange, AtomicCmpExchange or CAS that handles 16 bytes and returns a boolean indicating success.