events ~master
Event Object Model
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
events for D
events is an Event Object Model for the D programming language, with elegant design and beautiful syntax sugar.
How it works
events.d main goal is to allow subscription of multiple delegates with the same signature to a List. A trigger is then used to call the list of subscribed delegates.
Triggers
Every event list must be owned by a caller using the method EventsList.own
, the call will only work the first time so the best practice is to own the
event list right after instantiation.
auto event = new EventList!void;
auto trigger = event.own;
The trigger objects works like a function to call all the subscribed delegates.
trigger();
Subscription
Subscription is performed by the addSync
method:
event.addSync({
"first subscription".writeln;
});
The same operation can be performed with syntax sugar:
event ^ {
"first subscription".writeln;
};
Unsubscription
Unsubscription or removal of delegates from the event list can be achieved with the method remove
. The same instance of the delegate subscribed must be provided in order to properly perform the removal.
auto myDelegate = delegate int {
return 3000;
};
list ^ myDelegate;
list.remove(myDelegate) // trigger.count will now reporting one less subscription
Owners can use the method Trigger.reset
to unsubscribe all the delegates from the event.
Return Value
The first type of the EventList template is the return type, it's required even if the type is void
:
auto event = new EventList!void;
The return type is reflected in the signature of the call and the delegates:
auto event = new EventList!int;
auto trigger = event.own;
event ^ {
return 20;
};
int value = trigger(); // value = 20
Parameters
The types next to the return type belong to the parameters of the delegate:
auto mult = new EventList!(int, float);
auto trigger = mult.own;
mult ^ (base) {
return base * 3;
};
int value = trigger(20.0); // value = 60
Advanced: Fibers
Subscribers can use the method addAsync
or the operator ^^
to subscribe a delegate which executes in it's own fiber Fiber. Inside the delegate, you can capture the current Fiber using Fiber.getThis part of the standard module core.thread.
import core.thread;
...
auto event = new EventList!(string, int);
auto trigger = event.own;
event ^^ (age) {
return "third age is %d in Fiber %s".format(age, Fiber.getThis);
};
auto text = trigger(30);
text.writeln;
Advanced: Watching Changes
The trigger can provide notifications to the owner about the operation beign performed in the event list:
trigger.changed = (EventOperation op, item) {
if(op == EventOperation.Added) {
"new delegate subscribed".writeln;
} else if(op == EventOperation.Removed) {
"new delegate unsubscribed".writeln;
}
"%s %s".format(op, item).writeln;
};
Advanced: Activation
All events are considered active once the first delegate is subscribed to the event.
Events owners can provide a delegate to the method own
to perform actions when the event changes it's activation state.
The main difference between the activation delegate (also setteable via Trigger.activation
) and the changes delegate (Trigger.changed
)
is that the changes delegates is executed unconditionally when a delegate is subscribed or unsubscribed to the event, unlike Trigger.activation
which is only triggered under the following scenarios:
Active : The event just went from 0 subscribers to 1 subscriber.
Inactive: The event just went from 1 subscriber to 0 subscribers.
Example:
auto trigger = list.own((trigger, activated) {
if(activated) {
"first delegate subscribed".writeln;
} else {
"no more delegates subscribed".writeln;
}
});
Advanced: Actions
An action is an event that get's activated everytime a new delegate is subscribed to the action. Since actions are mostly intended to be returned by functions using closures, the subscription usually happens only one time in the lifetime of the action. A user-defined handler must be given to the action to receive the instance of the delegate that activated the action which can be fired multiple times as needed.
Example:
auto foo = function Action!(void, int)(int max) {
auto action = new Action!(void, int)((trigger) {
for(int i = 0; i < max; i++) {
trigger(i);
}
});
return action;
};
int values;
foo(5) ^= (i) {
values+=i;
};
assert(values == 10);
The sintax sugar to subscribe in the same fiber is ^=
and ^^=
for fibered subscriptions.
Advanced: Execution Strictness
Both classes EventList
and Action
allow users to use addSync
or addAsync
at will, however, there are scenarios where the author of the event/actions wants to enforce certain execution mode for subscriptions.
The classes StrictEventList
and StrictAction
allow authors enforce the execution type for the subscribers.
Example of strictly Asynchronous Action:
StrictAction!(StrictTrigger.Async, void) asyncAction;
...
asyncAction.addAsync({}); // OK
asyncAction ^^= {}; // OK
asyncAction.addSync({}); // ERROR: fails to compile
asyncAction ^= {}; // ERROR: fails to compile
Example of strictly Synchronous Action:
StrictAction!(StrictTrigger.Sync, void) syncAction;
...
syncAction.addAsync({}); // ERROR: fails to compile
syncAction ^^= {}; // ERROR: fails to compile
syncAction.addSync({}); // OK
syncAction ^= {}; // OK
Example of strictly Asynchronous Event:
StrictEventList!(StrictTrigger.Async, void) asyncEvent;
...
asyncEvent.addAsync({}); // OK
asyncEvent ^^ {}; // OK
asyncEvent.addSync({}); // ERROR: fails to compile
asyncEvent ^ {}; // ERROR: fails to compile
Example of strictly Asynchronous Event:
StrictEventList!(StrictTrigger.Sync, void) syncEvent;
...
syncEvent.addAsync({}); // ERROR: fails to compile
syncEvent ^^ {}; // ERROR: fails to compile
syncEvent.addSync({}); // OK
syncEvent ^ {}; // OK
Building
git clone https://github.com/heapsource/events.d.git
make
You can set the env variable DEBUG=1 to enable compilation with debugging capabilities.
DEBUG=1 make
Examples
Use make examples
to compile all the examples. Executables will be generated in the directory out/
.
Test
make tests
License (MIT)
Copyright (c) 2013, 2014 Heapsource.com - http://www.heapsource.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ~master released 10 years ago
- heapsource/events.d
- github.com/heapsource/events.d
- MIT
- Copyright © 2013, 2014, Heapsource.com
- Authors:
- Dependencies:
- none
- Versions:
-
0.1.1 2014-Feb-16 ~master 2014-Feb-16 - Download Stats:
-
-
0 downloads today
-
0 downloads this week
-
0 downloads this month
-
352 downloads total
-
- Score:
- 1.4
- Short URL:
- events.dub.pm