Created
January 14, 2016 17:50
-
-
Save nsf/a7a85e8c742be965399a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Collections.Generic; | |
namespace NG.Tasks { | |
public class Counter { | |
public int Count = 0; | |
/// Task that waits on this counter. | |
public Task WaitingTask; | |
public Counter(int num) { | |
Count = num; | |
} | |
} | |
public enum CoType { | |
Continue, | |
Yield, | |
Done, | |
WaitForCounter, | |
WaitForSemaphore, | |
WaitForMessage, | |
} | |
public class Out<T> : IOut<T> { | |
public T Value { get; set; } | |
} | |
public class CallbackOut<T> : IOut<T> { | |
Action<T> cb; | |
public CallbackOut(Action<T> cb) { | |
this.cb = cb; | |
} | |
public T Value { set { cb(value); } } | |
} | |
public interface IOut<T> { | |
T Value { set; } | |
} | |
public struct Co { | |
public CoType Type; | |
public object Subject; | |
public C.CSMessage Message; | |
/// Continue execution. | |
public static readonly Co Continue = new Co{ Type = CoType.Continue }; | |
/// Stop execution of the current coroutine. | |
public static readonly Co Done = new Co{ Type = CoType.Done }; | |
// Put the current coroutine to the end of the queue. | |
public static readonly Co Yield = new Co{ Type = CoType.Yield }; | |
/// Lock a mutex, possibly putting the current coroutine on hold if the mutex was locked by another coroutine. | |
public static Co Lock(Mutex m) { | |
return m.Lock(); | |
} | |
/// Unlock a mutex. Will schedule a coroutine for execution if there is one in internal queue. | |
public static void Unlock(Mutex m) { | |
m.Unlock(); | |
} | |
/// Schedule task for execution. | |
public static void Go(Task task) { | |
Scheduler.Go(task); | |
} | |
/// Schedule task for execution. | |
public static void Go(IEnumerator<Co> task) { | |
Scheduler.Go(new Task(task)); | |
} | |
/// Schedule task for execution with specified parameters. | |
public static void Go(IEnumerator<Co> task, TaskParameters tp) { | |
Scheduler.Go(new Task(task, tp)); | |
} | |
/// Schedule task for execution. | |
public static void Go(Action action) { | |
Scheduler.Go(new Task(action)); | |
} | |
/// Schedule task for execution with specified parameters. | |
public static void Go(Action action, TaskParameters tp) { | |
Scheduler.Go(new Task(action, tp)); | |
} | |
static Task ToTask(IEnumerator<Co> task) { | |
return new Task(task); | |
} | |
/// Runs tasks and waits for their completion. | |
public static Co WaitFor(IEnumerator<Co>[] tasks) { | |
return Scheduler.WaitFor(tasks.Select(ToTask).ToArray()); | |
} | |
/// Runs tasks and waits for their completion. | |
public static Co WaitFor(IEnumerable<IEnumerator<Co>> tasks) { | |
return Scheduler.WaitFor(tasks.Select(ToTask).ToArray()); | |
} | |
/// Runs tasks with specified parameters and waits for their completion. | |
public static Co WaitFor(IEnumerator<Co>[] tasks, TaskParameters tp) { | |
var ts = tasks.Select(ToTask).ToArray(); | |
for (int i = 0; i < ts.Length; i++) | |
ts[i].Params = tp; | |
return Scheduler.WaitFor(ts); | |
} | |
/// Runs tasks with specified parameters and waits for their completion. | |
public static Co WaitFor(IEnumerable<IEnumerator<Co>> tasks, TaskParameters tp) { | |
var ts = tasks.Select(ToTask).ToArray(); | |
for (int i = 0; i < ts.Length; i++) | |
ts[i].Params = tp; | |
return Scheduler.WaitFor(ts); | |
} | |
/// Runs tasks and waits for their completion. | |
public static Co WaitFor(IEnumerable<Task> tasks) { | |
return Scheduler.WaitFor(tasks.ToArray()); | |
} | |
/// Runs tasks and waits for their completion. | |
public static Co WaitFor(Task[] tasks) { | |
return Scheduler.WaitFor(tasks); | |
} | |
/// Runs task and waits for its completion. | |
public static Co WaitFor(Task task) { | |
return Scheduler.WaitFor(task); | |
} | |
/// Runs task and waits for its completion. | |
public static Co Do(IEnumerator<Co> task) { | |
Scheduler.CurrentTask.Value.Push(task); | |
return Co.Continue; | |
} | |
/// Runs task with specified parameters and waits for its completion. | |
public static Co WaitFor(IEnumerator<Co> task, TaskParameters tp) { | |
return Scheduler.WaitFor(new Task(task, tp)); | |
} | |
/// Runs task and waits for its completion. | |
public static Co Do(Action action) { | |
Scheduler.CurrentTask.Value.Push(action); | |
return Co.Continue; | |
} | |
/// Runs task with specified parameters and waits for its completion. | |
public static Co WaitFor(Action action, TaskParameters tp) { | |
return Scheduler.WaitFor(new Task(action, tp)); | |
} | |
public static Co WaitFor<T>(T msg) where T : C.BindGen.IMessage { | |
return new Co { | |
Type = CoType.WaitForMessage, | |
Message = new C.CSMessage(msg.Handle), | |
}; | |
} | |
public static void WaitForAnd<T>(T msg, Action cb) where T : C.BindGen.IMessage { | |
Scheduler.WaitForAnd(msg, new Task(cb)); | |
} | |
} | |
public enum Type { | |
CPU, | |
IO, | |
} | |
public enum Priority { | |
Critical, | |
High, | |
Normal, | |
Low, | |
Background, | |
} | |
public struct TaskParameters { | |
public string Name; | |
public Type Type; | |
public Priority Priority; | |
public bool SameTypeAndPriority(TaskParameters rhs) { | |
return Type == rhs.Type && Priority == rhs.Priority; | |
} | |
public static readonly TaskParameters Default = new TaskParameters { | |
Name = "unknown", | |
Type = Type.CPU, | |
Priority = Priority.Normal, | |
}; | |
public static TaskParameters Named(string name) { | |
var tp = Default; | |
tp.Name = name; | |
return tp; | |
} | |
} | |
public class Task { | |
public TaskParameters Params = TaskParameters.Default; | |
public Counter Counter; | |
public Mutex Mutex; | |
Stack<IEnumerator<Co>> stack = new Stack<IEnumerator<Co>>(4); | |
static IEnumerator<Co> ActionTask(Action action) { | |
action(); | |
yield break; | |
} | |
public Task(Action action) { | |
stack.Push(ActionTask(action)); | |
} | |
public Task(Action action, TaskParameters tp) { | |
stack.Push(ActionTask(action)); | |
Params = tp; | |
} | |
public Task(IEnumerator<Co> task) { | |
stack.Push(task); | |
} | |
public Task(IEnumerator<Co> task, TaskParameters tp) { | |
stack.Push(task); | |
Params = tp; | |
} | |
public void Push(IEnumerator<Co> task) { | |
stack.Push(task); | |
} | |
public void Push(Action action) { | |
stack.Push(ActionTask(action)); | |
} | |
public Co Run() { | |
while (stack.Count > 0) { | |
var enumerator = stack.Peek(); | |
if (!enumerator.MoveNext()) { | |
enumerator.Dispose(); | |
stack.Pop(); | |
continue; | |
} | |
Co d = enumerator.Current; | |
if (d.Type == CoType.Done) { | |
enumerator.Dispose(); | |
stack.Pop(); | |
continue; | |
} | |
return d; | |
} | |
return Co.Done; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment