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?

Reply via email to