On Friday, 11 November 2022 at 01:09:54 UTC, torhu wrote:
On Thursday, 10 November 2022 at 21:55:26 UTC, torhu wrote:
I'm trying to make a more thread-safe wrapper for AA's:

```
synchronized final class SyncAA(K, V) ///

I chose to fix this by just using `synchronized (this)` inside each method instead, for now. Still interested in cleaner solutions, but I guess synchronized/shared is a bit of a rabbit hole...

That's about what I ended up with, and just declaring my references __gshared. I don't know what's going on with shared/synchronized but it sounds like it's unfinished and people can't agree on what they're actually supposed to mean. __gshared, it just works. Previous thread: [synchronized/shared associative array .require error](https://forum.dlang.org/post/hcbrgpmdufjgjtxtu...@forum.dlang.org) Also: [synchronized - shared but actually useful](https://forum.dlang.org/thread/drrlgymevccozrqms...@forum.dlang.org)

```d
class SyncTable(KEY, VAL) {
        private VAL[KEY] table;
        auto opIndexAssign(VAL value, KEY key) {
                synchronized(this) {
                        return table[key] = value;
                }
        }
        int opApply(int delegate(ref KEY, ref VAL) dg) {
                synchronized(this) {
                        foreach (key, val; table) {
                                if (dg(key, val)) return 1;
                        }
                        return 0;
                }
        }
        auto opBinaryRight(string op)(KEY key) if (op == "in") {
                synchronized(this) {
                        return key in table;
                }
        }
        auto opDispatch(string s, SA...)(SA sargs) {
                synchronized(this) {
                        static if (SA.length == 0) {
                                mixin(format("return table.%s;", s));
                        } else {
mixin(format("return table.%s(%s);", s, sargs.stringof[6 .. $-1])); // tuple(_param_0)
                        }
                }
        }
}
```

With synchronized on the class, I had to do something like:
```d
synchronized class SyncTable(KEY, VAL) {
        // Anything that mutates must reassign unshared back to table!
        auto opIndexAssign(VAL value, KEY key) {
                auto unshared = cast(T) table;
                unshared[key] = value;
                table = cast(shared) unshared;
                return value;
        }
        auto require(KEY key) {
                auto unshared = cast(T) table;
                auto r = unshared.require(key);
                table = cast(shared) unshared;
                return r;
        }
        /* ... */
}
```
and it just doesn't feel right.

For mutexes without synchronized, there's also:
```d
struct Lock {
        private shared Mutex _mtx;
        this(shared Mutex mtx) {
                _mtx = mtx;
                _mtx.lock();
        }
        this(this) @disable;
        ~this() {
                if (_mtx)
                        _mtx.unlock();
                _mtx = null;
        }
}
class SyncTable(KEY, VAL) {
        private VAL[KEY] table;
        shared Mutex mtx;
        this() {
                mtx = new shared Mutex;
        }
        auto opIndexAssign(VAL value, KEY key) {
                auto lock = Lock(mtx);
                return table[key] = value;
        }
        /* ... */
}
```

Reply via email to