Timer

Joerg Joergonson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jun 21 16:15:58 PDT 2016


Does D have a timer? I've tried some user code and it doesn't 
work. I need to be able to have a delegate called periodically. 
(fiber or thread, doesn't matter)



https://github.com/Dav1dde/BraLa/blob/master/brala/utils/thread.d




module lib.mTimer;

private
{
     import std.traits : ParameterTypeTuple, isCallable;
     import std.string : format;
     import core.time : Duration;
     import core.sync.mutex : Mutex;
     import core.sync.condition : Condition;


     import std.stdio : stderr;
}

public import core.thread;


private enum CATCH_DELEGATE = `
     delegate void() {
         try {
             fun();
         } catch(Throwable t) {
                 stderr.writefln("--- Exception in Thread: \"%s\" 
---".format(this.name));
                 stderr.writeln(t.toString());
                 stderr.writefln("--- End Exception in Thread 
\"%s\" ---".format(this.name));

             throw t;
         }
     }
`;

class VerboseThread : Thread
{
     this(void function() fun, size_t sz = 0)
	{
         super(mixin(CATCH_DELEGATE), sz);
     }

     this(void delegate() fun, size_t sz = 0)
	{
         super(mixin(CATCH_DELEGATE), sz);
     }
}

class TTimer(T...) : VerboseThread
{
     static assert(T.length <= 1);
     static if(T.length == 1)
	{
         static assert(isCallable!(T[0]));
         alias ParameterTypeTuple!(T[0]) Args;
     } else
	{
         alias T Args;
     }

     public Duration interval;
     protected Args args;
     protected void delegate(Args) func;

     protected Event finished;
     @property bool is_finished() { return finished.is_set; }


     this(Duration interval, void delegate(Args) func, Args args)
	{
         super(&run);

         finished = new Event();

         this.interval = interval;
         this.func = func;

         static if(Args.length) {
             this.args = args;
         }
     }

     final void cancel()
	{
         finished.set();
     }

     protected void run()
	{
         finished.wait(interval);

         if(!finished.is_set)
		{
             func(args);
         }

         finished.set();
     }

}




class Event
{
     protected Mutex mutex;
     protected Condition cond;

     protected bool flag;
     @property bool is_set() { return flag; }

     this()
	{
         mutex = new Mutex();
         cond = new Condition(mutex);

         flag = false;
     }

     void set()
	{
         mutex.lock();
         scope(exit) mutex.unlock();

         flag = true;
         cond.notifyAll();
     }

     void clear()
	{
         mutex.lock();
         scope(exit) mutex.unlock();

         flag = false;
     }

     bool wait(T...)(T timeout) if(T.length == 0 || (T.length == 1 
&& is(T[0] : Duration)))
	{
         mutex.lock();
         scope(exit) mutex.unlock();

         bool notified = flag;
         if(!notified)
		{
             static if(T.length == 0)
			{
                 cond.wait();
                 notified = true;
             } else
			{
                 notified = cond.wait(timeout);
             }
         }
         return notified;
     }
}


More information about the Digitalmars-d-learn mailing list