Fiber
Fibers Lighweight Cooperative Multitasking
Emitter.cs
1 // Copyright 2018 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 using System;
4 using UnityEngine;
5 
6 namespace Askowl {
7  /// <a href="http://bit.ly/2B6jpZl">Cached C# Action instances using the observer pattern</a>
8  public class Emitter : IDisposable {
9  #region Instantiate
10  /// <a href="http://bit.ly/2B6jpZl">Retrieve an emitter from recycling or new</a>
11  public static Emitter Instance => Cache<Emitter>.Instance;
12 
13  /// <a href="http://bit.ly/2B6jpZl">Returns false to remove listener from future firings</a>
14  public delegate void Action(Emitter emitter);
15 
16  /// <a href="http://bit.ly/2B8WXPC">Fire once then dispose of the emitter</a>
17  public static Emitter SingleFireInstance {
18  get {
19  var emitter = Instance;
20  emitter.isSingleFire = true;
21  return emitter;
22  }
23  }
24  private bool isSingleFire;
25  #endregion
26 
27  #region Context
28  /// <a href="http://bit.ly/2RUcL2S">Retrieve the context as a class type - null for none or wrong type</a>
29  public T Context<T>() where T : class => context[typeof(T)].Value as T;
30 
31  /// <a href="http://bit.ly/2RUcL2S">Set the context to an instance of a type</a>
32  public Emitter Context<T>(T value) where T : class {
33  (context[typeof(T)].Value as IDisposable)?.Dispose();
34  context.Add(typeof(T), value);
35  return this;
36  }
37  /// <a href="http://bit.ly/2RUcL2S">Retrieve the context as a class type - null for none or wrong type</a>
38  public T Context<T>(string name) where T : class => context[name].Value as T;
39 
40  /// <a href="http://bit.ly/2RUcL2S">Set the context to an instance of a type</a>
41  public Emitter Context<T>(string name, T value) where T : class {
42  (context[name].Value as IDisposable)?.Dispose();
43  context.Add(name, value);
44  return this;
45  }
46  private readonly Map context = Map.Instance;
47  #endregion
48 
49  private readonly LinkedList<Action> listeners = new LinkedList<Action>();
50 
51  /// <a href="http://bit.ly/2B6jpZl">The owner shoots and all the listeners hear</a>
52  public void Fire() {
53  Firings++;
54  LinkedList<Action>.Node next;
55  for (node = listeners.First; node != null; node = next) {
56  next = node.Next;
57  node.Item(this);
58  }
59  if (isSingleFire) {
60  Firings = 0;
61  isSingleFire = false;
62  Dispose();
63  }
64  }
65 
66  /// <a href="http://bit.ly/2B6jpZl">Count of the number of times an emitter has fired</a>
67  public int Firings;
68 
69  /// <a href="http://bit.ly/2B6jpZl">Ask an emitter to tell me too</a>
70  public Emitter Listen(Action action) {
71  listeners.Add(action);
72  return this;
73  }
74 
75  /// <a href="http://bit.ly/2TpBXuR">Remove a listener if it is in the list</a>
76  public Emitter Remove(Action action) {
77  for (node = listeners.First; node != null; node = node.Next) {
78  if (node.Item != action) continue;
79  node.Recycle();
80  break;
81  }
82  return this;
83  }
84 
85  /// <a href="http://bit.ly/2Tn8xxq">Remove the listener currently being acted on</a>
87  node.Recycle();
88  return this;
89  }
90  private LinkedList<Action>.Node node;
91 
92  /// <a href="http://bit.ly/2B6jpZl">Removes all listeners</a>
93  public void RemoveAllListeners() {
94  listeners.Dispose();
95  Firings = 0;
96  }
97 
98  /// <a href="http://bit.ly/2B6jpZl">Return true if we have one or more listeners registered</a>
99  public bool Waiting => listeners.Count > 0;
100 
101  /// <a href="http://bit.ly/2B6jpZl">Call when we are done with this emitter.</a> <inheritdoc />
102  public void Dispose() {
104  (context as IDisposable)?.Dispose();
105  isSingleFire = false;
106  Cache<Emitter>.Dispose(this);
107  }
108 
109  public override string ToString() => $"Firings: {Firings}, Listeners: {listeners.Count}, Context: {context}";
110  }
111 }
Definition: Emitter.cs:6
static Emitter Instance
Retrieve an emitter from recycling or new
Definition: Emitter.cs:11
Emitter Listen(Action action)
Ask an emitter to tell me too
Definition: Emitter.cs:70
void RemoveAllListeners()
Removes all listeners
Definition: Emitter.cs:93
void Dispose()
Call when we are done with this emitter.
Definition: Emitter.cs:102
int Firings
Count of the number of times an emitter has fired
Definition: Emitter.cs:67
delegate void Action(Emitter emitter)
Returns false to remove listener from future firings
static Emitter SingleFireInstance
Fire once then dispose of the emitter
Definition: Emitter.cs:17
bool Waiting
Return true if we have one or more listeners registered
Definition: Emitter.cs:99
Emitter StopListening()
Remove the listener currently being acted on
Definition: Emitter.cs:86
void Fire()
The owner shoots and all the listeners hear
Definition: Emitter.cs:52
Cached C# Action instances using the observer pattern
Definition: Emitter.cs:8
Emitter Remove(Action action)
Remove a listener if it is in the list
Definition: Emitter.cs:76
T Context< T >()
Retrieve the context as a class type - null for none or wrong type