// 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;
}
}
}
}
}