2023-04-05 06:47:51 +00:00
|
|
|
/**
|
|
|
|
* A queue of queue items all of the same tag
|
|
|
|
*/
|
2020-09-29 09:57:25 +00:00
|
|
|
module tristanable.queue;
|
|
|
|
|
2023-03-27 13:41:50 +00:00
|
|
|
// TODO: Examine the below import which seemingly fixes stuff for libsnooze
|
|
|
|
import libsnooze.clib;
|
2023-02-26 20:24:49 +00:00
|
|
|
import libsnooze;
|
2023-03-27 13:41:50 +00:00
|
|
|
|
2023-02-26 20:24:49 +00:00
|
|
|
import core.sync.mutex : Mutex;
|
2023-03-30 11:35:09 +00:00
|
|
|
import std.container.slist : SList;
|
|
|
|
import tristanable.encoding;
|
2023-02-26 20:24:49 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
version(unittest)
|
|
|
|
{
|
|
|
|
import std.stdio;
|
|
|
|
import std.conv : to;
|
|
|
|
}
|
|
|
|
|
2023-02-26 19:55:13 +00:00
|
|
|
public class Queue
|
2020-09-29 09:57:25 +00:00
|
|
|
{
|
2023-02-26 20:24:49 +00:00
|
|
|
/**
|
|
|
|
* Everytime a thread calls `.dequeue()` on this queue
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
private Event event;
|
|
|
|
|
2023-03-30 11:35:09 +00:00
|
|
|
private SList!(TaggedMessage) queue;
|
2023-02-26 20:24:49 +00:00
|
|
|
private Mutex queueLock;
|
2023-03-27 13:41:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This queue's unique ID
|
|
|
|
*/
|
|
|
|
private ulong queueID;
|
2023-02-26 20:24:49 +00:00
|
|
|
|
|
|
|
|
2023-03-29 14:01:34 +00:00
|
|
|
this(ulong queueID)
|
2023-02-26 19:55:13 +00:00
|
|
|
{
|
2023-03-03 15:44:51 +00:00
|
|
|
/* Initialize the queue lock */
|
2023-02-26 20:24:49 +00:00
|
|
|
this.queueLock = new Mutex();
|
2023-03-03 15:44:51 +00:00
|
|
|
|
|
|
|
/* Initialize the event */
|
|
|
|
this.event = new Event();
|
2023-03-29 14:01:34 +00:00
|
|
|
|
|
|
|
/* Set the queue id */
|
|
|
|
this.queueID = queueID;
|
2023-02-26 20:24:49 +00:00
|
|
|
}
|
2020-09-29 09:57:25 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
/**
|
|
|
|
* Enqueues the provided tagged message onto this queue
|
|
|
|
* and then wakes up any thread that has called dequeue
|
|
|
|
* on this queue as well
|
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
* message = the TaggedMessage to enqueue
|
|
|
|
*/
|
2023-03-30 11:35:09 +00:00
|
|
|
public void enqueue(TaggedMessage message)
|
2023-02-26 20:24:49 +00:00
|
|
|
{
|
2023-04-05 06:33:08 +00:00
|
|
|
version(unittest)
|
|
|
|
{
|
|
|
|
writeln("queue["~to!(string)(queueID)~"]: Enqueuing '"~to!(string)(message)~"'...");
|
|
|
|
}
|
2023-03-30 11:35:09 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
scope(exit)
|
|
|
|
{
|
|
|
|
version(unittest)
|
|
|
|
{
|
|
|
|
writeln("queue["~to!(string)(queueID)~"]: Enqueued '"~to!(string)(message)~"'!");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the item queue */
|
|
|
|
queueLock.unlock();
|
|
|
|
}
|
2023-03-30 11:35:09 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
/* Lock the item queue */
|
|
|
|
queueLock.lock();
|
|
|
|
|
|
|
|
/* Add the item to the queue */
|
|
|
|
queue.insertAfter(queue[], message);
|
|
|
|
|
|
|
|
/* Wake up anyone wanting to dequeue from us */
|
2023-03-27 13:41:50 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// TODO: Make us wait on the event (optional with a time-out)
|
2023-04-05 06:33:08 +00:00
|
|
|
event.notifyAll();
|
2023-03-27 13:41:50 +00:00
|
|
|
}
|
|
|
|
catch(SnoozeError snozErr)
|
|
|
|
{
|
|
|
|
// TODO: Add error handling for libsnooze exceptions here
|
|
|
|
}
|
2023-04-05 06:33:08 +00:00
|
|
|
}
|
2023-02-26 20:24:49 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
// TODO: Make a version of this which can time out
|
2023-02-26 20:24:49 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
/**
|
|
|
|
* Blocks till a message can be dequeued from this queue
|
|
|
|
*
|
|
|
|
* Returns: the dequeued TaggedMessage
|
|
|
|
*/
|
|
|
|
public TaggedMessage dequeue()
|
|
|
|
{
|
2023-04-05 06:39:35 +00:00
|
|
|
version(unittest)
|
|
|
|
{
|
|
|
|
writeln("queue["~to!(string)(queueID)~"]: Dequeueing...");
|
|
|
|
}
|
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
/* The dequeued message */
|
|
|
|
TaggedMessage dequeuedMessage;
|
2023-02-26 20:24:49 +00:00
|
|
|
|
2023-04-05 06:39:35 +00:00
|
|
|
scope(exit)
|
|
|
|
{
|
|
|
|
version(unittest)
|
|
|
|
{
|
|
|
|
writeln("queue["~to!(string)(queueID)~"]: Dequeued '"~to!(string)(dequeuedMessage)~"'!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
/* Block till we dequeue a message successfully */
|
|
|
|
while(dequeuedMessage is null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// TODO: Make us wait on the event (optional with a time-out)
|
|
|
|
event.wait();
|
|
|
|
}
|
|
|
|
catch(SnoozeError snozErr)
|
|
|
|
{
|
|
|
|
// TODO: Add error handling for libsnooze exceptions here
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock the item queue */
|
|
|
|
queueLock.lock();
|
|
|
|
|
2023-04-05 06:33:48 +00:00
|
|
|
/* Consume the front of the queue (if non-empty) */
|
2023-04-05 06:33:08 +00:00
|
|
|
if(!queue.empty())
|
|
|
|
{
|
|
|
|
/* Pop the front item off */
|
|
|
|
dequeuedMessage = queue.front();
|
|
|
|
|
|
|
|
/* Remove the front item from the queue */
|
|
|
|
queue.linearRemoveElement(dequeuedMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the item queue */
|
|
|
|
queueLock.unlock();
|
|
|
|
}
|
2023-03-30 11:35:09 +00:00
|
|
|
|
2023-04-05 06:33:08 +00:00
|
|
|
return dequeuedMessage;
|
2023-02-26 19:55:13 +00:00
|
|
|
}
|
2020-09-29 09:57:25 +00:00
|
|
|
|
2023-03-29 14:01:34 +00:00
|
|
|
public ulong getID()
|
2023-02-26 19:55:13 +00:00
|
|
|
{
|
2023-03-29 14:01:34 +00:00
|
|
|
return queueID;
|
2023-02-26 19:55:13 +00:00
|
|
|
}
|
2020-09-29 09:57:25 +00:00
|
|
|
}
|