On Sunday, 7 October 2018 at 01:59:21 UTC, Manu wrote:
So I'm working on a SMT infrastructure, and expression ofthread-safety is a core design mechanic... but I'm really strugglingto express it in terms of the type system.I figure I'll throw some design challenges out here and see if anyonecan offer some good ideas.The thing I'm trying to model is an attribute along the lines of `shared`, but actually useful ;)I'll use the attribute `threadsafe` in place of `shared`, and seewhere that goes. Consider: struct Bob { int x; threadsafe Atomic!int y; void m1(); void m2() threadsafe;; void overloaded(); void overloaded() threadsafe; } void func( ref Bob x, ref threadsafe Bob y) { x.x = 10; // fine x.y = 10; // fine x.m1(); // fine x.m2(); // fine x.overloaded(); // fine, use the un-threadsafe overload y.x = 10; // ERROR, a threadsafe reference can NOT modify an un-threadsafe member y.y = 10; // fine x.m1(); // ERROR, method not threadsafe x.m2(); // fine x.overloaded(); // fine, use the threadsafe overload threadsafe Bob* p = &x; // can take threadsafe reference to thread-local object }This is loosely what `shared` models, but there's a few differences:1. thread-local can NOT promote to shared 2. shared `this` applies to membersFor `shared` to be useful, it should be that a shared reference to something inhibits access to it's thread-local stuff. And in that world, then I believe that thread-local promotion to shared would work like const does.I guess I'm wondering; should `shared` be transitive? Perhaps that's what's wrong with it...?
A delta comparison with sharedvoid func( ref Bob x, ref threadshared /* either shared or threadsafe*/ Bob y)
{
// threadsafe / shared
x.x = 10; // fine / fine
x.y = 10; // fine / fine uses atomics
x.m1(); // fine / fine
x.m2(); // fine / error cannot call shared method on unshared
object
x.overloaded(); // fine, use the un-threadsafe overload / finey.x = 10; // ERROR, a threadsafe reference can NOT modify an un-threadsafe member / error
y.y = 10; // fine / fine (using atomics) // Assuming these are supposed to be y not x y.m1(); // ERROR, method not threadsafe / error y.m2(); // fine / fine y.overloaded(); // fine, use the threadsafe overload / finethreadsafe Bob* p = &x; // can take threadsafe reference to thread-local object / error
} Differences: Can call threadsafe method on thread local / unshared Can take threadsafe reference to thread-local object.One thing that occurred to me is that _objects_ are shared, whereas _functions/methods_ (and their parameters) are thread safe .
Theadsafe is kind of like a const (as to mutable/immutable) to threading, a promise to behave correctly in the presence of threading. thread safe references therefore must not escape.
