Large (>32 byte) concurrency messages

JR zorael at gmail.com
Thu Aug 8 13:08:08 PDT 2013


I'm working on an IRC bot as my pet project. I do know of 
Dirk[1]; I'm mostly doing this to learn the language.


For the sake of the argument, imagine three threads; one that 
reads from the socketstream of the socket connected to the IRC 
server, one Mediator that keeps track of what other threads 
and/or functions are interested in different IRC events (joins, 
parts, channel messages, ...), and one that simply wants to 
receive stuff to print to the screen.

The flow of events would go like this:
1. the 'reading' thread gets a raw string from the server
2. ...and passes it as a concurrency message to the Mediator
3. the Mediator receives it
4. ...and does serious regex voodoo to produce an IrcEvent 
struct, with various members detailing what type of event it was 
(again join, parts, ...), from and to whom, textual content if 
applicable, etc
5. the Mediator sends the struct as a concurrency message to our 
printing thread
6. ...which receives and prints it.
7. GOTO 1

The first concurrency message passed is a string, which works as 
expected. The second message is the translated struct of over 32 
bytes in size (96 to be exact), and that's where things start 
breaking.

Passing by value, e.g. tid.send(eventStruct);
>core.exception.AssertError@/usr/include/d/4.8/std/variant.d(280): 
>target must be non-null

Passing by immutable, e.g. tid.send(cast(immutable) eventStruct);
>/usr/include/d/4.8/std/variant.d:552: Error: cannot modify 
>immutable expression *p
>/usr/include/d/4.8/std/concurrency.d:111: Error: template 
>instance 
>std.variant.VariantN!(32LU).VariantN.opAssign!(immutable(IrcEvent)) 
>error instantiating

Passing an immutable pointer *initially* works, but then you get 
a race to finish using the struct before the scope it was 
declared in ends. (It's not on the heap.)
>received *(immutable(IrcEvent*)): immutable(IrcEvent)(UNSET, 
>x"F0 30 E2 DA FF 7F 00 00 80 96 98 00 00 00 00 00 80 DF 9F 64 D2 
>7F 00 00 F0 30 E2 DA FF 7F 00 00 [...] Segmentation fault

 From gdb;
>The value of '_param_1.sender' is a struct/class of type 'struct 
>string' with the following fields:
>
>  length = 4409885 .. (Value of type 'ulong')
>     ptr = <Enter 1 to explore this field of type 'const char *'>
>
>Enter the field number of choice: 1
>'(_param_1.sender).ptr' is a pointer to a value of type 'const 
>char'
>Continue exploring it as a pointer to a single value [y/n]: y
>'(_param_1.sender).ptr' a pointer pointing to an invalid memory 
>location.


I put together http://dpaste.dzfl.pl/d7322971 earlier to 
demonstrate some of these errors, though I didn't mention the 
raciness of passing pointers there. To test that race I used 
http://dpaste.dzfl.pl/e6fd4569.


Are there any easy workarounds? Do people use std.concurrency, or 
is it largely avoided? Variant also seems to have some major 
issues... or maybe everything is caused by Variant and 
std.concurrency just exposes it.

I hit a wall here. :< Would love any tips or tricks you could 
spare!


[1]: https://github.com/JakobOvrum/Dirk


More information about the Digitalmars-d-learn mailing list