🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Progress, of a kind

Published March 11, 2009
Advertisement
After some extended discussions, I've come up with a system that I'm almost completely happy with.

entrypoint : () -> (){	task(async)	{		responsemap(responses)		{			some_message(integer(foo)) => { do_stuff(foo) }			other_message(integer(lots), integer(of), integer(params)) =>			{				do()				lots()				of()				stuff()			}			exit() => { return() }		}		while(true)		{			acceptmsg(responses)		}	}	message(async, some_message(42))	message(async, other_message(1, 2, 3))	message(async, exit())	acceptmsg(result(integer(foo)) => { debugwritestring(cast(string, foo)) } )}



There are some major notable points here:
  • The big thing is the concept of the response map. This is basically a pattern recognition block, where we examine the token used to identify the message, as well as the attached data payload. When a pattern is matched, we fire off the attached code block. (On a completely irrelevant note, the => magic symbol will also appear when it comes time to do lambdas.)

  • acceptmsg() has three overloads. One accepts a named response map; one accepts an anonymous response map which is constructed in-line; and one has no parameters, which is used to discard a message.

  • Named response maps can be reused, so they are effectively a sort of interface contract. This will come into play when it comes time to build the object model for Epoch.

  • Since this is based on pattern recognition, there's no need to define a set of messages beforehand; the interface for the async task is provided entirely by its responsemaps. Similarly, using an anonymous response map allows us to make one-off interactions between running bits of code.



I'm not sure how I'll feel about this in the light of day, but as of midnight it seems pretty darn solid [grin]
0 likes 2 comments

Comments

choffstein
Looks like Erlang's model a bit ... but your pattern matching is implicit.

How do I know, in my receiving blocks, who is sending me a message so I can send one back? A special keyword or something?

What is nice about this paradigm is that for the programmer, there is no difference between serial, parallel, and even distributed (your VM simply needs to keep a map of task names and whether they are running locally or on a foreign machine). Nice!
March 12, 2009 10:12 AM
ApochPiQ
There's two magic words: the caller() function gives you a handle to the task that forked the currently running task (in this example, caller() would return a handle to the main startup thread). The sender() function is valid only within a message accept block, or in a function called from such a block. sender(), as the name suggests, gives you a handle to the task that sent the currently in-process message.


And yes, I'm shamelessly ripping off Erlang, because I really like that model [smile]
March 12, 2009 11:03 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement