Reputation: 11885
To my sheer delight I discovered that D has made progress and now actually runs on Windows 64 bit. It even has a Visual Studio integration which seems to work as far as I can see after a few hours of playing with my new toy.
So, obviously I just started to play with D as a language and am a bloody newbie in D.
In the code below my goal was to define function prototypes in a template and then to write functions as sub-functions of main() which conform to those prototypes. But compiler complains and right now I cannot find out how to get it right (probably simple syntax problem).
The compiler errors I get are:
main.d(90): Error: function main.Actor!(int, int).Worker (Duration timeout, bool function(int) timeoutHandler, bool function(int, int) messageHandler, int context) is not callable using argument types ()
main.d(90): Error: function main.main.W1OnTimeout (int context) is not callable using argument types ()
main.d(90): Error: function main.main.W1OnMessage (int context, int message) is not callable using argument types ()
Building Debug\ConsoleApp1.exe failed!
import std.stdio;
import core.time;
import std.socket;
import std.concurrency;
import core.thread;
enum SystemMessage
{
Shutdown,
Terminate,
Ping,
Enable,
Disable
}
template Actor(C,M)
{
// TimeoutHandler implementations always return true
// unless the worker shall terminate.
alias TimeoutHandler = bool function(C);
// MessageHandler implementations always return true
// unless the worker shall terminate.
alias MessageHandler = bool function(C,M);
void
Worker
( Duration timeout
, TimeoutHandler timeoutHandler
, MessageHandler messageHandler
, C context
)
{
bool running = true;
bool enabled = true;
while(running)
{
if( true == std.concurrency.receiveTimeout
(timeout,
(M message)
{
if(enabled)
{
if(!messageHandler(context,message) )
{
running = false;
}
}
},
(SystemMessage message)
{
switch(message)
{
case SystemMessage.Shutdown: running = false; break;
case SystemMessage.Terminate: running = false; break;
case SystemMessage.Enable: enabled = true; break;
case SystemMessage.Disable: enabled = false; break;
case SystemMessage.Ping: /* TODO: supervisor... */; break;
default: break;
}
}
))
{
}
else
{
if(!timeoutHandler(context))
{
running = false;
}
}
}
}
}
alias IntIntActor = Actor!(int,int);
int main(string[] argv)
{
// The signatures of the next 2 functions conform to the function
// declarations, given in Actor template (IntIntActor).
// How to write them so it works?
bool W1OnTimeout(int context)
{
writeln("W1OnTimeout()");
return true;
}
bool W1OnMessage(int context,int message)
{
writefln("W1OnMessage: context = %d, message = %d", context, message);
return true;
}
// Do I need some special syntax here? Like e.g. &W1OnTimeout ? Or a cast?
auto w1 = spawn(IntIntActor.Worker,1000.msecs,W1OnTimeout,W1OnMessage,1);
for(int i = 0; i < 10; i++)
{
send(w1,i);
}
Thread.sleep(5000.msecs);
send(w1,SystemMessage.Shutdown);
thread_joinAll();
return 0;
}
Thanks for your help, in advance!
Upvotes: 0
Views: 62
Reputation: 46
You pretty much gave the answer in your comment:
// Do I need some special syntax here? Like e.g. &W1OnTimeout ? Or a cast?
&W1OnTimeout
is exactly it; also &IntIntActor.Worker
and &W1OnMessage
.
It still won't compile, because &W1OnTimeout
and &W1OnMessage
are regarded as delegates, but Worker
takes function pointers. Mark the nested functions static
and it works:
static bool W1OnTimeout(int context)
{
...
}
static bool W1OnMessage(int context,int message)
{
...
}
Alternatively, define them outside of main.
Upvotes: 3