-
Notifications
You must be signed in to change notification settings - Fork 0
/
Signal.ts
148 lines (122 loc) · 3.18 KB
/
Signal.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Packages
import {FreeArray} from "./FreeArray.ts";
// Connection Types
type DefaultCallback = () => void
// deno-lint-ignore no-explicit-any
type Callback = (...args: any[]) => void
export type CallbackDefinition = Callback
type SignalConnectionReferences = FreeArray<
{
Callback: Callback;
Connection: Connection;
}
>
// Classes
class Connection {
// Private Properties
private ConnectionReferences: SignalConnectionReferences
private Location: string
private Disconnected: boolean
// Constructor
constructor(connections: SignalConnectionReferences, callback: Callback) {
// Store our signal/callback
this.ConnectionReferences = connections
// Store our initial disconnected state
this.Disconnected = false
// Now store ourselves
this.Location = connections.Push(
{
Callback: callback,
Connection: this
}
)
}
// Public Methods
public Disconnect() {
// Make sure we aren't already disconnected
if (this.Disconnected) {
return
}
// Disconnect ourself
this.Disconnected = true
// Remove ourselves from our signal
this.ConnectionReferences.Remove(this.Location)
}
public IsDisconnected() {
return this.Disconnected
}
}
class Event<P extends Callback = DefaultCallback> {
// Private Properties
private Signal: Signal<P>
// Constructor
constructor(signal: Signal<P>) {
// Store our signal
this.Signal = signal
}
// Public Methods
public Connect(callback: P) {
return this.Signal.Connect(callback)
}
public IsDestroyed() {
return this.Signal.IsDestroyed()
}
}
class Signal<P extends Callback = DefaultCallback> {
// Private Properties
private ConnectionReferences: SignalConnectionReferences
private DestroyedState: boolean
// Constructor
constructor() {
// Create our list of connections
this.ConnectionReferences = new FreeArray()
// Store our initial destroyed state
this.DestroyedState = false
}
// Public Methods
public Connect(callback: P): Connection {
// Make sure we aren't destroyed
if (this.DestroyedState) {
throw('Cannot connect to a Destroyed Signal')
}
// Return our connection (since the connection handles everything itself)
return new Connection(this.ConnectionReferences, callback)
}
public Fire(...args: Parameters<P>) {
// Make sure we aren't destroyed
if (this.DestroyedState) {
throw('Cannot fire a Destroyed Signal')
}
// Loop through all of our connections
for (const [_, reference] of this.ConnectionReferences.GetIterator()) {
// Fire our callback
reference.Callback(...args)
}
}
public GetEvent(): Event<P> {
// Return our event
return new Event(this)
}
public IsDestroyed() {
return this.DestroyedState
}
// Deconstructor
public Destroy() {
// Make sure we aren't already destroyed
if (this.DestroyedState) {
return
}
// Disconnect all of our connections (so that the connection is labeled as Disconnected)
for (const [_, reference] of this.ConnectionReferences.GetIterator()) {
reference.Connection.Disconnect()
}
// Disconnect ourself
this.DestroyedState = true
}
}
// Exports
export type {Event, Connection}
export const IsConnection = (value: unknown): value is Connection => {
return (value instanceof Connection)
}
export {Signal}