Skip to content

Instantly share code, notes, and snippets.

@colrichie
Last active May 26, 2025 04:49
Show Gist options
  • Save colrichie/019fa2b75b9842d2c06cbfc51f4115e6 to your computer and use it in GitHub Desktop.
Save colrichie/019fa2b75b9842d2c06cbfc51f4115e6 to your computer and use it in GitHub Desktop.
Various Implementations of the "waitll" method and the Punctual Class
#!/bin/sh
#####################################################################
#
# A Sample Program of waitill for AWK (except mawk)
#
# You can make a more accurate loop by using the "waitill" function (*1)
# than by using the 'system("sleep n")' function simply.
#
# The following AWK script prints a message every 0.5 ms accurately.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# (*1) To run this script, you must install the "Tokideli" command set
# in advance. "Tokideli" is published on the following website.
# https://github.com/ShellShoccar-jpn/tokideli
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
#####################################################################
exit_trap() {
set -- ${1:-} $? # $? is set as $1 if no argument given
trap '' EXIT HUP INT QUIT PIPE ALRM TERM
[ -d "${Tmp:-}" ] && rm -rf "${Tmp%/*}/_${Tmp##*/_}"
trap - EXIT HUP INT QUIT PIPE ALRM TERM
exit $1
}
error_exit() { ${2+:} false && echo "${0##*/}: $2" 1>&2; exit $1; }
case "$(awk -W interactive 'BEGIN{exit;}' 2>&1)" in
'') error_exit 1 'Your AWK implementation is mawk, and not supported :-(';;
esac
trap 'exit_trap' EXIT HUP INT QUIT PIPE ALRM TERM
Tmp=`mktemp -d -t "_${0##*/}.$$.XXXXXXXXXXX"` || error_exit 1 'Failed to mktemp'
mkfifo "$Tmp/tscat" || error_exit 1 'Failed to mkfifo (tscat)'
mkfifo "$Tmp/linets" || error_exit 1 'Failed to mkfifo (linets)'
awk -v __PUNCTUAL_FIFO_t="$Tmp/tscat" -v __PUNCTUAL_FIFO_l="$Tmp/linets" '
function new_punctual(mode, __dummy) {
__PUNCTUAL_CMD_t = "tscat -1z " __PUNCTUAL_FIFO_t;
__PUNCTUAL_CMD_t | getline __dummy;
mode = (mode!="") ? mode : "9e";
__PUNCTUAL_CMD_l = "linets -1" mode " " __PUNCTUAL_FIFO_l;
__PUNCTUAL_CMD_l | getline __dummy;
print 1 > __PUNCTUAL_FIFO_l; fflush();
__PUNCTUAL_CMD_l | getline WT_EPOCH;
}
function now(__dummy) {
print 1 > __PUNCTUAL_FIFO_l; fflush();
__PUNCTUAL_CMD_l | getline __dummy;
return substr(dummy,1,index(__dummy," ")-1);
}
function get_epoch() { return WT_EPOCH; }
function reset_epoch(__dummy) {
print -1 > __PUNCTUAL_FIFO_t; fflush();
__PUNCTUAL_CMD_t | getline __dummy;
print 1 > __PUNCTUAL_FIFO_l; fflush();
__PUNCTUAL_CMD_l | getline WT_EPOCH;
return WT_EPOCH;
}
function waitill(sec_to_ret, __dummy) {
print sec_to_ret > __PUNCTUAL_FIFO_t; fflush();
__PUNCTUAL_CMD_t | getline __dummy;
}
function delete_punctual() {
close(__PUNCTUAL_FIFO_t); close(__PUNCTUAL_CMD_t );
close(__PUNCTUAL_FIFO_l); close(__PUNCTUAL_CMD_l );
}
BEGIN {
new_punctual();
print "Set the epoch.";
for (t=0.5; t<=5.0; t+=0.5) {
waitill(t);
printf("%.1f second(s) have passed.\n",t);
}
delete_punctual();
}
'
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for C11 with POSIX
//
// You can make an accurate interval loop a little simpler by using the
// "waitill()" function than by using the "clock_nanosleep()" function.
//
// The following C11 program prints a message every 0.5 ms accurately.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
struct timespec wt_epoch;
int new_punctual(void) {
return clock_gettime(CLOCK_REALTIME,&wt_epoch);
}
int now(struct timespec* pts) {
if (pts==NULL) {errno=EINVAL; return -1;}
return clock_gettime(CLOCK_REALTIME,pts);
}
int reset_epoch() {
return clock_gettime(CLOCK_REALTIME,&wt_epoch);
}
int waitill_d(double sec_to_ret) {
struct timespec due={0};
double i,d;
d=modf(sec_to_ret,&i);
due.tv_nsec=wt_epoch.tv_nsec+(long)(d*1000000000L);
if (due.tv_nsec>999999999L) {due.tv_nsec-=1000000000L;due.tv_sec++;}
due.tv_sec+=wt_epoch.tv_sec+(time_t)i;
if (due.tv_sec<wt_epoch.tv_sec) {
due.tv_sec =(time_t)((~(time_t)0)>>1);
due.tv_nsec=999999999L;
}
return clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&due,NULL);
}
int waitill_ts(struct timespec *duration) {
int i;
struct timespec due={0};
if (duration==NULL) {errno=EINVAL; return -1;}
due.tv_sec =wt_epoch.tv_sec +duration->tv_sec;
due.tv_nsec=wt_epoch.tv_nsec+duration->tv_nsec;
if (due.tv_nsec>999999999L) {due.tv_nsec-=1000000000L;due.tv_sec++;}
if (due.tv_sec<wt_epoch.tv_sec) {
due.tv_sec =(time_t)((~(time_t)0)>>1);
due.tv_nsec=999999999L;
}
return clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&due,NULL);
}
#define waitill(duration) _Generic((duration), \
double : waitill_d, \
struct timespec* : waitill_ts \
)(duration)
int main(void) {
int i;
if ((i=new_punctual())!=0) {return i;}
printf("Set the epoch.\n");
for (double t=0.5; t<=5.0; t+=0.5) {
if ((i=waitill(t))!=0) {return i;}
printf("%.1f second(s) have passed.\n", t);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for C++17
//
// You can make an accurate interval loop a little simpler by using the
// "Punctual::waitill()" method than by using the
// "std::this_thread::sleep_until()" function.
//
// The following C++ program prints a message every 0.5 ms accurately.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
#include <chrono> // for std::chrono
#include <ctime> // for std::timespec
#include <thread> // for std::this_thread::sleep_until
#include <iostream>
class Punctual {
private:
using hr_clk = std::chrono::high_resolution_clock;
using time_point = hr_clk::time_point;
using duration = hr_clk::duration;
time_point wt_epoch;
public:
Punctual() {wt_epoch = hr_clk::now();}
time_point now() const {return hr_clk::now(); }
time_point get_epoch() const {return wt_epoch; }
time_point reset_epoch() {wt_epoch = hr_clk::now();
return wt_epoch; }
bool waitill(double sec_to_ret) {
using namespace std::chrono;
auto duration = std::chrono::duration<double>(sec_to_ret);
auto due = wt_epoch + duration_cast<hr_clk::duration>(duration);
std::this_thread::sleep_until(due);
return true;
}
bool waitill(duration duration_to_ret) {
auto due = wt_epoch + duration_to_ret;
std::this_thread::sleep_until(due);
return true;
}
bool waitill(std::timespec& ts) {
auto due = wt_epoch + std::chrono::seconds( ts.tv_sec )
+ std::chrono::nanoseconds(ts.tv_nsec);
std::this_thread::sleep_until(due);
return true;
}
};
int main() {
Punctual punc;
std::cout << "Set the epoch.\n";
for (double t=0.5; t<=5.0; t+=0.5) {
punc.waitill(t);
std::cout << t << " second(s) have passed." << std::endl;
}
return 0;
}
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for C#
//
// You can make a more accurate interval loop by using the
// "Punctual.Waitill()" method than by using both the "Thread.Sleep()"
// and "Task.Delay()" methods simply.
//
// The following C# program prints a message every 0.5 ms accurately.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
using System;
using System.Threading.Tasks;
public class Punctual {
private DateTime wtEpoch;
public Punctual() {wtEpoch = DateTime.Now;}
public DateTime Now() {return DateTime.Now; }
public DateTime GetEpoch() {return wtEpoch; }
public DateTime ResetEpoch() {wtEpoch = DateTime.Now;
return wtEpoch; }
public async Task<bool> Waitill(double secToRet) {
var due = wtEpoch.AddSeconds(secToRet);
var now = DateTime.Now;
var duration = due - now;
if (duration.TotalMilliseconds > 0) {
await Task.Delay(duration);
}
return true;
}
}
public class Example {
public static async Task Main() {
var punctual = new Punctual();
Console.WriteLine("Set the epoch.");
double t = 0.5;
double step = 0.5;
double max = 5.0;
while (t <= max) {
await punctual.Waitill(t);
Console.WriteLine($"{t:F1} second(s) have passed.");
t += step;
}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% A Sample Program of waitill() for Erlang
%
% You can make a more accurate interval loop by using the waitill()
% function of the Punctual module than by using the "timer:sleep()"
% function simply.
%
% The following Erlang program prints a message every 0.5 ms accurately.
%
% THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
%
% Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(punctual).
-export([start/0, example/0]).
%%%-------------------------
%%% Punctual module
%%%-------------------------
start() ->
spawn(fun() -> loop(os:system_time(nanosecond)) end).
loop(WtEpoch) ->
receive
{From, now} ->
NowNano = os:system_time(nanosecond),
From ! {self(), NowNano / 1_000_000_000},
loop(WtEpoch);
{From, get_epoch} ->
From ! {self(), WtEpoch / 1_000_000_000},
loop(WtEpoch);
{From, reset_epoch} ->
NewEpoch = os:system_time(nanosecond),
From ! {self(), NewEpoch / 1_000_000_000},
loop(NewEpoch);
{From, {waitill, SecToRet}} ->
Due = WtEpoch + trunc(SecToRet * 1_000_000_000),
Now = os:system_time(nanosecond),
Nsec = Due - Now,
( if
Nsec > 0 ->
timer:sleep(Nsec div 1_000_000);
true ->
ok
end ),
From ! {self(), true},
loop(WtEpoch)
end.
%%%-------------------------
%%% Usage
%%%-------------------------
example() ->
Pid = start(),
io:put_chars("Set the epoch.\n"),
loop(Pid, 0.5, 0.5, 5.0).
loop(_Pid, T, _Step, Max) when T > Max ->
ok;
loop(Pid, T, Step, Max) ->
Pid ! {self(), {waitill, T}},
receive
{Pid, true} ->
io:format("~.1f second(s) have passed.~n", [T]),
loop(Pid, T + Step, Step, Max)
end.
#####################################################################
#
# A Sample Program of waitill() for Elixer
#
# You can make a more accurate interval loop by using the waitill()
# function of the Punctual module than by using the "timer:sleep()"
# function simply.
#
# The following Elixer program prints a message every 0.5 ms accurately.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
#####################################################################
#-------------------------
# Punctual module
#-------------------------
defmodule Punctual do
def start do
spawn(fn -> loop(System.os_time(:nanosecond)) end)
end
defp loop(wt_epoch) do
receive do
{:now, from} ->
now = System.os_time(:nanosecond)
send(from, {:ok, now / 1_000_000_000})
loop(wt_epoch)
{:get_epoch, from} ->
send(from, {:ok, wt_epoch / 1_000_000_000})
loop(wt_epoch)
{:reset_epoch, from} ->
new_epoch = System.os_time(:nanosecond)
send(from, {:ok, new_epoch / 1_000_000_000})
loop(new_epoch)
{{:waitill, sec_to_ret}, from} ->
due = wt_epoch + trunc(sec_to_ret * 1_000_000_000)
now = System.os_time(:nanosecond)
nsec = due - now
if nsec > 0 do
:timer.sleep(div(nsec, 1_000_000))
end
send(from, {:ok, true})
loop(wt_epoch)
end
end
end
#-------------------------
# Usage
#-------------------------
defmodule Example do
def run do
pid = Punctual.start()
IO.puts("Set the epoch.")
loop(pid, 0.5, 0.5, 5.0)
end
defp loop(_pid, t, _step, max) when t > max, do: :ok
defp loop(pid, t, step, max) do
send(pid, {{:waitill, t}, self()})
receive do
{:ok, true} ->
IO.puts("#{Float.round(t, 1)} second(s) have passed.")
loop(pid, t + step, step, max)
end
end
end
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for Golang
//
// You can make a more accurate interval loop by using the "Punctual.Waitill()"
// method than by using the "time.Sleep()" function simply.
//
// The following Golang program can make the 0.5 ms interval printing
// more accurate than typical sample programs.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
package main
import (
"fmt"
"time"
)
type Punctual struct {wt_epoch time.Time}
func NewPunctual() *Punctual {return &Punctual{
wt_epoch: time.Now()}}
func (p *Punctual) Now() time.Time {return time.Now() }
func (p *Punctual) ResetEpoch() time.Time {p.wt_epoch=time.Now()
return p.wt_epoch }
func (p *Punctual) GetEpoch() time.Time {return p.wt_epoch }
func (p *Punctual) Waitill(secToRet float64) bool {
due := p.wt_epoch.Add(time.Duration(secToRet * float64(time.Second)))
now := time.Now()
if due.After(now) {
duration := due.Sub(now)
time.Sleep(duration)
}
return true
}
func main() {
p := NewPunctual()
fmt.Println("Set the epoch.")
for t := 0.5; t <= 5.0; t += 0.5 {
p.Waitill(t)
fmt.Printf("%.1f second(s) have passed.\n", t)
}
}
----------------------------------------------------------------------
--
-- A Sample Program of waitill() for Haskell
--
-- You can make a more accurate interval loop by using the "waitill()"
-- function than by using the "threadDelay()" function simply.
--
-- The following Haskell program can make the 0.5 ms interval printing
-- more accurate than typical sample programs.
--
-- THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
--
-- Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
--
----------------------------------------------------------------------
import Data.IORef
import Control.Concurrent (threadDelay)
import System.Clock
-- The "Punctual" type class
data Punctual = Punctual { wtEpoch :: TimeSpec }
new :: IO Punctual
new = do
t <- getTime Realtime
return $ Punctual { wtEpoch = t }
now :: IO Double
now = do
TimeSpec s n <- getTime Realtime
return $ fromIntegral s + fromIntegral n / 1e9
getEpoch :: Punctual -> IO Double
getEpoch (Punctual t) = do
let TimeSpec s n = t
return $ fromIntegral s + fromIntegral n / 1e9
resetEpoch :: IORef TimeSpec -> IO Double
resetEpoch ref = do
t@(TimeSpec s n) <- getTime Realtime
writeIORef ref t
return $ fromIntegral s + fromIntegral n / 1e9
waitill :: Punctual -> Double -> IO ()
waitill (Punctual secToRet) due = do
now <- getTime Realtime
let elapsed = fromIntegral (toNanoSecs (now - secToRet)) / 1e9
duration = due - elapsed
if duration > 0
then threadDelay (floor $ duration * 1e6)
else return ()
-- Example
main :: IO ()
main = do
punctual <- new
putStrLn "Set the epoch."
let loop t
| t > 5.0 = return ()
| otherwise = do
waitill punctual t
putStrLn $ show t ++ " second(s) have passed."
loop (t + 0.5)
loop 0.5
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for Java
//
// You can make a more accurate interval loop by using the "Punctual.waitill()"
// method than by using the "Thread.sleep()" function simply.
//
// The following Java program prints a message every 0.5 ms accurately.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
import java.time.Instant;
import java.time.Duration;
public class Punctual {
private Instant wtEpoch;
public Punctual() {this.wtEpoch = Instant.now();}
public Instant now() {return Instant.now();}
public Instant getEpoch() {return wtEpoch;}
public Instant resetEpoch() {this.wtEpoch = Instant.now();
return this.wtEpoch; }
public boolean waitill(double secToRet) {
Instant due = wtEpoch.plusNanos((long)(secToRet * 1_000_000_000));
Duration duration = Duration.between(Instant.now(), due);
if (!duration.isNegative()) {
try {
Thread.sleep(duration.toMillis(), duration.getNano() % 1_000_000);
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
return true;
}
}
/* If you try the Punctual.waitill(), make a file as "Main.java" and write
the following code. Then, compile them and run the Main.main() function.
```
public class Main {
public static void main(String[] args) {
Punctual punc = new Punctual();
System.out.println("Set the epoch.");
for (double t = 0.5; t <= 5.0; t += 0.5) {
punc.waitill(t);
System.out.printf("%.1f second(s) have passed.\n", t);
}
}
}
```
According to the Java language specification, it is impossible to show
you a sample program containing both the public Punctual class and the
Main class in one file. :(
*/
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for JavaScript
//
// You can make a more accurate interval loop by using the
// "Punctual.prototype.waitill()" method than by using the setTimeout()
// function simply.
//
// The following JavaScript program can make the 0.5 ms interval printing
// more accurate than typical sample programs.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
class Punctual {
#wt_epoch;
constructor() {this.#wt_epoch = new Date(); }
now() {return new Date(); }
get_epoch() {return new Date(this.#wt_epoch.getTime());}
reset_epoch() {this.#wt_epoch = new Date();
return new Date(this.#wt_epoch.getTime());}
async waitill(sec_since_epoch) {
if (typeof(sec_since_epoch)!=='number' || isNaN(sec_since_epoch)) {
throw new Error('"sec_since_epoch" argument must be a valid number');
}
const dt = new Date() - this.#wt_epoch;
const msec = sec_since_epoch*1000 - dt;
if (msec <= 0 ) {return;}
await new Promise(res => setTimeout(res,msec));
return true;
}
}
(async () => {
const punc = new Punctual();
console.log('Set the epoch.');
for (let t=0.5; t<=5.0; t+=0.5) {
await punc.waitill(t);
console.log(t+' second(s) have passed.');
}
})();
#!/bin/sh
exec php -q "$0" "$@"
<?php
######################################################################
#
# A Sample Program of waitill() for PHP
#
# You can make an accurate interval loop a little simpler by using the
# "Punctual::waitill()" method than by using the time_sleep_until().
#
# The following PHP script prints a message every 0.5 ms accurately.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
######################################################################
class Punctual {
private float $wt_epoch;
public function __construct() {
$this->wt_epoch = microtime(true);
}
public function now(): float {
return microtime(true);
}
public function get_epoch(): float {
return $this->wt_epoch;
}
public function reset_epoch(): float {
$this->wt_epoch = microtime(true);
return $this->wt_epoch;
}
public function waitill(float $sec_to_ret): bool {
$time_to_ret = $this->wt_epoch + $sec_to_ret;
$old_err_lv = error_reporting(E_ERROR | E_PARSE);
time_sleep_until($time_to_ret);
error_reporting($old_err_lv);
return true;
}
}
$punc = new Punctual();
echo "Set the epoch.\n";
for ($t=0.5; $t<=5.0; $t+=0.5) {
$punc->waitill($t);
printf("%.1f second(s) have passed.\n", $t);
}
?>
#!/usr/bin/env perl
######################################################################
#
# A Sample Program of waitill() for Perl
#
# You can make a more accurate interval loop by using the "Punctual::waitill()"
# function than by using the Time::HiRes::sleep() function simply.
#
# The following Perl script can make the 0.5 ms interval printing
# more accurate than typical sample programs.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
######################################################################
use strict;
use warnings;
package Punctual;
use Time::HiRes qw(time sleep);
sub new {my $class = shift;
my $self = {_wt_epoch => Time::HiRes::time()};
bless $self, $class;
return $self; }
sub now {return Time::HiRes::time(); }
sub get_epoch {my $self = shift; return $self->{_wt_epoch}; }
sub reset_epoch {my $self = shift;
$self->{_wt_epoch} = Time::HiRes::time();
return $self->{_wt_epoch}; }
sub waitill {my ($self, $sec_to_ret) = @_;
my $due = $self->{_wt_epoch}+$sec_to_ret;
my $now = Time::HiRes::time();
my $sec = $due-$now;
if ($sec > 0) {Time::HiRes::sleep($sec);}
return 1; }
1;
package main;
my $punc = Punctual->new();
print "Set the epoch.\n";
for (my $t=0.5; $t<=5.0; $t+=0.5) {
$punc->waitill($t);
printf("%.1f second(s) have passed.\n",$t);
}
#!/usr/bin/env python3
# ####################################################################
#
# A Sample Program of waitill() for Python3
#
# You can make a more accurate interval loop by using the "Punctual.waitill()"
# function than by using the time.sleep() function simply.
#
# The following Python script can make the 0.5 ms interval printing
# more accurate than typical sample programs.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
# ####################################################################
import datetime
import time
class Punctual:
_wt_epoch = 0
def __init__(self):
self._wt_epoch = datetime.datetime.now()
return
def now(self):
return datetime.datetime.now()
def get_epoch(self):
return self._wt_epoch.replace(minute=0)
def reset_epoch(self):
self._wt_epoch = datetime.datetime.now()
return self._wt_epoch.replace(minute=0)
def waitill(self, sec_since_epoch):
try:
if not isinstance(sec_since_epoch, (int, float)):
raise TypeError(f'"sec_since_epoch" must be int or float')
dt = datetime.datetime.now() - self._wt_epoch
sec = sec_since_epoch - dt.total_seconds()
if sec > 0:
time.sleep(sec)
return True
except (ValueError, TypeError):
return False
punc = Punctual()
print("Set the epoch.")
for i in range(10):
t = (i+1) * 0.5
punc.waitill(t)
print("{:03.1f} second(s) have passed.".format(t))
#!/usr/bin/env ruby
######################################################################
#
# A Sample Program of waitill() for Ruby
#
# You can make a more accurate interval loop by using the "Punctual.waitill()"
# function than by using the time.sleep() function simply.
#
# The following Ruby script can make the 0.5 ms interval printing
# more accurate than typical sample programs.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
######################################################################
class Punctual
def initialize
@wt_epoch = Time.now
end
def now
Time.now
end
def get_epoch
@wt_epoch.dup
end
def reset_epoch
@wt_epoch = Time.now
@wt_epoch.dup
end
def waitill(sec_to_ret)
dt = Time.now - @wt_epoch
sec = sec_to_ret - dt
sleep(sec) if sec > 0
true
end
end
punc = Punctual.new
puts "Set the epoch."
0.5.step(5.0, 0.5) do |t|
punc.waitill(t)
printf("%.1f second(s) have passed.\n",t)
end
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for Rust
//
// You can make a little simpler interval loop by using the
// "Punctual::waitill()" method than by using the
// "std::thread::sleep::sleep()" function simply.
//
// The following Rust program prints a message every 0.5 ms accurately.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
use std::time::{Duration, Instant};
use std::thread::sleep;
struct Punctual {wt_epoch: Instant}
impl Punctual {
fn new() -> Self {Punctual {wt_epoch: Instant::now()}}
fn now(&self) -> Instant {Instant::now() }
fn get_epoch(&self) -> Instant {self.wt_epoch }
fn reset_epoch(&mut self) -> Instant {self.wt_epoch=Instant::now();
self.wt_epoch }
fn waitill(&self, sec_to_ret: f64) -> bool {
let due = self.wt_epoch + Duration::from_secs_f64(sec_to_ret);
let now = Instant::now();
if due > now {sleep(due - now)}
true
}
}
fn main() {
let mut punc = Punctual::new();
println!("Set the epoch.");
let mut t = 0.5;
while t <= 5.0 {
punc.waitill(t);
println!("{:.1} second(s) have passed.", t);
t += 0.5;
}
}
#!/bin/sh
#####################################################################
#
# A Sample Program of waitill for shell script #1
#
# You can make a more accurate loop by using the "waitill" command (*1)
# than by using the sleep command simply.
#
# The following shell script prints a message every 0.5 ms accurately.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# (*1) To run this script, you must install the "Tokideli" command set
# in advance. "Tokideli" is published on the following website.
# https://github.com/ShellShoccar-jpn/tokideli
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
#####################################################################
now() { [ $# -eq 0 ] && set -- 9e; herewego -$1 0; }
get_epoch() { echo $WT_EPOCH; }
reset_epoch() { export WT_EPOCH=+$(now); echo $WT_EPOCH; }
new_punctual() { export WT_EPOCH=+$(now); }
new_punctual
echo 'Set the epoch.'
for t in 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0; do
waitill -e $t
echo "$t second(s) have passed."
done
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' A Sample Program of waitill() for VB.NET
'
' You can make a more accurate interval loop by using the
' "Punctual.Waitill()" method than by using the "Thread.Sleep()"
' method simply.
'
' The following VB.NET program prints a message every 0.5 ms accurately.
'
' THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
'
' Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Imports System
Imports System.Threading
Public Class Punctual
Private wtEpoch As DateTime
Public Sub New()
wtEpoch = DateTime.Now
End Sub
Public Function Now() As DateTime
Return DateTime.Now
End Function
Public Function GetEpoch() As DateTime
Return wtEpoch
End Function
Public Function ResetEpoch() As DateTime
wtEpoch = DateTime.Now
Return wtEpoch
End Function
Public Function Waitill(secToRet As Double) As Boolean
Dim due As DateTime = wtEpoch.AddSeconds(secToRet)
Dim now As DateTime = DateTime.Now
Dim duration As TimeSpan = due - now
If duration.TotalMilliseconds > 0 Then
Thread.Sleep(duration)
End If
Return True
End Function
End Class
Module Example
Sub Main()
Dim punc As New Punctual()
Console.WriteLine("Set the epoch.")
For t As Double = 0.5 To 5.0 Step 0.5
punc.Waitill(t)
Console.WriteLine("{0:F1} second(s) have passed.", t)
Next
End Sub
End Module
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' A Sample Program of waitill() for VBA
'
' You can make an accurate interval loop a little simpler by using the
' "Waitill()" function than by using the"Application.Wait()" function.
'
' The following VBA program prints a message every 1 s accurately.
'
' THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
'
' Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim wtEpoch As Date
Sub NewPunctual()
wtEpoch = Now
End Sub
Function GetEpoch() As Date
GetEpoch = wtEpoch
End Function
Function ResetEpoch() As Date
wtEpoch = Now
ResetEpoch = wtEpoch
End Function
Function Waitill(ByVal secToRet As Double) As Boolean
Dim targetTime As Date
due = wtEpoch + TimeSerial(0, 0, secToRet)
If Now < due Then
Application.Wait due
End If
Waitill = True
End Function
Sub ExampleUsage()
Call NewPunctual
Debug.Print "Set the epoch."
Dim t As Integer
For t = 1 To 5 Step 1
Call Waitill(t)
Debug.Print Format(t, "0") & " second(s) have passed."
Next t
End Sub
#!/bin/sh
#####################################################################
#
# A Sample Program of waitill for shell script #2
# (#2 is better than #1 if you want to make a shorter interval loop
# than about 0.1 second)
#
# You can make a more accurate loop by using the "waitill" command (*1)
# than by using the sleep command simply.
#
# The following shell script prints a message every 0.5 ms accurately.
#
# THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
#
# (*1) To run this script, you must install the "Tokideli" command set
# in advance. "Tokideli" is published on the following website.
# https://github.com/ShellShoccar-jpn/tokideli
#
# Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
#
#####################################################################
exit_trap() {
set -- ${1:-} $? # $? is set as $1 if no argument given
trap '' EXIT HUP INT QUIT PIPE ALRM TERM
[ -d "${Tmp:-}" ] && rm -rf "${Tmp%/*}/_${Tmp##*/_}"
trap - EXIT HUP INT QUIT PIPE ALRM TERM
[ -n "${PID_linets:-}" ] && kill $PID_linets
[ -n "${PID_tscat:-}" ] && kill $PID_tscat
exit $1
}
error_exit() { ${2+:} false && echo "${0##*/}: $2" 1>&2; exit $1; }
trap 'exit_trap' EXIT HUP INT QUIT PIPE ALRM TERM
Tmp=`mktemp -d -t "_${0##*/}.$$.XXXXXXXXXXX"` || error_exit 1 'Failed to mktemp'
mkfifo "$Tmp/tscat2sh" || error_exit 1 'Failed to mkfifo (cmd2sh)'
mkfifo "$Tmp/sh2tscat" || error_exit 1 'Failed to mkfifo (sh2cmd)'
mkfifo "$Tmp/linets2sh" || error_exit 1 'Failed to mkfifo (cmd2sh)'
mkfifo "$Tmp/sh2linets" || error_exit 1 'Failed to mkfifo (sh2cmd)'
new_punctual() {
[ $# -eq 0 ] && set -- 9e
_punctual_mode=$1
read _punctual_tmp < "$Tmp/tscat2sh" &
tscat -1z "$Tmp/sh2tscat" > "$Tmp/tscat2sh" &
PID_tscat=$!
export WT_EPOCH=$(herewego -$1 0)
exec 3>"$Tmp/sh2tscat"
read _punctual_tmp < "$Tmp/linets2sh" &
linets -1$1 "$Tmp/sh2linets" > "$Tmp/linets2sh" &
PID_linets=$!
exec 4>"$Tmp/sh2linets"
}
now() {
echo 1>&4
read _punctual_tmp <"$Tmp/linets2sh"
echo "$_punctual_tmp"
}
get_epoch() {
echo $WT_EPOCH;
}
reset_epoch() {
echo -1 1>&3
read _punctual_tmp <"$Tmp/tscat2sh"
export WT_EPOCH=$(herewego -$_punctual_mode 0)
}
waitill() {
[ $# -eq 0 ] && return 0
echo $1 1>&3
read _punctual_tmp <"$Tmp/tscat2sh"
}
new_punctual 3I
echo 'Set the epoch.'
for t in 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0; do
waitill $t
echo "$t second(s) have passed."
sleep 0.1
done
//////////////////////////////////////////////////////////////////////
//
// A Sample Program of waitill() for Arduino
//
// You can make a more accurate loop by using the "waitill()" function
// than by using the delay() function simply.
//
// The following Arduino sketch can make the 0.5 ms LED blinking more
// accurate than typical sample programs.
//
// THIS SAMPLE IS DEDICATED TO PUNCTUAL PROGRAMMERS IN THE WORLD!
//
// Written by Shell-Shoccar Japan (@shellshoccarjpn) on 2025-05-25
//
//////////////////////////////////////////////////////////////////////
bool waitill(unsigned long millisec_to_ret);
unsigned long WT_EPOCH; // To set the reference time (epoch time)
unsigned long t; // To set the milliseconds after the WT_EPOCH
// (It is for the argument for waitill())
void setup() {
pinMode(13,OUTPUT); // LED pin
WT_EPOCH = millis();
t = 0;
}
void loop() {
digitalWrite(13,HIGH);
t += 500; // Set the next end time for the waitill(),
waitill(t); // then call it.
digitalWrite(13,LOW );
t += 500; // Set the next end time for the waitill(),
waitill(t); // then call it.
}
bool waitill(unsigned long millisec_to_ret) {
unsigned long dt;
dt = millis() - WT_EPOCH;
if (millisec_to_ret > dt) {delay(millisec_to_ret-dt);}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment