Signals far from Slots

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon May 5 15:19:48 PDT 2014


On 05/04/2014 10:57 AM, Jim Hewes wrote:
> Is there a good way to connect signals and slots when the objects are
> far apart? All tutorials for signals and slots show the objects being
> readily accessible by the main() function. But what if they're not? Is
> there an elegant design?
>
> For example, here's a typical minimal demo:
>
> ---------------------------------------------------------
> class Foo
> {
>      void Listen()
>      {
>          writeln("Foo: I hear you!");
>      }
> }
>
> class Bar
> {
>      mixin Signal!() barSignal;
>      void SaySomething()
>      {    emit();   }
> }
>
> int main(string[] argv)
> {
>      Foo f = new Foo();
>      Bar b = new Bar();
>
>      b.barSignal.connect(&f.Listen);
>      b.SaySomething();
>      return 0;
> }
> ---------------------------------------------------------------
>
> The main() function is a kind of controller that connects up the
> components. But let's say main() doesn't have access to Bar because it's
> behind a layer:
>
> ------------------------------------------------------------------
>
> class BarContainer
> {
>      this() { b = new Bar(); }
>
>      void SetBarSignalHandler(b.barSignal.slot_t dg)
>      {    b.barSignal.connect(dg);  }
>
>      private Bar b;
> };
>
> int main(string[] argv)
> {
>      Foo f = new Foo();
>      BarContainer bc = new BarContainer();
>
>      bc.SetBarSignalHandler(&f.Listen);
>      return 0;
> }
> ------------------------------------------------------------------
> This can get worse if there is also a FooContainer and objects get
> further away.
>
> My first thought is to pass the delegates through the layers, as in the
> SetBarSignalHandler() function in BarContainer. But this seems kind of
> ugly as all the layers need to know about the connection between the
> signaling object and the observer object. It would be nice if they
> didn't have to.
>
> Do you know any any cleaner way?
>
> Jim

As far as I understand, you have to expose a function on BarContainer 
similar to SaySomething() (I named it SaySomething() as well :) ):

import std.stdio;
import std.signals;

class Foo
{
     void Listen()
     {
         writeln("Foo: I hear you!");
     }
}

class Bar
{
     mixin Signal!() barSignal;
     void SaySomething()
     {    emit();   }
}

class BarContainer
{
     this() { b = new Bar(); }

     void SetBarSignalHandler(b.barSignal.slot_t dg)
     {    b.barSignal.connect(dg);  }

     void SaySomething()    // <== ADDED
     {
         b.emit();
     }

     private Bar b;
}

int main(string[] argv)
{
     Foo f = new Foo();
     BarContainer bc = new BarContainer();

     bc.SetBarSignalHandler(&f.Listen);
     bc.SaySomething();    // <== ADDED

     return 0;
}

Ali



More information about the Digitalmars-d-learn mailing list