// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.Threading; using System.Runtime.InteropServices; using System; namespace FASTER.core { [StructLayout(LayoutKind.Explicit)] struct AtomicOwner { [FieldOffset(0)] int owner; [FieldOffset(4)] int count; [FieldOffset(0)] long atomic; /// /// Enqueue token /// true: success + caller is new owner /// false: success + someone else is owner /// /// public bool Enqueue() { while (true) { var older = this; var newer = older; newer.count++; if (older.owner == 0) newer.owner = 1; if (Interlocked.CompareExchange(ref this.atomic, newer.atomic, older.atomic) == older.atomic) { return older.owner == 0; } } } /// /// Dequeue token (caller is/remains owner) /// true: successful dequeue /// false: failed dequeue /// /// public bool Dequeue() { while (true) { var older = this; var newer = older; newer.count--; if (Interlocked.CompareExchange(ref this.atomic, newer.atomic, older.atomic) == older.atomic) { return newer.count > 0; } } } /// /// Release queue ownership /// true: successful release /// false: failed release /// /// public bool Release() { while (true) { var older = this; var newer = older; if (newer.count > 0) return false; if (newer.owner == 0) throw new Exception("Invalid release by non-owner thread"); newer.owner = 0; if (Interlocked.CompareExchange(ref this.atomic, newer.atomic, older.atomic) == older.atomic) { return true; } } } } }