[Issue 10821] .byKey erroneously returns a null key

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Aug 17 11:00:44 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=10821



--- Comment #5 from Andrej Mitrovic <andrej.mitrovich at gmail.com> 2013-08-17 11:00:42 PDT ---
(In reply to comment #4)
> I found
> that the only way to keep things consistent without strange side-effects was to
> keep a list of to-be-deleted entries separately, and the delegate would never
> modify the array of callbacks directly, but would append itself to the
> to-be-deleted list if it wants to remove itself.

Hmm yeah, it gets complicated real fast. Thanks for the insight.

So here's a quick safer workaround implementation:

-----

struct Signal
{
    void connect(void delegate(int) func)
    {
        if (emitting)
        {
            funcsToAdd[func] = 1;
        }
        else
        {
            stderr.writefln("Func connect: %s", *cast(void**)&func);
            funcs[func] = 1;
        }
    }

    void disconnect(void delegate(int) func)
    {
        if (emitting)
        {
            funcsToDelete[func] = 1;
        }
        else
        {
            stderr.writefln("Func disconnect: %s", *cast(void**)&func);
            funcs.remove(func);
        }
    }

    void emit(int i)
    {
        emitting = true;
        scope(exit) emitting = false;

        foreach (func; funcs.byKey)
        {
            stderr.writefln("Calling: %s", *cast(void**)&func);
            func(i);
        }

        foreach (func; funcsToDelete.byKey())
            funcs.remove(func);

        funcsToDelete = null;

        foreach (func; funcsToAdd.byKey())
            funcs[func] = 1;

        funcsToAdd = null;
    }

    int[void delegate(int)] funcs;
    int[void delegate(int)] funcsToAdd;
    int[void delegate(int)] funcsToDelete;
    bool emitting;
}

void main()
{
    Signal signal;

    void delegate(int) handler;
    handler =
        (int i)
        {
            signal.disconnect(handler);
        };

    signal.connect(handler);

    signal.emit(1);
    signal.emit(2);
    signal.emit(3);
    signal.emit(4);
}
-----

Of course this still isn't perfect, there's no telling what a signal handler
really wants to do, whether it actually wants to add/remove some other handler
immediately or only schedule add/removal for later.

I guess the bottom line is this stuff is more complicated than I thought. I
wonder if that new signals implementation recently announced handles this sort
of stuff.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list