Re: Defining event handlers for function, method, or shared method

2016-01-26 Thread Ali Çehreli via Digitalmars-d-learn

On 01/26/2016 11:42 AM, tcak wrote:

>> struct S {
>> void memberFunction() {
>> }
>> }
>> auto s = S();
>>
>> auto memberClosure(ref S s) {
>> return () => s.memberFunction();
>> }
>>
>> events ~= new ConcreteEvent!(() => memberClosure(s),
>>  () => writeln("stop"),
>>  bar);
>>
>> events.each!(e => e.stop);
>> }
>>
>> Ali

> Hmm. Your example works fine for functions, but I can't pass a method
> instead of function as alias.

That's why I used a closure in the example.

> Check my example:
>
>
> import std.socket;
>
> class EventClass{
>  public void eventHandlerMethod(){
>  writeln("Barking from method");
>  }
> }
>
> class Generator(alias eventHandler){
>  public void bark(){
>  eventHandler();
>  }
> }
>
> public void eventHandlerFunc(){
>  writeln("Barking from function");
> }
>
> void main(){
>  auto events = new EventClass;
>
>  auto gen1 = new Generator!( eventHandlerFunc )();
>  auto gen2 = new Generator!( events.eventHandlerMethod )();

As far as I know, just the member function name cannot be used that way. 
The problem boils down to how to create a type (or an alias) that will 
call a specific member function of a given object.


One way is to have a dedicated type that always call foo():

import std.stdio;

class C {
void foo() {
writeln("foo called");
}
}

class FooCaller {
C c;

this (C c) {
this.c = c;
}

void call() {
c.foo();// hard-coded to call foo()
}
}

void main() {
auto f = new FooCaller(new C());
f.call();
}

The following one creates a lambda (closure in this case?) that allows 
the user to pick which member function to call. Admittedly, 
CallableCaller() is not really needed in this example but it 
demonstrates how "a member function call on a specific object" can be 
passed as an alias template parameter:


import std.stdio;

class C {
void foo() {
writeln("foo called");
}
}

class CallableCaller(alias closure) {
void call() {
closure();
}
}

void main() {
auto c = new C();
auto f = new CallableCaller!(() => c.foo());
f.call();
}

Ali



Re: Defining event handlers for function, method, or shared method

2016-01-26 Thread tcak via Digitalmars-d-learn

On Tuesday, 26 January 2016 at 19:22:58 UTC, Ali Çehreli wrote:

On 01/26/2016 10:41 AM, tcak wrote:
> I need/want this class to be able to bind
> a function, a method, or a shared method. From the
perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not
to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define 
the interface and a templated class can provide the differences:


import std.stdio;
import std.algorithm;

interface Event {
void start();
void stop();
void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias 
onItemAdded) : Event {

void start() {
onStart();
}

void stop() {
onStop();
}

void itemAdded(size_t itemIndex) {
itemAdded(itemIndex);
}
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, 
fooItemAdded);


struct S {
void memberFunction() {
}
}
auto s = S();

auto memberClosure(ref S s) {On 01/26/2016 10:41 AM, tcak 
wrote:

> I need/want this class to be able to bind
> a function, a method, or a shared method. From the
perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not
to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define 
the interface and a templated class can provide differences:


import std.stdio;
import std.algorithm;

interface Event {
void start();
void stop();
void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias 
onItemAdded) : Event {

void start() {
onStart();
}

void stop() {
onStop();
}

void itemAdded(size_t itemIndex) {
itemAdded(itemIndex);
}
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, 
fooItemAdded);


struct S {
void memberFunction() {
}
}
auto s = S();

auto memberClosure(ref S s) {
return () => s.memberFunction();
}

events ~= new ConcreteEvent!(() => memberClosure(s),
 () => writeln("stop"),
 bar);

events.each!(e => e.stop);
}

Ali

return () => s.memberFunction();
}

events ~= new ConcreteEvent!(() => memberClosure(s),
 () => writeln("stop"),
 bar);

events.each!(e => e.stop);
}

Ali


Hmm. Your example works fine for functions, but I can't pass a 
method instead of function as alias. Check my example:



import std.socket;

class EventClass{
public void eventHandlerMethod(){
writeln("Barking from method");
}   
}

class Generator(alias eventHandler){
public void bark(){
eventHandler();
}
}

public void eventHandlerFunc(){
writeln("Barking from function");
}

void main(){
auto events = new EventClass;

auto gen1 = new Generator!( eventHandlerFunc )();
auto gen2 = new Generator!( events.eventHandlerMethod )();

gen1.bark();
gen2.bark();
}


Error is given on "auto gen2 = ..." in main function due to 
passing method. I guess because it is runtime normal compile time 
information.


I was looking for something like to be defined in the class 
Generator:


public DelegateOnStart eventOnStart;

So I could set eventOnStart as either function pointer, method 
pointer, or shared method pointer. To be able to support three of 
them, for every event, I need to define another variable, another 
alias, and while calling, check whichever variable (delegate 
pointer) is set, and call that one. I hope I am making it clear 
why it turns into mess.


Re: Defining event handlers for function, method, or shared method

2016-01-26 Thread tcak via Digitalmars-d-learn

On Tuesday, 26 January 2016 at 19:42:42 UTC, tcak wrote:

On Tuesday, 26 January 2016 at 19:22:58 UTC, Ali Çehreli wrote:

[...]


Hmm. Your example works fine for functions, but I can't pass a 
method instead of function as alias. Check my example:


[...]


Edit: ... "I guess because it is runtime information, not compile 
time" ...


Re: Defining event handlers for function, method, or shared method

2016-01-26 Thread Ali Çehreli via Digitalmars-d-learn
What a lousy copy+paste mistake that was. I am glad no credit card 
number leaked there. :p


On 01/26/2016 11:22 AM, Ali Çehreli wrote:
> class ConcreteEvent(alias onStart, alias onStop, alias onItemAdded) :

>  void itemAdded(size_t itemIndex) {
>  itemAdded(itemIndex);
>  }

That call should have been onItemAdded().

Ali



Re: Defining event handlers for function, method, or shared method

2016-01-26 Thread Ali Çehreli via Digitalmars-d-learn

On 01/26/2016 10:41 AM, tcak wrote:
> I need/want this class to be able to bind
> a function, a method, or a shared method. From the perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define the 
interface and a templated class can provide the differences:


import std.stdio;
import std.algorithm;

interface Event {
void start();
void stop();
void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias onItemAdded) : 
Event {

void start() {
onStart();
}

void stop() {
onStop();
}

void itemAdded(size_t itemIndex) {
itemAdded(itemIndex);
}
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, fooItemAdded);

struct S {
void memberFunction() {
}
}
auto s = S();

auto memberClosure(ref S s) {On 01/26/2016 10:41 AM, tcak wrote:
> I need/want this class to be able to bind
> a function, a method, or a shared method. From the perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define the 
interface and a templated class can provide differences:


import std.stdio;
import std.algorithm;

interface Event {
void start();
void stop();
void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias onItemAdded) : 
Event {

void start() {
onStart();
}

void stop() {
onStop();
}

void itemAdded(size_t itemIndex) {
itemAdded(itemIndex);
}
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, fooItemAdded);

struct S {
void memberFunction() {
}
}
auto s = S();

auto memberClosure(ref S s) {
return () => s.memberFunction();
}

events ~= new ConcreteEvent!(() => memberClosure(s),
 () => writeln("stop"),
 bar);

events.each!(e => e.stop);
}

Ali

return () => s.memberFunction();
}

events ~= new ConcreteEvent!(() => memberClosure(s),
 () => writeln("stop"),
 bar);

events.each!(e => e.stop);
}

Ali



Defining event handlers for function, method, or shared method

2016-01-26 Thread tcak via Digitalmars-d-learn
In many multi threading module designs of mine, I generally 
design a base class, and

this class have some events. Exempli gratia:

void eventOnStart();
void eventOnStop();
void eventOnItemAdded( size_t itemIndex );

There is this problem though. I need/want this class to be able 
to bind a function, a method, or a shared method. From the 
perspective of class design, there shouldn't be any
difference. Its purpose is to let know about the event, not to 
care about how the event

handler is designed.

If I want handlers to be functions, I design it like,

public alias EventOnStart = void function();
public EventOnStart eventOnStart;


If it is for normal methods, design becomes like,

public alias EventOnStart = void delegate();


For shared methods, it becomes,

public alias EventOnStart = void delegate() shared;


As you will guess, to be able to support any of those three, it 
becomes so complex. Is
there any way generalise to support three of them without making 
this any complex? A
secondary thing, this is not D related though, whether there is 
any different approach
for event listener design like Observer pattern but with little 
overhead and complexity?