Synchronisation help

Anonymouse zorael at gmail.com
Tue Jan 2 10:41:55 UTC 2024


On Monday, 1 January 2024 at 19:49:28 UTC, Jonathan M Davis wrote:
> [...]

Thank you. Yes, `Foo` is a class for the purposes of inheritance 
-- I left that out of the example.

So a completely valid solution is to write a struct wrapper 
around an AA of the type I need, overload the required operators, 
and then just drop-in replace the current AA? All array 
operations would then transparently be between lock and unlock 
statements.

```d
struct MutexedAA(AA : V[K], V, K)
{
     import core.sync.mutex : Mutex;

     shared Mutex mutex;

     shared AA aa;

     void setup() nothrow
     {
         mutex = new shared Mutex;

         mutex.lock_nothrow();

         if (K.init !in (cast()aa))
         {
             (cast()aa)[K.init] = V.init;
             (cast()aa).remove(K.init);
         }

         mutex.unlock_nothrow();
     }

     auto opIndexAssign(V value, K key)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         (cast()aa)[key] = value;
         mutex.unlock_nothrow();
         return value;
     }

     auto opIndex(K key)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         auto value = (cast()aa)[key];
         mutex.unlock_nothrow();
         return value;
     }

     auto opBinaryRight(string op : "in")(K key)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         auto value = key in cast()aa;
         mutex.unlock_nothrow();
         return value;
     }

     auto remove(K key)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         auto value = (cast()aa).remove(key);
         mutex.unlock_nothrow();
         return value;
     }

     auto opEquals()(auto ref typeof(this) other)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         auto isEqual = (cast()aa == cast()(other.aa));
         mutex.unlock_nothrow();
         return isEqual;
     }

     auto opEquals()(auto ref AA other)
     in (mutex, typeof(this).stringof ~ " has null Mutex")
     {
         mutex.lock_nothrow();
         auto isEqual = (cast()aa == other);
         mutex.unlock_nothrow();
         return isEqual;
     }
}
```

(https://gist.github.com/zorael/433c50f238b21b9bb68d076d8a495045)

I tried this and it seems to work. Is it glaringly incorrect 
somehow, or am I free to roll with this?

You mention passing a `shared Foo*`. In the gist I pass the 
instance of the `MutexedAA!(string[int])` to the worker thread 
*by value* instead of as something `shared`, since I couldn't get 
operator overloading to work when `shared`. (Calling 
`sharedAA.opIndexAssign("hello", 42)` worked, but `sharedAA[42] = 
"hello"` wouldn't compile.)

I guess this can break synchronisation between the two if I 
replace the `Mutex` in either thread. Are there any other obvious 
caveats?


More information about the Digitalmars-d-learn mailing list