Mallocator and 'shared'
bitwise via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Feb 12 12:08:05 PST 2017
On Saturday, 11 February 2017 at 04:32:37 UTC, Michael Coulombe
wrote:
> On Friday, 10 February 2017 at 23:57:18 UTC, bitwise wrote:
>> [...]
>
> A shared method means that it can only be called on a shared
> instance of the struct/class, which will have shared fields. A
> shared method should be logically thread-safe, but that cannot
> be guaranteed by the compiler. A non-shared method can touch
> shared memory, and thus should be thread-safe if it does, but
> can only be called on a non-shared instance with possibly
> non-shared fields.
>
> shared/non-shared methods don't mix because you generally need
> to use different, less-efficient instructions and algorithms to
> be thread-safe and scalable in a shared method. In the case of
> Mallocator, there are no fields so as far as I can tell the
> attribute doesn't do much except for documentation and for
> storing references to it in other shared structs/objects.
Thanks for the explanation, but I'm still confused.
It seems like you're saying that 'shared' should mean both
'thread safe' and 'not thread safe' depending on context, which
doesn't make sense.
Example:
shared A a;
struct A {
int x, y;
void foo() shared {
a.x = 1;
}
}
int main(string[] argv) {
a.x = 5;
a.y = 5;
a.foo();
return 0;
}
Qualifying 'a' with 'shared' means that it's shared between
threads, which means that accessing it is _not_ thread safe.
Since the method 'foo' accesses 'a', 'foo' is also _not_ thread
safe. Given that both the data and the method are 'shared', a
caller should know that race conditions are possible and that
they should aquire a lock before accessing either of them...or so
it would seem.
I imagine that qualifying a method with 'shared' should mean that
it can access shared data, and hence, is _not_ thread safe. This
prevent access to 'shared' data from any non 'shared' context,
without some kind of bridge/cast that a programmer would use when
they knew that they had aquired the lock or ownership of the
data. Although this is what would make sense to me, it doesn't
seem to match with the current implementation of 'shared', or
what you're saying.
It seems that methods qualified with 'shared' may be what you're
suggesting matches up with the 'bridge' I'm trying to describe,
but again, using the word 'shared' to mean both 'thread safe' and
'not thread safe' doesn't make sense. Firstly, because the same
keyword should not mean two strictly opposite things. Also, if a
'shared' method is supposed to be thread safe, then the fact that
it has access to shared data is irrelevant to the caller. So
'shared' as a method qualifier doesn't really make sense. What
would make more sense is to have a region where 'shared' data
could be accessed - Maybe something like this:
struct S {
shared int x;
Lock lk;
private void addNum(int n) shared {
x += num;
}
int add(int a, int b)
{
shared {
lk.lock();
addNum(a);
addNum(b);
lk.unlock();
}
}
}
So above,
1) 'x' would be shared, and mutating it would not thread safe.
2) 'addNum' would have access to 'shared' data, and also be
non-thread-safe
3) 'x' and 'addNum' would be inaccessible from 'add' since
they're 'shared'
4) a 'shared' block inside 'add' would allow access to 'x' or
'addNum', with the responsibility being on the programmer to lock.
5) alternatively, 'shared' data could be accessed from within a
'synchronized' block.
I thought 'shared' was a finished feature, but it's starting to
seem like it's a WIP. This kind of feature seems like it has
great potential, but is mostly useless in it's current state.
After more testing with shared, it seems that 'shared' data is
mutable from many contexts, from which it would be unsafe to
mutate it without locking first, which basically removes any
gauruntee that would make 'shared' useful.
Again, tell me if I'm wrong here, but there seems to be a lot of
holes in 'shared'.
Thanks
More information about the Digitalmars-d-learn
mailing list