Thread-safe attribution

Nicholas Wilson iamthewilsonator at hotmail.com
Sun Oct 7 02:39:28 UTC 2018


On Sunday, 7 October 2018 at 01:59:21 UTC, Manu wrote:
> So I'm working on a SMT infrastructure, and expression of
> thread-safety is a core design mechanic... but I'm really 
> struggling
> to express it in terms of the type system.
> I figure I'll throw some design challenges out here and see if 
> anyone
> can 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 
> see
> where 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 members
>
> For `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 shared

void 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 / fine

   y.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 / fine

   threadsafe 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.



More information about the Digitalmars-d mailing list