RejectedSoftware Forums

Sign up

Concurrency

Why this doesn't work?

import vibe.d;

shared static this() {
  setLogLevel(LogLevel.debugV);
  setPlainLogging(false);
  auto t = runTask({
    while(true) receive(
      (string s) {
        logDebug("string received");
      }
    );
  });
  runTask({
    while(true) {
      t.send("test");
      logDebug("string sent");
      sleep(2.seconds);
    }
  });
}

expected

[01F40F80:00000000 dbg] Creating new fiber...
[01F40F80:00000000 dbg] Creating new fiber...
[01F40F80:01F40D00 dbg] string sent
[01F40F80:00000000 dia] Running event loop...
[01F40F80:01F40D00 dbg] string sent
[01F40F80:XXXXXXXX dbg] string received
[01F40F80:01F40D00 dbg] string sent
[01F40F80:XXXXXXXX dbg] string received
[01F40F80:01F40D00 dbg] string sent
[01F40F80:XXXXXXXX dbg] string received

but given

[01F40F80:00000000 dbg] Creating new fiber...
[01F40F80:00000000 dbg] Creating new fiber...
[01F40F80:01F40D00 dbg] string sent
[01F40F80:00000000 dia] Running event loop...
[01F40F80:01F40D00 dbg] string sent
[01F40F80:01F40D00 dbg] string sent
[01F40F80:01F40D00 dbg] string sent

Re: Concurrency

Windows 7, DMD 2.062

Re: Concurrency

Also tried running example "message".
Output:

send Hello World
send int 1
send double 1.2
send int 2
send 3xint 1 2 3
send string Bye bye

Re: Concurrency

Seems like TaskMutex/TaskCondition is broken.

import vibe.d;

shared static this() {
  bool flag = false;
  TaskCondition cv = new TaskCondition(new TaskMutex);
  runTask({
    synchronized(cv.mutex) {
      while(!flag) cv.wait();
    }
    logInfo("notified");
  });
  runTask({
    synchronized(cv.mutex) {
      flag = true;
      cv.notify();
    }
    logInfo("notify");
  });
}

outputs

notify

Re: Concurrency

On Fri, 03 May 2013 16:28:40 GMT, Jack Applegame wrote:

Seems like TaskMutex/TaskCondition is broken.

import vibe.d;

shared static this() {
  bool flag = false;
  TaskCondition cv = new TaskCondition(new TaskMutex);
  runTask({
    synchronized(cv.mutex) {
      while(!flag) cv.wait();
    }
    logInfo("notified");
  });
  runTask({
    synchronized(cv.mutex) {
      flag = true;
      cv.notify();
    }
    logInfo("notify");
  });
}

outputs

notify


It looks like libevent loses the events that should cause receive/TaskCondition.wait to stop waiting whenever the initial wait happens before the event loop has been started. I'll look into this. For now there are two workarounds:

  1. Put f.ex. sleep(1.seconds()); before the first receive call or use a timer with zero timeout to start the tasks after the event loop has started
  2. Use "subConfigurations": { "vibe-d": "win32" } in package.json to switch to the win32 driver, which doesn't suffer from the issue

Re: Concurrency

Thank you very much.
yield() at the beginning of the task function solves this issue.

Re: Concurrency

On Fri, 03 May 2013 18:09:16 GMT, Jack Applegame wrote:

Thank you very much.
yield() at the beginning of the task function solves this issue.

The cause was a __gshared field in Libevent2ManualEvent which caused the map of waiting threads to be reset. Works again now without the yield().

https://github.com/rejectedsoftware/vibe.d/commit/bf65a196055946184d165746ac29eee853a632ef