mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
95 lines
2.2 KiB
Plaintext
95 lines
2.2 KiB
Plaintext
module std::experimental::scheduler <Event>;
|
|
import std::collections, std::thread, std::time;
|
|
|
|
struct DelayedSchedulerEvent @local
|
|
{
|
|
inline Event event;
|
|
Clock execution_time;
|
|
}
|
|
|
|
fn int DelayedSchedulerEvent.compare_to(self, DelayedSchedulerEvent other)
|
|
{
|
|
switch
|
|
{
|
|
case self.execution_time < other.execution_time: return -1;
|
|
case self.execution_time > other.execution_time: return 1;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
struct FrameScheduler
|
|
{
|
|
PriorityQueue{DelayedSchedulerEvent} delayed_events;
|
|
List{Event} events;
|
|
List{Event} pending_events;
|
|
bool pending;
|
|
Mutex mtx;
|
|
}
|
|
|
|
fn void FrameScheduler.init(&self)
|
|
{
|
|
self.events.init(mem);
|
|
self.pending_events.init(mem);
|
|
self.delayed_events.init(mem);
|
|
(void)self.mtx.init();
|
|
bool pending;
|
|
}
|
|
|
|
macro void FrameScheduler.@destroy(&self; @destruct(Event e))
|
|
{
|
|
foreach (e : self.events) @destruct(e);
|
|
foreach (e : self.pending_events) @destruct(e);
|
|
foreach (e : self.delayed_events.heap) @destruct(e.event);
|
|
self.events.free();
|
|
self.pending_events.free();
|
|
self.delayed_events.free();
|
|
self.mtx.destroy();
|
|
}
|
|
|
|
fn void FrameScheduler.queue_delayed_event(&self, Event event, Duration delay)
|
|
{
|
|
self.mtx.@in_lock()
|
|
{
|
|
self.delayed_events.push({ event, clock::now().add_duration(delay)});
|
|
@atomic_store(self.pending, true);
|
|
};
|
|
}
|
|
|
|
fn bool FrameScheduler.has_delayed(&self)
|
|
{
|
|
self.mtx.@in_lock()
|
|
{
|
|
return @ok(self.delayed_events.first());
|
|
};
|
|
}
|
|
|
|
fn void FrameScheduler.queue_event(&self, Event event)
|
|
{
|
|
self.mtx.@in_lock()
|
|
{
|
|
self.pending_events.push(event);
|
|
@atomic_store(self.pending, true);
|
|
};
|
|
}
|
|
fn Event? FrameScheduler.pop_event(&self)
|
|
{
|
|
while (true)
|
|
{
|
|
if (try event = self.events.pop()) return event;
|
|
if (!@atomic_load(self.pending)) return NO_MORE_ELEMENT~;
|
|
self.mtx.@in_lock()
|
|
{
|
|
self.events.add_all(&self.pending_events);
|
|
self.pending_events.clear();
|
|
Clock c = clock::now();
|
|
while (try top = self.delayed_events.first())
|
|
{
|
|
if (top.execution_time > c) break;
|
|
self.events.push(self.delayed_events.pop()!!);
|
|
}
|
|
@atomic_store(self.pending, self.delayed_events.len() > 0);
|
|
if (!self.events.len()) return NO_MORE_ELEMENT~;
|
|
};
|
|
}
|
|
}
|