Fiber
Fibers Lighweight Cooperative Multitasking
Worker.cs
1 // Copyright 2018 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 // ReSharper disable StaticMemberInGenericType
4 
5 using System;
6 using UnityEngine;
7 
8 namespace Askowl {
9  // ReSharper disable once ClassNeverInstantiated.Global
10  public partial class Fiber {
11  /// <a href="http://bit.ly/2Ptbf6V">List of workers associated with Fiber actions</a>
12  public readonly Fifo<Worker> Workers = Fifo<Worker>.Instance;
13 
14  /// <a href="http://bit.ly/2Ptbf6V">Abstract code to implement a worker</a>
15  public abstract class Worker : IDisposable {
16  /// <a href="http://bit.ly/2Ptbf6V">Fiber that owns this worker instance</a>
17  protected Fiber Fiber;
18  /// <a href="http://bit.ly/2Ptbf6V">Queue that Fiber came from and will return to after worker is done</a>
19  internal Queue From;
20 
21  private protected static void Deactivate(LinkedList<Fiber>.Node node) => node.MoveTo(node.Item.Workers.Top.From);
22 
23  private protected static int Compare(LinkedList<Fiber>.Node left, LinkedList<Fiber>.Node right) =>
24  left.Item.Workers.Top?.CompareTo(right.Item.Workers.Top) ?? ((right.Item.Workers.Top == null) ? 0 : -1);
25 
26  /// <a href="http://bit.ly/2Ptbf6V">Implement for worker queue order</a>
27  protected virtual int CompareTo(Worker other) => 0;
28 
29  /// <a href="http://bit.ly/2Ptbf6V">Implement to stop scanning based on sort order</a>
30  public virtual bool NoMore => false;
31 
32  /// <a href="http://bit.ly/2Ptbf6V">Implement on processing worker (usually calls dispose)</a>
33  public virtual void Step() { }
34 
35  /// <a href="http://bit.ly/2Ptbf6V">Name from worker class name</a>
36  public string Name;
37 
38  /// <a href="http://bit.ly/2Ptbf6V">Return worker name</a>
39  public override string ToString() => Name;
40 
41  /// <a href="http://bit.ly/2Ptbf6V">Do any preparation to payload here</a>
42  protected abstract bool Prepare();
43 
44  /// <a href="http://bit.ly/2Ptbf6V">Implement anything needed before worker is placed in recycle bin</a>
45  protected abstract void Recycle();
46 
47  /// <a href="http://bit.ly/2Ptbf6V">Move Fiber back to queue it came from</a> <inheritdoc />
48  public virtual void Dispose() {
49  Fiber.node.MoveTo(From);
50  Fiber.Workers.Pop();
51  Recycle();
52  }
53  }
54 
55  /// <a href="http://bit.ly/2Ptbf6V">Worker with payload</a> <inheritdoc />
56  public abstract class Worker<T> : Worker {
57  /// <a href="http://bit.ly/2Ptbf6V">Payload</a>
58  public T Seed;
59 
60  /// <a href="http://bit.ly/2Ptbf6V">Load happens when we are building up a list of actions</a>
61  public Fiber Load(Fiber fiber, T data) {
62  if (NeedsUpdates) Instance.Go(onUpdate); // hook into update if this worker needs it
63  NeedsUpdates = false;
64 
65  Name = $"{GetType()}-{Uid += 1}";
66  Seed = data;
67  Fiber = fiber;
68  // ActivateWorker happens when we are executing all the actions in sequence
69  if (fiber.Running) { ActivateWorker(fiber); } else { fiber.AddAction(ActivateWorker); }
70  return fiber;
71  }
72 
73  private protected static int Uid;
74 
75  /// <a href="http://bit.ly/2Ptbf6V">Move fiber to worker queue and start processing</a>
76  protected void ActivateWorker(Fiber fiber) {
77  if (!Prepare()) return;
78  fiber.Workers.Push(this);
79  From = (Queue) fiber.node.Owner;
80  fiber.node.MoveTo(Queue);
81  }
82 
83  internal static readonly Queue Queue = new Queue {CompareItem = Compare, DeactivateItem = Deactivate};
84 
85  /// <a href="http://bit.ly/2Ptbf6V">Set to false for workers that do not need calls on frame update</a>
86  protected static bool NeedsUpdates = true;
87 
88  // ReSharper disable once MemberHidesStaticFromOuterClass
89  private static readonly Action onUpdate = (fiber) => {
90  var node = Queue.First;
91  while (node?.Item.Workers.Top?.NoMore == false) {
92  var next = node.Next; // save in case Step() calls dispose
93  node.Item.Workers.Top.Step();
94  node = next;
95  }
96  };
97  }
98  }
99 }
Definition: Emitter.cs:6
virtual bool NoMore
Implement to stop scanning based on sort order
Definition: Worker.cs:30
abstract void Recycle()
Implement anything needed before worker is placed in recycle bin
Abstract code to implement a worker
Definition: Worker.cs:15
lightweight cooperative multi-tasking
Definition: Fiber.cs:10
override string ToString()
Return Fiber contents and current state
virtual void Dispose()
Move Fiber back to queue it came from
Definition: Worker.cs:48
T Seed
Payload
Definition: Worker.cs:58
string Name
Name from worker class name
Definition: Worker.cs:36
Fiber Load(Fiber fiber, T data)
Load happens when we are building up a list of actions
Definition: Worker.cs:61
Fiber Fiber
Fiber that owns this worker instance
Definition: Worker.cs:17
Fiber Go()
Start a fiber if it is not already running
readonly Fifo< Worker > Workers
List of workers associated with Fiber actions
Definition: Worker.cs:12
virtual void Step()
Implement on processing worker (usually calls dispose)
Definition: Worker.cs:33
static bool NeedsUpdates
Set to false for workers that do not need calls on frame update
Definition: Worker.cs:86
static Fiber Instance
Precompile an instance of a fiber command
Definition: Fiber.cs:22
virtual int CompareTo(Worker other)
Implement for worker queue order
abstract bool Prepare()
Do any preparation to payload here
void ActivateWorker(Fiber fiber)
Move fiber to worker queue and start processing
Definition: Worker.cs:76
delegate void Action(Fiber fiber)
Method signature for Do(Action) methods