78
78
79
79
]]
80
80
81
- local c_running = coroutine.running
82
- local c_yield = coroutine.yield
83
- local t_defer = task .defer
84
- local t_desynchronize = task .desynchronize
85
-
86
81
local ERROR_ON_ALREADY_DISCONNECTED = false
87
82
88
83
local Signal = {}
@@ -91,64 +86,66 @@ Signal.__index = Signal
91
86
local Connection = {}
92
87
Connection .__index = Connection
93
88
89
+ function Signal :__call (_ , ...)
90
+ if not self :IsActive () then
91
+ return
92
+ end
93
+
94
+ return self :Connect (... )
95
+ end
96
+
94
97
function Signal .new ()
95
98
local self = setmetatable ({
96
- [ 1 ] = nil , -- _head
97
- [ 2 ] = true -- _active
99
+ _active = true ,
100
+ _head = nil
98
101
}, Signal )
99
102
100
103
return self
101
104
end
102
105
103
106
function Signal :IsActive ()
104
- return self [ 2 ] == true
107
+ return self . _active == true
105
108
end
106
109
107
- local function Connect (self , func , self_disconnects )
110
+ function Signal :Connect (func )
111
+ assert (
112
+ typeof (func ) == ' function' ,
113
+ " :Connect must be called with a function"
114
+ )
115
+
108
116
if not self :IsActive () then
109
117
return setmetatable ({
110
118
Connected = false
111
119
}, Connection )
112
120
end
113
121
114
- local _head = self [1 ]
115
-
116
122
local connection = setmetatable ({
117
123
Connected = true ,
118
- [1 ] = func , -- _func
119
- [2 ] = self , -- _signal
120
- [3 ] = _head , -- _next
121
- [4 ] = nil , -- _prev
122
- [5 ] = self_disconnects -- _self_disconnects
124
+ _func = func ,
125
+ _signal = self ,
126
+ _next = nil ,
127
+ _prev = nil
123
128
}, Connection )
124
129
130
+ local _head = self ._head
125
131
if _head ~= nil then
126
- _head [ 4 ] = connection -- _head ._prev = connection
127
- connection [ 3 ] = _head -- connection ._next = _head
132
+ _head ._prev = connection
133
+ connection ._next = _head
128
134
end
129
135
130
- self [ 1 ] = connection -- _head = connection
136
+ self . _head = connection
131
137
132
138
return connection
133
139
end
134
140
135
- function Signal :Connect (func )
136
- assert (
137
- typeof (func ) == ' function' ,
138
- " :Connect must be called with a function"
139
- )
140
-
141
- return Connect (self , func )
142
- end
143
-
144
141
function Signal :ConnectParallel (func )
145
142
assert (
146
143
typeof (func ) == ' function' ,
147
144
" :ConnectParallel must be called with a function"
148
145
)
149
146
150
- return Connect (self , function (...)
151
- t_desynchronize ()
147
+ return self : Connect (function (...)
148
+ task . desynchronize ()
152
149
func (... )
153
150
end )
154
151
end
@@ -164,37 +161,48 @@ function Connection:Disconnect()
164
161
165
162
self .Connected = false
166
163
167
- local _next = self [ 3 ]
168
- local _prev = self [ 4 ]
164
+ local _next = self . _next
165
+ local _prev = self . _prev
169
166
170
167
if _next ~= nil then
171
- _next [ 4 ] = _prev -- _next ._prev = _prev
168
+ _next ._prev = _prev
172
169
end
173
170
174
171
if _prev ~= nil then
175
- _prev [ 3 ] = _next -- _prev ._next = _next
172
+ _prev ._next = _next
176
173
else
177
174
-- \\ This connection was the _head,
178
175
-- therefore we need to update the head
179
176
-- to the connection after this one.
180
177
181
- self [ 2 ][ 1 ] = _next -- self ._signal._head = _next
178
+ self ._signal ._head = _next
182
179
end
183
180
184
181
-- \\ Safe to wipe references to:
185
182
186
- self [ 2 ] = nil
187
- self [ 4 ] = nil
183
+ self . _signal = nil
184
+ self . _prev = nil
188
185
end
189
186
190
187
function Signal :Wait ()
191
- Connect (
192
- self ,
193
- c_running (),
194
- true
195
- )
188
+ if not self :IsActive () then
189
+ warn (" Tried to :Wait on destroyed signal" )
190
+ return
191
+ end
192
+
193
+ local thread = coroutine.running ()
194
+
195
+ local connection
196
+ connection = self :Connect (function (...)
197
+ connection :Disconnect ()
196
198
197
- return c_yield ()
199
+ task .spawn (
200
+ thread ,
201
+ ...
202
+ )
203
+ end )
204
+
205
+ return coroutine.yield ()
198
206
end
199
207
200
208
function Signal :Fire (...)
@@ -203,54 +211,38 @@ function Signal:Fire(...)
203
211
return
204
212
end
205
213
206
- local connection = self [ 1 ]
214
+ local connection = self . _head
207
215
while connection ~= nil do
208
- t_defer (
209
- connection [ 1 ] ,
216
+ task . defer (
217
+ connection . _func ,
210
218
...
211
219
)
212
-
213
- if connection [5 ] then
214
- -- If connection is one-fire only:
215
- connection :Disconnect ()
216
- end
217
220
218
- connection = connection [ 3 ] -- > _next
221
+ connection = connection . _next
219
222
end
220
223
end
221
224
222
225
function Signal :DisconnectAll ()
223
- local connection = self [ 1 ] -- _head
226
+ local connection = self . _head
224
227
while connection ~= nil do
228
+ -- connection:Disconnect()
229
+
225
230
connection .Connected = false
226
- connection [ 2 ] = nil -- _signal = nil
227
- connection [ 4 ] = nil -- _prev = nil
231
+ connection . _prev = nil
232
+ connection . _signal = nil
228
233
229
- connection = connection [ 3 ] -- > _next
234
+ connection = connection . _next
230
235
end
231
- self [ 1 ] = nil -- _head = nil
236
+ self . _head = nil
232
237
end
233
238
234
239
function Signal :Destroy ()
235
240
if not self :IsActive () then
236
241
return
237
242
end
238
243
239
- self [ 2 ] = false
244
+ self . _active = false
240
245
self :DisconnectAll ()
241
246
end
242
247
243
- function Signal :__call (_ , func )
244
- if not self :IsActive () then
245
- return
246
- end
247
-
248
- assert (
249
- typeof (func ) == ' function' ,
250
- " :Connect must be called with a function"
251
- )
252
-
253
- return Connect (self , func )
254
- end
255
-
256
248
return Signal
0 commit comments