std.pattern.. templated publisher subscriber pattern, adding events to collections

Jacob Carlborg doob at me.com
Wed Jul 7 03:54:39 PDT 2010


On 2010-07-07 10.48, Dmitry Olshansky wrote:
> 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.

I think it would be nice to simulate the events in C#. It's quite easy, 
just a struct containing a linked list of delegates, a function to call 
all the delegates and functions to add and remove delegates from the list.


-- 
Jacob Carlborg


More information about the Digitalmars-d-learn mailing list