New syntax for string mixins
Graham St Jack
Graham.StJack at internode.on.net
Tue Dec 14 15:19:46 PST 2010
> I don't know, do you have an example ?
>
>> For example taking a classname and a bunch of field types and names, and
>> turning it into a class definition complete with constructor from field
>> values, constructor from an input stream, a method to write to an output
>> stream, and const getters. Or maybe std.typecons.AutoImplement.
>
> Could you post an example of how that mixin would be used and the code
> it would generate then I can see if I can translate it to my syntax.
> AutoImplement seems to just contain template mixins which is something
> else.
>
I have attached my concurrency framework, which relies heavily on
mixins, plus its unit test to show how it is used. I haven't included
the various dependencies because I assume you just want the example
code. Let me know if you want something buildable, or perhaps something
more cut-down.
What the code-generating template does is to create from something like
this (you can have any number of Messages in a Protocol):
alias Protocol!("Requests", Message!("job", string, "name")).code
jobCode;
mixin(jobCode);
this code:
class Requests {
struct jobMsg {
string name;
this(string name) {
this.name = name;
}
void read(InStream stream) {
name = stream.get!string;
}
void write(OutStream stream) {
stream(name);
}
}
struct Message {
uint kind;
union {
jobMsg job;
}
this(ref jobMsg msg) {
kind = 0;
job = msg;
}
this(InStream stream) {
kind = stream.get!uint;
switch(kind) {
case 0: job.read(stream); break;
default: assert(0, "Cannot read unsupported message kind");
}
}
void write(OutStream stream) {
stream(kind);
switch(kind) {
case 0: job.write(stream); break;
default: assert(0, "Cannot write unsupported message
kind");
}
}
}
private alias Channel!(Message) _Chan;
private alias shared _Chan Chan;
private Chan channel;
this() { channel = new Chan(); }
ChannelSelectable newSelectable() { return channel.newSelectable(); }
void finalize() { channel.finalize; }
interface IHandler {
void job(string name);
}
void job(string name) {
channel.add(Message(jobMsg(name)));
}
void receive(IHandler handler) {
auto message = channel.remove;
switch (message.kind) {
case 0: handler.job(message.job.name); break;
default: assert(0, "Cannot dispatch unsupported message kind");
}
}
}
I use this for inter-thread communications, and I use the discriminated
union to pass messages between processes. The manual mixin after the
alias is a debugging aid - the compiler errors when doing mixins aren't
helpful at all. I case you are wondering why I did all this, it was
partly a learning experience, but mostly an attempt to do something
properly thread-safe (!hasAliasing), using shared, const and immutable
properly.
--
Graham St Jack
-------------- next part --------------
A non-text attachment was scrubbed...
Name: concurrency.d
Type: text/x-dsrc
Size: 18980 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20101215/ed14b56f/attachment-0002.d>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: concurrency_test.d
Type: text/x-dsrc
Size: 3095 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20101215/ed14b56f/attachment-0003.d>
More information about the Digitalmars-d
mailing list