May 05, 2022

Some code I have:

alias Operator = dstring function(dstring input);

//List of all operations.
package Operator[dstring] opList;

//List of all functions.
package dstring[dstring] funcList;

//Functions that may not be deleted.
package dstring[dstring] noTouch;

//Initialize the basic arithmetic operations to null: these will be handled by operator overloading.
shared static this()
{
    opList["+"d] = null;
	opList["-"d] = null;
	opList["*"d] = null;
	opList["/"d] = null;
	opList["^^"d] = null;
}

//Add the neccessary functions to noTouch.
shared static this()
{
    noTouch["ln(x) = num(num)"d] = null;
    noTouch["sin(x) = num(num)"d] = null;
    noTouch["cos(x) = num(num)"d] = null;
    noTouch["tan(x) = num(num)"d] = null;
    noTouch["csc(x) = num(num)"d] = null;
    noTouch["sec(x) = num(num)"d] = null;
    noTouch["cot(x) = num(num)"d] = null;
    noTouch["Γ(x) = num(num)"d] = null;
    noTouch["δ(x) = num(num)"d] = null;
    assert("δ(x) = num(num)"d in noTouch);
}

//CUT

//CUT END

bool removeFunction(dstring funcdef) @safe @nogc nothrow
{
    if(funcdef !in funcList || funcdef in noTouch) //Make sure that the function acutally exists and isn't non-removable.
        return false;
    funcList.remove(funcdef);
    return true;
}

///
unittest
{
    dstring func = "x + 1"d;
    assert(!removeFunction("a(x) = num(num)"d));
    funcList["δ(x) = num(num)"d] = null;
    assert("δ(x) = num(num)"d in noTouch);
    assert(!removeFunction("δ(x) = num(num)"d));
    funcList.remove("δ(x) = num(num)");
    //registerFunction("a(x) = num(num)"d, func);
    //assert(removeFunction("a(x) = num(num)"d));
}

Running dub test (with silly) returns no errors.

Now, comment out the following line of code:

assert("δ(x) = num(num)"d in noTouch);

Running dub test fails, with the removal of this line being the culprit.

However, this code (plus an added main function) passes when pasted into run.dlang.io.

I have tried building both with dmd 2.099.1 and ldc 1.029.0 on Windows 10 x86_64 with -m64, and it fails.

What can I do to fix this?

May 05, 2022

On Thursday, 5 May 2022 at 01:44:37 UTC, Ruby The Roobster wrote:

>

Some code I have:
(...)
What can I do to fix this?

I didn't try your code, but opList, funcList, and noTouch are thread-local variables, and you fill them in a shared static this. This means they will remain empty in any thread other than the main one. The test would fail in the way you describe if they are empty. So, I bet the tests run in another thread.

Of this is indeed the problem you can either:

  • Make the lists immutable. This implicitly shares them among threads. But it looks like you want to modify them so immutable won't work in this case.

  • If you don't want / need to share the lists over threads, fill them using a normal static this instead.

  • If you do need to share them over threads, mark the lists as shared /
    __gshared, but you'll be responsible for accessing them in a thread-safe manner.