www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Implementing a timer using threads

reply Dennis Kempin <dennis xardias.net> writes:
Hi,

i just started to learn D (have been using c++ or java up to now) and am
wondering how to implement some kind of timer, a thread that calls a
delegate every n seconds.
This was my first idea (without flags for stopping the timer etc):

class Timer: Thread
{
        int run()
        {
                while(true)
                {
                        this.wait(1000); // wait one second
                        writefln("one second passed");
                }
                return 0;
        }
}

But writefln never gets executed, because this.wait is used to wait for
other threads than the current one. Is there any other way to get let
Thread sleep for some seconds (I know that there is a Sleep function for
Win32, but a platform independend way would be very great).

regards
Dennis
Jan 27 2007
next sibling parent reply Heinz <billgates microsoft.com> writes:
Dennis Kempin Wrote:

 Hi,
 
 i just started to learn D (have been using c++ or java up to now) and am
 wondering how to implement some kind of timer, a thread that calls a
 delegate every n seconds.
 This was my first idea (without flags for stopping the timer etc):
 
 class Timer: Thread
 {
         int run()
         {
                 while(true)
                 {
                         this.wait(1000); // wait one second
                         writefln("one second passed");
                 }
                 return 0;
         }
 }
 
 But writefln never gets executed, because this.wait is used to wait for
 other threads than the current one. Is there any other way to get let
 Thread sleep for some seconds (I know that there is a Sleep function for
 Win32, but a platform independend way would be very great).
 
 regards
 Dennis

You could insert a block of asm code. Look here http://www.digitalmars.com/d/iasm.html for valid opcodes. Here http://www.acm.uiuc.edu/sigmil/talks/shellcode/sleep.asm is an approach. This method is platform independant but not architecture independant, anyway, most computers processors are x86. Good luck.
Jan 28 2007
next sibling parent reply Dennis Kempin <dennis xardias.net> writes:
Heinz wrote: 
 You could insert a block of asm code. Look here
 http://www.digitalmars.com/d/iasm.html for valid opcodes. Here
 http://www.acm.uiuc.edu/sigmil/talks/shellcode/sleep.asm is an approach.
 
 This method is platform independant but not architecture independant,
 anyway, most computers processors are x86.
 
 Good luck.

Hi Heinz, thanks for your reply. I tried the following solution: int timerFunction() { while(true) { writefln("a"); asm { xor EAX,EAX; mov EBX,0x77e61bea; mov AX,1000; push EAX; call EBX; } } return 0; } but the result is a crash without any error message or warning. As the comment of the asm code says "windows shellcode" i think it simply uses the windows internel Sleep method. Still no way to make the thread go sleep in linux. Maybe I just should use linux/windows c API methods and insert a platform fork. I will report here if i got a working solution.. Maybe I am not the only one who needs timing. regards Dennis
Jan 29 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Dennis Kempin wrote:
 ...
 Maybe I just should use linux/windows c API methods and insert a platform
 fork. I will report here if i got a working solution.. Maybe I am not the
 only one who needs timing. 

No, I suspect you're probably not the only one. Seems like most Thread apis I've seen have had some sort of Sleep() method. Not sure why Phobos' doesn't. Hopefully Tango will have a sleep(). --bb
Jan 29 2007
parent Don Clugston <dac nospam.com.au> writes:
Bill Baxter wrote:
 Dennis Kempin wrote:
  > ...
 Maybe I just should use linux/windows c API methods and insert a platform
 fork. I will report here if i got a working solution.. Maybe I am not the
 only one who needs timing. 

No, I suspect you're probably not the only one. Seems like most Thread apis I've seen have had some sort of Sleep() method. Not sure why Phobos' doesn't. Hopefully Tango will have a sleep().

It does.
 
 --bb

Jan 30 2007
prev sibling parent Dennis Kempin <dennis xardias.net> writes:
okay here we go, i have a simple conditional compilation added to use
windows Sleep or linux usleep function.
Maybe someone has use for this simple class. You can decide if the timed
event shall be called once or forever until the process/thread is
terminated.

I have not tested this in windows but it "should" work ;)

regards Dennis

import std.thread;

version(Windows)
{
        extern (C)
        {
                void Sleep(int);        
        }
}

version(linux)
{
        extern (C)
        {
                void usleep(int);       
        }
}

class Timer: Thread
{
        private void delegate() action;
        private int waitTime;
        private bit autoRestart;

        this(int waitTime, void delegate() action, bit autoRestart=false)
        {
                this.action = action;
                this.waitTime = waitTime;
                this.autoRestart = autoRestart;
        }

        protected this(int waitTime, bit autoRestart=false)
        {
                this.waitTime = waitTime;
                this.autoRestart = autoRestart;
        }

        override int run()
        {
                sleep(waitTime);
                execute();
                while(autoRestart)
                {
                        sleep(waitTime);
                        execute();
                }
                return 0;
        }

        void execute()
        {
                action();
        }

        private void sleep(int time)
        {
                version(Windows)
                {
                        Sleep(time);
                }
                
                version(linux)
                {
                        usleep(time*1000);
                }
        }
}
Jan 29 2007
prev sibling parent reply BCS <BCS pathlink.com> writes:
Dennis Kempin wrote:
 Hi,
 
 i just started to learn D (have been using c++ or java up to now) and am
 wondering how to implement some kind of timer, a thread that calls a
 delegate every n seconds.
 This was my first idea (without flags for stopping the timer etc):
 
 class Timer: Thread
 {
         int run()
         {
                 while(true)
                 {
                         this.wait(1000); // wait one second
                         writefln("one second passed");
                 }
                 return 0;
         }
 }
 
 But writefln never gets executed, because this.wait is used to wait for
 other threads than the current one. Is there any other way to get let
 Thread sleep for some seconds (I know that there is a Sleep function for
 Win32, but a platform independend way would be very great).
 
 regards
 Dennis

I'd try something with Thread.yield and a time check. Example (insert your favorite time API) class Timer : Thread { run() { auto next = CurrentTime()+inc; while(running) { auto now = CurrentTime(); if(now > next) { dg(); next += inc; } else this.yield(); } } }
Jan 29 2007
parent reply Max Samukha <samukha voliacable.com> writes:
On Mon, 29 Jan 2007 10:55:37 -0800, BCS <BCS pathlink.com> wrote:

Dennis Kempin wrote:
 Hi,
 
 i just started to learn D (have been using c++ or java up to now) and am
 wondering how to implement some kind of timer, a thread that calls a
 delegate every n seconds.
 This was my first idea (without flags for stopping the timer etc):
 
 class Timer: Thread
 {
         int run()
         {
                 while(true)
                 {
                         this.wait(1000); // wait one second
                         writefln("one second passed");
                 }
                 return 0;
         }
 }
 
 But writefln never gets executed, because this.wait is used to wait for
 other threads than the current one. Is there any other way to get let
 Thread sleep for some seconds (I know that there is a Sleep function for
 Win32, but a platform independend way would be very great).
 
 regards
 Dennis

I'd try something with Thread.yield and a time check. Example (insert your favorite time API) class Timer : Thread { run() { auto next = CurrentTime()+inc; while(running) { auto now = CurrentTime(); if(now > next) { dg(); next += inc; } else this.yield(); } } }

Be careful about Thread.yield under Windows. It calls Sleep(0) that won't yield to a thread of a lower priority. In case of the proposed timer this is not a problem except it will use 100% of CPU and won't let any lower priority thread run but if you use something like a spin lock waiting for a lower priority thread to release it, the lock will never be released. You could use Sleep(1) or SwitchToThread() on single processor systems. And you should use 'rep nop' for hyperthreaded CPUs. A platform independent way to put a thread to sleep using Phobos: import std.c.time; sleep(1);// secs msleep(1000); millisecs http://www.digitalmars.com/d/archives/digitalmars/D/29144.html
Jan 30 2007
parent reply BCS <BCS pathlink.com> writes:
Max Samukha wrote:
 On Mon, 29 Jan 2007 10:55:37 -0800, BCS <BCS pathlink.com> wrote:
 
 
Dennis Kempin wrote:

Hi,

i just started to learn D (have been using c++ or java up to now) and am
wondering how to implement some kind of timer, a thread that calls a
delegate every n seconds.
This was my first idea (without flags for stopping the timer etc):

class Timer: Thread
{
        int run()
        {
                while(true)
                {
                        this.wait(1000); // wait one second
                        writefln("one second passed");
                }
                return 0;
        }
}

But writefln never gets executed, because this.wait is used to wait for
other threads than the current one. Is there any other way to get let
Thread sleep for some seconds (I know that there is a Sleep function for
Win32, but a platform independend way would be very great).

regards
Dennis

I'd try something with Thread.yield and a time check. Example (insert your favorite time API) class Timer : Thread { run() { auto next = CurrentTime()+inc; while(running) { auto now = CurrentTime(); if(now > next) { dg(); next += inc; } else this.yield(); } } }

Be careful about Thread.yield under Windows. It calls Sleep(0) that won't yield to a thread of a lower priority. In case of the proposed timer this is not a problem except it will use 100% of CPU and won't let any lower priority thread run but if you use something like a spin lock waiting for a lower priority thread to release it, the lock will never be released.

Ouch, I hadn't head of that.
 You could use Sleep(1) or SwitchToThread() on
 single processor systems. And you should use 'rep nop' for
 hyperthreaded CPUs.
 
 A platform independent way to put a thread to sleep using Phobos:
 import std.c.time;
 
 sleep(1);// secs
 msleep(1000); millisecs
 http://www.digitalmars.com/d/archives/digitalmars/D/29144.html
 
  

However that gives the problem of not accounting for the run time of the threads "action". Not alwyas a problem, but... What is thread suposed to do to "kill time"? e.i. let other things run with out using up much CPU but keep poling the thread. while(NothingToDo()) thisThread.MarkTime();
Jan 30 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
BCS wrote:
 Max Samukha wrote:
 A platform independent way to put a thread to sleep using Phobos:
 import std.c.time;

 sleep(1);// secs
 msleep(1000); millisecs
 http://www.digitalmars.com/d/archives/digitalmars/D/29144.html

  

However that gives the problem of not accounting for the run time of the threads "action". Not alwyas a problem, but... What is thread suposed to do to "kill time"? e.i. let other things run with out using up much CPU but keep poling the thread. while(NothingToDo()) thisThread.MarkTime();

Couldn't you just do something like: ----- time_t nextEvent = currentTime() + interval; time_t now; while (true) { while ((now = currentTime()) < nextEvent) sleep(nextEvent - now); // or msleep, if you prefer nextEvent += interval; action(); } ----- (where time_t is some type suitable for measuring time) That should sleep until it's time, right?
Jan 30 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Frits,

 BCS wrote:
 
 while(NothingToDo())
 thisThread.MarkTime();

Couldn't you just do something like: ----- time_t nextEvent = currentTime() + interval; time_t now; while (true) { while ((now = currentTime()) < nextEvent) sleep(nextEvent - now); // or msleep, if you prefer nextEvent += interval; action(); } ----- (where time_t is some type suitable for measuring time) That should sleep until it's time, right?

That would work if the end condition is a clock time. It's not quite the same problem but what about if you are waiting for some logical condition?
Jan 30 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
BCS wrote:
 Reply to Frits,
 
 BCS wrote:

 while(NothingToDo())
 thisThread.MarkTime();

Couldn't you just do something like: ----- time_t nextEvent = currentTime() + interval; time_t now; while (true) { while ((now = currentTime()) < nextEvent) sleep(nextEvent - now); // or msleep, if you prefer nextEvent += interval; action(); } ----- (where time_t is some type suitable for measuring time) That should sleep until it's time, right?

That would work if the end condition is a clock time. It's not quite the same problem but what about if you are waiting for some logical condition?

Then you pick a reasonable poll interval and do something like this: --- time_t nextCheck = currentTime(); while(true) { while (!condition()) { nextCheck += poll_interval; sleep(nextCheck - currentTime()); } action(); } ---
Jan 30 2007
parent BCS <ao pathlink.com> writes:
Reply to Frits,

 Then you pick a reasonable poll interval and do something like this:

Man, wouldn't it be better if the OS writers would just put in a proper yield?
Jan 30 2007