Skip to content

Commit c5bc13a

Browse files
committed
v5.0.0 - dispatchTime on all Callbacks
- Added `dispatchTime: DispatchTime` on all Callbacks, and providing this value on all Callback invocations. - Version will bump up to 5.0.0 to reflect this interface-breaking change - README.md updated to reflect new changes
1 parent 84039f5 commit c5bc13a

File tree

11 files changed

+44
-42
lines changed

11 files changed

+44
-42
lines changed

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ let package = Package(
130130
dependencies: [
131131
.package(
132132
url: "https://github.com/Flowduino/EventDrivenSwift.git",
133-
.upToNextMajor(from: "4.2.0")
133+
.upToNextMajor(from: "5.0.0")
134134
),
135135
],
136136
//...
@@ -217,7 +217,7 @@ class TemperatureProcessor: EventThread {
217217
}
218218

219219
/// Define our Callback Function to process received TemperatureEvent Events
220-
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority) {
220+
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
221221

222222
}
223223
}
@@ -230,6 +230,8 @@ The function `registerEventListeners` will be called automatically when an insta
230230

231231
Our *Callback* (or *Handler* or *Listener Event*) is called `onTemperatureEvent`, which is where we will implement whatever *Operation* is to be performed against a `TemperatureEvent`.
232232

233+
Version 5.0.0 introduces the new parameter, `dispatchTime`, which will always provide the `DispatchTime` reference at which the *Event* was *Dispatched*. You can use this to determine *Delta* (how much time has passed since the *Event* was *Dispatched*), which is particularly useful if you are performing interpolation and/or extrapolation.
234+
233235
Now, let's actually do something with our `TemperatureEvent` in the `onTemperatureEvent` method.
234236
```swift
235237
/// An Enum to map a Temperature value onto a Rating
@@ -262,7 +264,7 @@ Now, let's actually do something with our `TemperatureEvent` in the `onTemperatu
262264
@ThreadSafeSemaphore public var temperatureInCelsius: Float = Float.zero
263265
@ThreadSafeSemaphore public var temperatureRating: TemperatureRating = .freezing
264266

265-
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority) {
267+
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
266268
temperatureInCelsius = event.temperatureInCelsius
267269
temperatureRating = TemperatureRating.fromTemperature(event.temperatureInCelsius)
268270
}
@@ -315,7 +317,7 @@ protocol TemperatureProcessorObserver: AnyObject {
315317
```
316318
Now let's modify the `onTemperatureEvent` method we implemented in the previous example:
317319
```swift
318-
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority) {
320+
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
319321
temperatureInCelsius = event.temperatureInCelsius
320322
temperatureRating = TemperatureRating.fromTemperature(event.temperatureInCelsius)
321323

@@ -343,7 +345,7 @@ enum TemperatureRatingEvent: Eventable {
343345
```
344346
With the *Event* type defined, we can now once more expand our `onTemperatureEvent` to *Dispatch* our reciprocal `TemperatureRatingEvent`:
345347
```swift
346-
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority) {
348+
func onTemperatureEvent(_ event: TemperatureEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
347349
temperatureInCelsius = event.temperatureInCelsius
348350
temperatureRating = TemperatureRating.fromTemperature(event.temperatureInCelsius)
349351

@@ -385,7 +387,7 @@ class TemperatureRatingViewModel: ObservableObject {
385387

386388
var listenerHandle: EventListenerHandling?
387389

388-
internal func onTemperatureRatingEvent(_ event: TemperatureRatingEvent, _ priority: EventPriority) {
390+
internal func onTemperatureRatingEvent(_ event: TemperatureRatingEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
389391
temperatureInCelsius = event.temperatureInCelsius
390392
temperatureRating = event.temperatureRating
391393
}
@@ -438,7 +440,7 @@ class TemperatureRatingViewModel: ObservableObject {
438440

439441
var listenerHandle: EventListenerHandling?
440442

441-
internal func onTemperatureRatingEvent(_ event: TemperatureRatingEvent, _ priority: EventPriority) {
443+
internal func onTemperatureRatingEvent(_ event: TemperatureRatingEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) {
442444
temperatureInCelsius = event.temperatureInCelsius
443445
temperatureRating = event.temperatureRating
444446
}
@@ -480,9 +482,8 @@ The above example would use the `EventPoolLowestLoadBalancer` implementation, wh
480482
## Features Coming Soon
481483
`EventDrivenSwift` is an evolving and ever-improving Library, so here are lists of the features you can expect in future releases.
482484

483-
Version 4.3.0 (or 5.0.0 if interface-breaking changes are required):
484-
- **Event Pool Scalers** - Dynamic Scaling for `EventPool` instances will be fully-implemented
485-
- **Latest-Only Events** - A Dispatch option to replace any unprocessed (older) *Events* with the newest *Event* of that specific *Eventable* type. This will be useful for things like sensor readings, where you only care about the most recent value possible (because older values are no longer relevant)
485+
Version 5.1.0 (or 6.0.0 if interface-breaking changes are required):
486+
- **Event Pool Scalers** - Dynamic Scaling for `EventPool` instances will be fully-implemented (for the moment, no automatic Scaling will occur, and you cannot change the scale of an *Event Pool* once it has been initialised)
486487

487488
## License
488489

Sources/EventDrivenSwift/Event/Wrappers/EventListeners.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
import Foundation
10-
10+
/*
1111
public protocol EventListenerCallbackContainer {
1212
associatedtype TEventType: Eventable
1313

@@ -35,3 +35,4 @@ public struct EventListeners<TOwner: AnyObject> {
3535
return results
3636
}
3737
}
38+
*/

Sources/EventDrivenSwift/Event/Wrappers/EventMethod.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import Foundation
1010

11-
public typealias EventMethodTypedEventCallback<TOwner: AnyObject, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority) -> ()
11+
public typealias EventMethodTypedEventCallback<TOwner: AnyObject, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) -> ()
1212

1313
/**
1414
Any Property wrapped with `EventMethod` will automatically conform to `EventMethodContainer`
@@ -28,7 +28,7 @@ public protocol EventMethodContainer {
2828
/**
2929
Decorate Typed Event Callback Closures as `var` with `@EventMethod<TEventType>` to automatically register them.
3030
- Author: Simon J. Stuart
31-
- Version: 4.1.0
31+
- Version: 5.0.0
3232
*/
3333
@propertyWrapper
3434
public struct EventMethod<TOwner: AnyObject, TEventType: Eventable>: EventMethodContainer {
@@ -37,9 +37,9 @@ public struct EventMethod<TOwner: AnyObject, TEventType: Eventable>: EventMethod
3737

3838
private weak var owner: AnyObject? = nil
3939

40-
private func callback(event: TEventType, priority: EventPriority) {
40+
private func callback(event: TEventType, priority: EventPriority, dispatchTime: DispatchTime) {
4141
if let typedOwner = owner as? TOwner {
42-
wrappedValue?(typedOwner, event, priority)
42+
wrappedValue?(typedOwner, event, priority, dispatchTime)
4343
}
4444
}
4545

Sources/EventDrivenSwift/EventListener/EventListenable.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import Foundation
1313
- Author: Simon J. Stuart
1414
- Version: 3.0.0
1515
*/
16-
public typealias EventCallback = (_ event: any Eventable, _ priority: EventPriority) -> ()
16+
public typealias EventCallback = (_ event: any Eventable, _ priority: EventPriority, _ dispatchTime: DispatchTime) -> ()
1717

1818
/**
1919
Convienience `typealias` used for Typed Event Callbacks
2020
- Author: Simon J. Stuart
2121
- Version: 3.0.0
2222
*/
23-
public typealias TypedEventCallback<TEvent: Any> = (_ event: TEvent, _ priority: EventPriority) -> ()
23+
public typealias TypedEventCallback<TEvent: Any> = (_ event: TEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) -> ()
2424

2525
public enum ExecuteEventOn {
2626
/**

Sources/EventDrivenSwift/EventListener/EventListener.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,23 @@ open class EventListener: EventHandler, EventListenable {
7373
Task { // We raise a Task because we don't want the entire Listener blocked in the event the dispatchQueue is busy or blocked!
7474
let dispatchQueue = listener.dispatchQueue ?? DispatchQueue.main
7575
dispatchQueue.async {
76-
listener.callback(event.event, priority)
76+
listener.callback(event.event, priority, event.dispatchTime)
7777
}
7878
}
7979
case .listenerThread:
80-
listener.callback(event.event, priority)
80+
listener.callback(event.event, priority, event.dispatchTime)
8181
case .taskThread:
8282
Task {
83-
listener.callback(event.event, priority)
83+
listener.callback(event.event, priority, event.dispatchTime)
8484
}
8585
}
8686
}
8787
}
8888

8989
@discardableResult public func addListener<TEvent: Eventable>(_ requester: AnyObject?, _ callback: @escaping TypedEventCallback<TEvent>, forEventType: Eventable.Type, executeOn: ExecuteEventOn = .requesterThread, interestedIn: EventListenerInterest = .all) -> EventListenerHandling {
9090
let eventTypeName = forEventType.getEventTypeName()
91-
let method: EventCallback = { event, priority in
92-
self.callTypedEventCallback(callback, forEvent: event, priority: priority)
91+
let method: EventCallback = { event, priority, dispatchTime in
92+
self.callTypedEventCallback(callback, forEvent: event, priority: priority, dispatchTime: dispatchTime)
9393
}
9494
let eventListenerContainer = EventListenerContainer(requester: requester, callback: method, dispatchQueue: OperationQueue.current?.underlyingQueue, executeOn: executeOn, interestedIn: interestedIn)
9595
_eventListeners.withLock { eventCallbacks in
@@ -157,9 +157,9 @@ open class EventListener: EventHandler, EventListenable {
157157
- forEvent: The instance of the `Eventable` type to be processed
158158
- priority: The `EventPriority` with which the `forEvent` was dispatched
159159
*/
160-
internal func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority) {
160+
internal func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority, dispatchTime: DispatchTime) {
161161
if let typedEvent = forEvent as? TEvent {
162-
callback(typedEvent, priority)
162+
callback(typedEvent, priority, dispatchTime)
163163
}
164164
}
165165
}

Sources/EventDrivenSwift/EventThread/EventThread.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public protocol ThreadEventMethodContainer {
3232
- Note: Inherit from this to implement a discrete unit of code designed specifically to operate upon specific `Eventable` types containing information useful to its operation(s)
3333
*/
3434
open class EventThread: EventReceiver, EventThreadable {
35-
public typealias EventMethodTypedEventCallback<TOwner: EventThread, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority) -> ()
35+
public typealias EventMethodTypedEventCallback<TOwner: EventThread, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority, _ dispatchTime: DispatchTime) -> ()
3636

3737
/**
3838
Property Wrapper to simplify the registration of Event Callbacks in `EventThread`-inheriting types.
@@ -54,9 +54,9 @@ open class EventThread: EventReceiver, EventThreadable {
5454

5555
private weak var owner: AnyObject? = nil
5656

57-
@inline(__always) private func callback(event: TEventType, priority: EventPriority) {
57+
@inline(__always) private func callback(event: TEventType, priority: EventPriority, dispatchTime: DispatchTime) {
5858
if let typedOwner = owner as? TOwner {
59-
wrappedValue?(typedOwner, event, priority)
59+
wrappedValue?(typedOwner, event, priority, dispatchTime)
6060
}
6161
}
6262

@@ -139,7 +139,7 @@ open class EventThread: EventReceiver, EventThreadable {
139139
if callbackContainer == nil { return } // If there is no Callback, we will just return!
140140

141141
for callback in callbackContainer! {
142-
callback.callback(event.event, priority)
142+
callback.callback(event.event, priority, event.dispatchTime)
143143
}
144144
}
145145

@@ -163,8 +163,8 @@ open class EventThread: EventReceiver, EventThreadable {
163163
bucket = [EventCallbackContainer]()
164164
}
165165

166-
callbackContainer = EventCallbackContainer(callback: { event, priority in
167-
self.callTypedEventCallback(callback, forEvent: event, priority: priority)
166+
callbackContainer = EventCallbackContainer(callback: { event, priority, dispatchTime in
167+
self.callTypedEventCallback(callback, forEvent: event, priority: priority, dispatchTime: dispatchTime)
168168
}, eventType: forEventType)
169169

170170
bucket!.append(callbackContainer!)
@@ -192,9 +192,9 @@ open class EventThread: EventReceiver, EventThreadable {
192192
- forEvent: The instance of the `Eventable` type to be processed
193193
- priority: The `EventPriority` with which the `forEvent` was dispatched
194194
*/
195-
@inline(__always) open func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority) {
195+
@inline(__always) open func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority, dispatchTime: DispatchTime) {
196196
if let typedEvent = forEvent as? TEvent {
197-
callback(typedEvent, priority)
197+
callback(typedEvent, priority, dispatchTime)
198198
}
199199
}
200200

Sources/EventDrivenSwift/UIEventThread/UIEventThread.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ open class UIEventThread: EventThread, UIEventThreadable {
2525
}
2626
}
2727

28-
override open func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority) {
28+
override open func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority, dispatchTime: DispatchTime) {
2929
Task { /// Have to use a Task because this method is not `async`
3030
await MainActor.run { /// Forces the call to be invoked on the `MainActor` (UI Thread)
31-
super.callTypedEventCallback(callback, forEvent: forEvent, priority: priority)
31+
super.callTypedEventCallback(callback, forEvent: forEvent, priority: priority, dispatchTime: dispatchTime)
3232
}
3333
}
3434
}

Tests/EventDrivenSwiftTests/BasicEventListenerTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ final class BasicEventListenerTests: XCTestCase, EventListening {
1818
var bar: String
1919
}
2020

21-
@EventMethod<BasicEventListenerTests, TestEventTypeOne>(executeOn: .taskThread) var event1 = { (self, event: TestEventTypeOne, priority: EventPriority) in
21+
@EventMethod<BasicEventListenerTests, TestEventTypeOne>(executeOn: .taskThread) var event1 = { (self, event: TestEventTypeOne, priority: EventPriority, dispatchTime: DispatchTime) in
2222
self.doTestEvent(event: event, priority: priority)
2323
}
2424

2525
func doTestEvent(event: TestEventTypeOne, priority: EventPriority) {
2626
print("onTestEvent: foo = \(event.foo)")
2727
}
2828

29-
@EventMethod<BasicEventListenerTests, TestEventTypeTwo>(executeOn: .taskThread) var event2 = { (self, event: TestEventTypeTwo, priority: EventPriority) in
29+
@EventMethod<BasicEventListenerTests, TestEventTypeTwo>(executeOn: .taskThread) var event2 = { (self, event: TestEventTypeTwo, priority: EventPriority, dispatchTime: DispatchTime) in
3030
self.doTestEventTwo(event: event, priority: priority)
3131
}
3232

@@ -43,7 +43,7 @@ final class BasicEventListenerTests: XCTestCase, EventListening {
4343
registerListeners()
4444
XCTAssertEqual(myFoo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(myFoo)")
4545

46-
listenerHandler = TestEventTypeOne.addListener(self, { (event: TestEventTypeOne, priority) in
46+
listenerHandler = TestEventTypeOne.addListener(self, { (event: TestEventTypeOne, priority, dispatchTime) in
4747
self.myFoo = event.foo
4848
self.awaiter.signal()
4949
}, executeOn: .listenerThread)
@@ -63,7 +63,7 @@ final class BasicEventListenerTests: XCTestCase, EventListening {
6363
// registerListeners()
6464
XCTAssertEqual(myFoo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(myFoo)")
6565

66-
listenerHandler = TestEventTypeOne.addListener(self, { (event: TestEventTypeOne, priority) in
66+
listenerHandler = TestEventTypeOne.addListener(self, { (event: TestEventTypeOne, priority, dispatchTime) in
6767
self.myFoo = event.foo
6868
self.awaiter.signal()
6969
}, executeOn: .taskThread)

Tests/EventDrivenSwiftTests/BasicEventPoolTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class BasicEventPoolTests: XCTestCase {
3131
class PoolTestingThread: EventThread {
3232
override func registerEventListeners() {
3333
addEventCallback(
34-
{ (event: PoolTestingEvent, priority) in
34+
{ (event: PoolTestingEvent, priority, dispatchTime) in
3535
Thread.sleep(forTimeInterval: 5)
3636
PoolTestStatic.setValue(index: event.index, value: event.value)
3737
Thread.sleep(forTimeInterval: 5)

Tests/EventDrivenSwiftTests/BasicEventSchedulingTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class BasicEventSchedulingTests: XCTestCase {
1919
private var executed: DispatchTime? = nil
2020

2121
func testPerformanceExample() throws {
22-
TestEvent.addListener(self, { (event: TestEvent, priority) in
22+
TestEvent.addListener(self, { (event: TestEvent, priority, dispatchTime) in
2323
print("TestEvent where foo = \(event.foo)")
2424
self.testValue = event.foo
2525
self.executed = DispatchTime.now()

0 commit comments

Comments
 (0)