Am 22.01.2014 06:16, schrieb unknown soldier:
I'm confused by shared and how to use it.
import std.stdio;
class Foo {
File logFile;
void log(in string line) shared {
synchronized(this){
logFile.writeln(line);
}
}
}
This (or the equivalent code in my full size program) won't
compile:
source/log.d(256): Error: template std.stdio.File.writeln does
not match any function template declaration. Candidates are:
/usr/include/dmd/phobos/std/stdio.d(781):
std.stdio.File.writeln(S...)(S args)
source/log.d(256): Error: template std.stdio.File.writeln(S...)(S
args) cannot deduce template function from argument types
!()(const(immutable(char)[])) shared
Why is logFile suddenly being treated as shared? This does not
make sense to me. As a programmer I have acknowledged that log()
is a shared function in the declaration 'void log(in string line)
shared', so isn't it up to me to ensure that I do proper
synchronization within the function? Why is the compiler trying
to ensure that all functions called within log() are also marked
shared?
What is the right thing to do here?
Note that I can't just mark log() as not shared; log() must be
shared because elsewhere I have:
shared Foo sfoo = ...
sfoo.log(...)
For a shared method the this pointer is also shared. That means that you
have to tell the compiler (manually) that it is now safe to use
non-shared code. You usually do this by casting the this pointer to a
unshared type.
class Foo {
File logFile;
void log(in string line) shared {
synchronized(this){
// safe from here on because synchronized
auto self = cast(Foo)this;
self.logFile.writeln(line);
}
}
}
The compiler does not do this for you, because it can not know if
accessing any member is truly thread-safe. You might share the logFile
with other instances of Foo. This would be a case where the compiler
would wrongly remove the shared from this, if it would do so
automatically inside synchronized blocks.