Fiber
Fibers Lighweight Cooperative Multitasking
IEnumeratorWorker.cs
1 // Copyright 2018 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 // ReSharper disable ClassNeverInstantiated.Local, ClassNeverInstantiated.Global
4 
5 using System;
6 using System.Collections;
7 using UnityEngine;
8 
9 namespace Askowl {
10  public partial class Fiber {
11  /// <a href="http://bit.ly/2CSVnCt">Wait for a C# IEnumerator/Unity Coroutine to take a step</a>
12  public Fiber WaitFor(IEnumerator enumerator) =>
13  AddAction(_ => LoadWithPayload(enumerator, 0), "WaitFor(IEnumerator)");
14 
15  /// <a href="http://bit.ly/2CSVnCt">Wait for a C# IEnumerator/Unity Coroutine to take a step - value passed by function return</a>
16  public Fiber WaitFor(Func<Fiber, IEnumerator> getter) =>
17  AddAction(_ => LoadWithPayload(getter(this), 0), "WaitFor(IEnumerator)");
18 
19  /// <a href=""></a> //#TBD#//
20  public Fiber WaitFor(int framesBetweenChecks, IEnumerator enumerator) =>
21  AddAction(_ => LoadWithPayload(enumerator, framesBetweenChecks), "WaitFor(framesBetweenChecks, IEnumerator)");
22 
23  private Fiber LoadWithPayload(IEnumerator enumerator, int skipFrames) {
24  var payload = new EnumeratorWorker.Payload {Enumerator = enumerator, SkipFrames = skipFrames};
25  return EnumeratorWorker.Instance.Load(this, payload);
26  }
27 
28  /// <a href=""></a> <inheritdoc /> //#TBD#//
29  private class EnumeratorWorker : Worker<EnumeratorWorker.Payload> {
30 // static EnumeratorWorker() => NeedsUpdates = false;
31  // ReSharper disable once MemberHidesStaticFromOuterClass
32  public static EnumeratorWorker Instance => Cache<EnumeratorWorker>.Instance;
33  protected override void Recycle() => Cache<EnumeratorWorker>.Dispose(this);
34 
35  /// <a href=""></a> //#TBD#//
36  public struct Payload {
37  internal IEnumerator Enumerator;
38  internal int SkipFrames;
39  }
40 
41  private int nextStepFrame;
42 
43  protected override bool Prepare() => true;
44 
45  protected override int CompareTo(Worker other) =>
46  Seed.SkipFrames.CompareTo((other as EnumeratorWorker)?.Seed.SkipFrames);
47 
48  public override void Step() {
49  if (Time.frameCount < nextStepFrame) return;
50 
51  nextStepFrame = Time.frameCount + Seed.SkipFrames;
52 
53  if (Seed.Enumerator.MoveNext()) {
54  switch (Seed.Enumerator.Current) {
55  case IEnumerator coroutine:
56  Fiber.WaitFor(coroutine);
57  break;
58  case float seconds:
59  Fiber.WaitFor(seconds);
60  break;
61  case int frames:
62  nextStepFrame = Time.frameCount + frames;
63  break;
64  case YieldInstruction _:
65  Debug.LogWarning(
66  $"YieldInstruction {Seed.Enumerator.Current.GetType()} only works with Unity coroutines");
67  break;
68  case null: break; // step again on next frame
69  }
70  } else { Dispose(); }
71  }
72  }
73  }
74 }
Definition: Emitter.cs:6
Abstract code to implement a worker
Definition: Worker.cs:15
lightweight cooperative multi-tasking
Definition: Fiber.cs:10
Fiber WaitFor(IClosure closure)
Helper that is the same as fiber.WaitFor(closure.OnComplete)
void Dispose()
Cleans up Fiber before it goes into the recycling
Definition: Fiber.cs:34
static Fiber Instance
Precompile an instance of a fiber command
Definition: Fiber.cs:22
Fiber SkipFrames(int framesToSkip)
Wait a specific count of Update, FixedUpdate or LateUpdate frames