I would like to use Perl and/or Python to implement the following JavaScript pseudocode:
var c=0;
function timedCount()
{
c=c+1;
print("c=" + c);
if (c<10) {
var t;
t=window.setTimeout("timedCount()",100);
}
}
// main:
timedCount();
print("after timedCount()");
var i=0;
for (i=0; i<5; i++) {
print("i=" + i);
wait(500); //wait 500 ms
}
Now, this is a particularly unlucky example to choose as a basis - but I simply couldn't think of any other language to provide it in :) Basically, there is a 'main loop' and an auxiliary 'loop' (timedCount
), which both count at different rates: main with 500 ms period (implemented through a wait
), timedCount
with 100 ms period (implemented via setInterval
). However, JavaScript is essentially single-threaded, not multi-threaded - and so, there is no real sleep
/wait
/pause
or similar (see JavaScript Sleep Function - ozzu.com), which is why the above is, well, pseudocode ;)
By moving the main part to yet another setInterval
function, however, we can get a version of the code which can be pasted and ran in a browser shell like JavaScript Shell 1.4 (but not in a terminal shell like EnvJS/Rhino):
var c=0;
var i=0;
function timedCount()
{
c=c+1;
print("c=" + c);
if (c<10) {
var t;
t=window.setTimeout("timedCount()",100);
}
}
function mainCount() // 'main' loop
{
i=i+1;
print("i=" + i);
if (i<5) {
var t;
t=window.setTimeout("mainCount()",500);
}
}
// main:
mainCount();
timedCount();
print("after timedCount()");
... which results with something like this output:
i=1
c=1
after timedCount()
c=2
c=3
c=4
c=5
c=6
i=2
c=7
c=8
c=9
c=10
i=3
i=4
i=5
... that is, the main counts and auxiliary counts are 'interleaved'/'threaded'/'interspersed', with a main count on approx every five auxiliary counts, as anticipated.
And now the main question - what is the recommended way of doing this in Perl and Python, respectively?
- Additionally, do either Python or Perl offer facilities to implement the above with microsecond timing resolution in cross-platform manner?
Many thanks for any answers,
Cheers!
Here's another Perl example - without
fork
, withTime::HiRes
withusleep
(for main) andsetitimer
(for auxiliary) - however, it seems that thesetitimer
needs to be retriggered - and even then, it seems just to run through the commands (not actually wait):EDIT: Here is even a simpler example with
setitimer
, which I cannot get to time out correctly (reardless of ITIMER_VIRTUAL or ITIMER_REAL), it simply runs as fast as possible:The simplest and most general way I can think of doing this in Python is to use Twisted (an event-based networking engine) to do this.
Twisted has a highly efficient and stable event-loop implementation called the reactor. This makes it single-threaded and essentially a close analogue to Javascript in your example above. The reason I'd use it to do something like your periodic tasks above is that it gives tools to make it easy to add as many complicated periods as you like.
It also offers more tools for scheduling task calls you might find interesting.
For Perl, for default capabilities, in How do I sleep for a millisecond in Perl?, it is stated that:
sleep
has resolution of a secondselect
accepts floating point, the decimal part interpreted as millisecondsAnd then for greater resolution, one can use
Time::HiRes
module, and for instance,usleep()
.If using the default Perl capabilities, the only way to achieve this 'threaded' counting seems to be to 'fork' the script, and let each 'fork' act as a 'thread' and do its own count; I saw this approach on Perl- How to call an event after a time delay - Perl - and the below is a modified version, made to reflect the OP:
A simple python implementation using the standard library's
threading.Timer
:Alternatively, you can't go wrong using an asynchronous library like twisted (demonstrated in this answer) or gevent (there are quite a few more out there).