std.pattern.. templated publisher subscriber pattern, adding events to collections
Dmitry Olshansky
dmitry.olsh at gmail.com
Wed Jul 7 01:48:59 PDT 2010
On 07.07.2010 2:47, BLS wrote:
> Okay a bit better snippet than before. snippet should be almost
> functional..
>
> /*
> Hi,
> Andrei brings in the idea of std.pattern. Seems that this module is
> "stalled"; Unfortunately !
> However I would like to enhance collection classes (likewise
> dcollections) with a Publisher - Subscriber pattern (signal - slot, or
> observer pattern) , if you prefer)
> Hope the idea of enhancing collections with events become clear with the
> following snippet.
> !!! I am able to spend just a few hours a month with D programming.. in
> other words, please don't kill me :)
> Untested Draft code which requires a lot of help and ,more important,
> feedback from you.
>
> */
>
> struct publisherMsg(T) {
> T data;
> Action a;
> }
>
> mixin template Publisher(T) {
> private :
>
> enum Action = {INSERT, UPDATE, DELETE, READONLY};
> //alias typeof(this) PT;
>
> struct receiver {
> Object o;
> callback cb;
> }
>
> receiver[] subscriber;
>
> publisherMsg!(T) msg;
>
> alias void delegate(const ref msg) callback;
>
> void addSubscriber(object o, callback cb) {
> //subscriber ~= o;
> }
>
> void publish() {
Now where are arguments? kind of (T t,Action act)
> foreach (object o ; subscriber)
> {
> // create message and send message
>
> }
> }
The considerations are still the same :
foreach(c;subscriber)
c.callback(
see my erlier post
> }
>
> mixin template Subscriber() {
> // see UndoList for implementation
> }
>
> final class Stack(T, bool observable = false ) {
> T[] data;
>
> static if (observable) mixin Observable!T;
Yes, I think Observable is more appropriate then Publisher. Then maybe
methods should be:
addObserver instead of addSubscriber,
notify instead of publish?
But back to the whole idea - I'm sure you do not want to reimplement all
the shiny std.container.
What I think we basically need is universal wrapper for _any_ container
stuff.
let's call that Observable!Cont. Something like :
final class Observable(Cont){
Cont cont;
//here goes your current Publisher stuff
//...
alias Cont!ElementType T;
static if(__traits(compiles,cont.insert(T.init)))//some such ...
need to test if it has this method
{
size_t insert(Stuff)(Stuff s){//trouble is - we could insert
anything that converts to T
size_t n = cont.insert(s);
notify(cast!(T)s,Action.Insert);
}
}
//and all such stuff from std.continer.TotalContainer
//in theory could even be generated from phobos source
....
}
usage :
alias Observable!(Array!int) observableArray;
observableArray arr = [ 4,5,6]; //that would be nice
arr.addObserver( (ref msg m){ writeln("arr insertion:
",to!string(m.data,m.action));
arr.insert(42); //should print that fancy message
...
Yes, I still think that plain delegates approach is more flexible and
straightforward (see my earlier post).
>
> void push( T t) {
> data ~= t;
> publish(t, Action.INSERT);
> }
> T pop() {
> publish(t, Action.DELETE);
> //...
> }
> bool empty() {
>
> }
> T top() {
> publish(t, Action.READONLY);
> //...
> }
> size_t size() {
>
> }
> }
> // Undo list will receive every pushed or popped item -data and action)
> class UndoList(T) {
> private:
> T[] data;
>
> /// should be part of the sunscriber mixin templates.
> publisherMsg!T stackMessage;
>
> void delegate(const ref stackMessage) dg;
>
> alias Stack!(int) IntegerStack;
>
> IntegerStack intstack = new IntegerStack;
>
> private this() {
> dg = &this.feedback;
>
> // SUBBSCRIBE Stack(T) push and pop events.
> intstack.addSubscriber(this, dg);
Again from my POV it could be:
intstack.addSubcriber(
(const ref stackMessage msg){ feedback(msg); }
);
//somewhat scary in this case, but in fact it does not restrict you to
class instances.
>
> }
> public void feedback(const ref stackMessage msg ) {
> writefln("Action");
> }
> }
BTW I'm definitely interesed in this effort, and in fact want that kind
of functionality for my upcoming gui lib.
It all just needs to be more reusable and flexible.
--
Dmitry Olshansky
More information about the Digitalmars-d-learn
mailing list