DMD 1.022 and 2.005 releases - what's wrong with threading?

downs default_357-line at yahoo.de
Sun Oct 7 01:49:46 PDT 2007


David Brown wrote:
> This is certainly not what I would hope to ever find in a normal piece of
> threading code.  Let's pretend I have condition variables (.NET style), and
> see what it looks like:
> 
>   void put(T t)
>   {
>     synchronized (this) {
>       buffer ~= t;
>       conditionSignal (this);
>     }
>   }
> 
>   void get(T t)
>   {
>     synchronized (this) {
>       while (buffer.length == 0)
>         conditionWait (this);
>       auto res=buffer[0];
>       buffer = buffer[1..$];
>       return res;
>     }
>   }
> 
> where conditionSignal and conditionWait are as defined by .NET or posix
> Pthreads (with the condition variable and mutex as part of each object).
> This can be implemented directly on top of both Windows and Linux, meaning
> it won't hurt performance.  It's a whole lot easier to use correctly, and
> doesn't obscure the code quite as much.  (Yes, the conditionWait is inside
> of the synchronized, it is _required_ to be there, that's why it is so much
> easier to use).  In fact, if a thread was allowed to 'pause()' itself
> inside of a synchronized section and that meant it would atomically release
> the critical section and pause, and then regain the critical section on
> resume, the Phobos version could be made much simpler.
> 
> Other implementations using semaphores aren't much more difficult.
> 
> I still would say this is too primitive for most uses, and higher level
> constructs can be made.  But, only the useful primitives need to be in the
> thread library itself.
> 
> David

Okay, let's try this again.
I'm not sure if the following code will work, seeing as I never actually
tested it. I'm fairly optimistic though ^^

module test4;

import std.thread;
class Lock
{
  private
  {
    Thread locked;
    bool[Thread] sleeping;
    bool signalling=false;
  }
  void lock(Object what)
  {
    while (locked !is Thread.getThis) synchronized(what)
      if (!locked) locked = Thread.getThis;
  }
  void unlock()
  in
  {
    assert (Thread.getThis is locked);
  }
  body
  {
    locked = null;
  }
  void synchronize(Object what, void delegate() dg)
  {
    lock(what);
    scope(exit) unlock;
    dg();
  }
  void conditionWait(Object what)
  {
    synchronized(this) sleeping[Thread.getThis]=true;
    unlock;
    // prevent accidental resume
    while (!signalling) Thread.getThis.pause;
    synchronized(this) sleeping.remove(Thread.getThis);
    lock(what);
  }
  void conditionSignal()
  {
    synchronized(this)
    {
      signalling=true;
      scope(exit) signalling=false;
      foreach (thr, bogus; sleeping) thr.resume;
    }
  }
}

class UnBoundedBuffer(T) {
  private T[] buffer;
  Lock lock; this() { lock=new Lock; }
  void put(T t)
  {
    lock.synchronize(this, {
      buffer ~= t;
      lock.conditionSignal;
    });
  }
  T get()
  {
    T res=void;
    lock.synchronize(this, {
      while (!buffer.length)
        lock.conditionWait(this);
      res = buffer[0];
      buffer=buffer[1..$];
    });
    return res;
  }
}

void main() {
  auto bb=new UnBoundedBuffer!(int);
}



More information about the Digitalmars-d mailing list