TLF = thread local functions
Stanislav Blinov
stanislav.blinov at gmail.com
Fri Jan 24 02:43:04 PST 2014
On Friday, 24 January 2014 at 09:50:44 UTC, Dicebot wrote:
> On Friday, 24 January 2014 at 08:11:53 UTC, Stanislav Blinov
> wrote:
>> ...Unless the thread is started with a delegate (literal or
>> member function), which implicitly gains an unsynchronized
>> view of its enclosing scope (or class).
>
> Which means accessing shared data pretty much by definition.
I would rephrase that as "implicitly sharing not explicitly
shared data".
> It actually should not even compile without explicit casts. I
> guess yet another delegate qualifier bug.
Why shouldn't it compile? Safe spawner (std.concurrency.spawn)
does not accept delegates. Unsafe one (core.thread.Thread) does.
I wouldn't consider it a bug since in the context of one thread
it's pretty much a feature :)
But I agree that some special syntax for threading and otherwise
restricting sharing would be great. Maybe another set of
parentheses?
Consider:
// Call could be anything. Just a call, do-some-work-and call,
// spawn a thread, etc.
void call(F,Args...)(F dg,Args args) if (is(F == delegate)) {
dg(args);
}
void main() {
int myPreciousInt = 42;
string myPreciousString = "precious";
// current syntax, horrifying if call spawns a thread with
that delegate
call({
myPreciousInt = 151; // modifies main's myPreciousInt
myPreciousString = "stolen"; // ditto
});
// current syntax with parameters, ditto
call((int i){
myPreciousInt = i;
myPreciousString = "stolen";
});
// explicit capture syntax:
call((myPreciousInt){ // capture by value
myPreciousInt = 132; // changes local variable
myPreciousString = "stolen"; // would not compile,
variable is not captured
});
// explicit capture with parameters:
call((ref myPreciousInt)(int i){ // capture by reference
myPreciousInt = 144; // will modify main's myPreciousInt
too
});
}
This could be extended to support various capture qualifies:
ref - by reference
in - by move
ref shared - by reference if variable is shared
etc.
Looks like C++'s [](){}, perhaps, but with D's powerful
compile-time facilities we could do so much more. For example,
the above, coupled with some introspection with e.g.
__traits(captures, dg) could give way to implementing safe thread
spawners even for delegates: e.g. disallow capturing non-shared
data by reference.
As I mentioned, currently pretty much all that can be done is a
shallow copy of the stack (which means allocation), and I don't
even know how portable or safe that is :)
>
>> Um, duh, but in d data is already TLS.
>
> 1) not necessarily, is is only default
>
> 2) "using TLS data" usually implies "using _own_ TLS data" as
> you shouldn't be able to get reference to TLS of other thread
> without dirty hacks (it breaks basic type system assumptions)
In my understanding delegates are pretty much unique at that.
Probably because they were redesigned like that since D1, but
never were taken one step further towards multithreading.
More information about the Digitalmars-d-learn
mailing list