How to perform actions periodically in Erlang - timer

-define(INTERVAL, 1000).
init([]) ->
Timer = erlang:send_after(?INTERVAL, self(), tick),
{ok, Timer}.
handle_info(tick, OldTimer) ->
erlang:cancel_timer(OldTimer),
io:format("Tick ~w~n", [OldTimer]),
Timer = erlang:send_after(?INTERVAL, self(), tick).
{noreplay, Timer}.
start_clock() ->
{_, Timer} = init([]),
spawn(clock, handle_info, [tick, Timer]).
My codes is as above, but the output is not what I want.
How can I integrate init() and handle_info() into the main function(start_clock)?

In the timer module, the function apply_interval(Time, Module, Function, Arguments) executes Module:Function(Arguments) every interval of Time. It takes care of spawning a process, returns a reference to allow a cancellation later.
You also can have a look at send_interval(Time, Pid, Message) in the same library.
You can also implement a simple loop like:
loop(Args,Tick) when is_integer(Tick), Tick >= 0 ->
receive
stop -> stopped
after
Tick ->
do_something(Args),
{NewArgs,NewTick} = new_args(Args,Tick),
loop(NewArgs,NewTick)
end.
it is not a realtime timer, but the function new_args(Args,Tick) can help to correct the deviation due to process scheduling.

I think you need something like this:
start_timer() ->
gen_server:start_link({local, clock}, ?MODULE, [], []).

Related

Asking for countdown while it's running

I made a function with a while loop that countdown from a specific time and returns when Time is up.
But I want to make a function get_time() that tells me how much time is left on the timer while the other is running.
This second function is also a while loop that waits for my input to return where the countdown is at now.
So how can I make this get_time() function?
Look at the following code (python) as reference
from multiprocessing import Process
def func1():
print 'func1: starting'
for i in xrange(10000000): pass
print 'func1: finishing'
def get_time():
print 'get_time: starting'
for i in xrange(10000000): pass
print 'get_time: finishing'
if __name__ == '__main__':
p1 = Process(target=func1)
p1.start()
p2 = Process(target=get_time)
p2.start()
p1.join()
p2.join()

How can I use Tokio to trigger a function every period or interval in seconds?

In Node.js I can set the interval that a certain event should be triggered,
function intervalFunc() {
console.log('whelp, triggered again!');
}
setInterval(intervalFunc, 1500);
However the interface for Tokio's interval is a bit more complex. It seems to be a something to do with a much more literal definition of an interval, and rather than calling a function at an interval, it simply stalls the thread until the time passes (with .await).
Is there a primitive in Tokio that calls a function "every x seconds" or the like? If not, is there an idiom that has emerged to do this?
I only need to run one function on a recurring interval... I don't care about other threads either. It's just one function on Tokio's event loop.
Spawn a Tokio task to do something forever:
use std::time::Duration;
use tokio::{task, time}; // 1.3.0
#[tokio::main]
async fn main() {
let forever = task::spawn(async {
let mut interval = time::interval(Duration::from_millis(10));
loop {
interval.tick().await;
do_something().await;
}
});
forever.await;
}
You can also use tokio::time::interval to create a value that you can tick repeatedly. Perform the tick and call your function inside of the body of stream::unfold to create a stream:
use futures::{stream, StreamExt}; // 0.3.13
use std::time::{Duration, Instant};
use tokio::time; // 1.3.0
#[tokio::main]
async fn main() {
let interval = time::interval(Duration::from_millis(10));
let forever = stream::unfold(interval, |mut interval| async {
interval.tick().await;
do_something().await;
Some(((), interval))
});
let now = Instant::now();
forever.for_each(|_| async {}).await;
}
async fn do_something() {
eprintln!("do_something");
}
See also:
How can I run a set of functions concurrently on a recurring interval without running the same function at the same time using Tokio?
I am still a rust/tokio beginner, but I did find this solution helpful for myself:
use std::time::Duration;
use tokio::time;
use tokio_stream::wrappers::IntervalStream;
#[tokio::main]
async fn main() {
let mut stream = IntervalStream::new(time::interval(Duration::from_secs(1)));
while let Some(_ts) = stream.next().await {
println!("whelp, triggered again!");
}
}
Please note that _ts holds the execution timestamp.

Flink TestHarness output doesn't clear after collect

I have the following test:
testHarness.processElement2(new StreamRecord<>(element1));
testHarness.processElement1(new StreamRecord<>(new Tuple2<>(id, element2)));
testHarness.setProcessingTime(1); //let's assume it's the correct time for the timer inside the function
softly.assertThat(testHarness.getOutput()).containsExactly(new StreamRecord<>(expectedResult)); //this one is passed
testHarness.setProcessingTime(2); // setting second timer which will trigger different timer
softly.assertThat(testHarness.getOutput()).containsExactly(new StreamRecord<>(expectedResult2)); //fails cause output has expectedResult & expectedResult2
Why TestHarness is not clearing it's elements once we call getOutput()? Could this functionality be achieved somehow?
This can be achieved by calling clear() on the output :
testHarness.processElement2(new StreamRecord<>(element1));
testHarness.processElement1(new StreamRecord<>(new Tuple2<>(id, element2)));
testHarness.setProcessingTime(1); //let's assume it's the correct time for the timer inside the function
softly.assertThat(testHarness.getOutput()).containsExactly(new StreamRecord<>(expectedResult)); // Pass
testHarness.getOutput().clear();
testHarness.setProcessingTime(2); // setting second timer which will trigger different timer
softly.assertThat(testHarness.getOutput()).containsExactly(new StreamRecord<>(expectedResult2)); // Pass

Rx Swift simple timer not working

I have this RxSwift code in swift 3
let bag:DisposeBag = DisposeBag()
var sig:Observable<Int>!
sig = Observable<Int>.interval(1.0, scheduler: MainScheduler.instance)
sig.subscribe(onNext: { (milsec) in
print("Mil: \(milsec)")
}).addDisposableTo(bag)
i run this code when button tapped, but its not print anything on console.
DisposeBag will dispose of your subscription once it goes out of scope. In this instance, it'll be right after the call to subscribe, and it explains why you don't see anything printed to the console.
Move the definition of dispose bag to the class creating the subscription and everything should work fine.
class MyViewController: UIViewController {
let bag:DisposeBag = DisposeBag()
dynamic func onButtonTapped() {
var sig:Observable<Int>!
sig = Observable<Int>.interval(1.0, scheduler: MainScheduler.instance)
sig.subscribe(onNext: { (sec) in
print("Sec: \(sec)")
}).addDisposableTo(bag)
}
}
On a side note, interval expects an interval in seconds, so it will only tick every seconds as oposed to milliseconds.

Waiting for both keyword and timer events with OCamlSDL (SDL2)

I need to be able to wait for two types of events in the app using OCamlSDL:
User key presses
Timer events with fixed-time interval
I can see in the tutorial how to wait for events in a loop. My idea was to set up a timer using SDL_AddTimer and feed via it custom USER events which will be processed in the same loop as the keyboard events. However I do not see OCAML binding for SDL_AddTimer SDL function. How can I implement something like this?
The solution I found involves running separate POSIX thread which uses Sldevent.add to send user-defined events which are then processed in the main event processing loop with keyboard events. Here is a code except which starts the thread:
...
and timer_cb () = Sdlevent.add [USER 0] in
let timer_thread = Thread.create timer_loop (timer_flag, timer_cb) in
loop state; (* runs main program logic *)
timer_flag := true;
Thread.join timer_thread
Timer function (executed in separate thread):
let rec timer_loop (flag, callback) =
if !flag then
Thread.exit
else
(Thread.delay 0.5;
callback ();
(timer_loop (flag, callback)))
Event handling loop except:
let rec loop state =
match wait_event () with
| KEYDOWN {keysym=KEY_LEFT} ->
(* process left arrow key press here *)
loop state
| USER 0 ->
(* Process ticks here *)
loop state
| KEYDOWN {keysym=KEY_ESCAPE} ->
(* ESC to exit the app *)
()
| _ ->
loop state

Resources