Rratic
Rratic

Reputation: 123

How to build a setInterval-like task?

This is my idea

task=@task begin
while true
    sleep(1)
    foo()
    if should_end
        # ?
    end
end
end

But there are some problems

  1. are there any simple ways to contact other than using global should_end?
  2. how to end the task from inside the expression?

Upvotes: 0

Views: 132

Answers (1)

ahnlabb
ahnlabb

Reputation: 2162

While implementing something like this can be a good exercise, note that Timers are in the standard library and they are similar to the JS functions you may be used to because Julia and Node.js both use libuv internally. Whether you use Node.js setInterval or Timeout, or Julia Timer eventually uv_timer_start is called (although the creation and low-level management of timers is different in the respective runtimes).

To answer your 2nd question, you can just break in the if expression:

julia> should_end = false
false

julia> task = @task begin
           while true
               sleep(1)
               if should_end
                   break
               end
           end
           "Tasks can return a value"
       end
Task (runnable) @0x00007fca1c9c3990

julia> schedule(task)
Task (runnable) @0x00007fca1c9c3990

julia> task
Task (runnable) @0x00007fca1c9c3990

julia> should_end = true;sleep(1)

julia> task
Task (done) @0x00007fca1c9c3990

julia> fetch(task)
"Tasks can return a value"

As for the 1st question, there is a lot of information in the Julia docs, e.g. the Asynchronous Programming section. As is described there, Channels can be used for communication between tasks (when suitable). Note that should_end doesn't have to be global. A task wraps a function and that function can capture variables in enclosing scopes (@task begin a = 1 end is really just Task(() -> begin a = 1 end).

Here is a short example using a Timer and a Channel to send data to a task:

function pinger(n)
    ping() = parse(Float64, match(r"time=(.*) ms", read(`ping -c 1 8.8.8.8`, String))[1])
    ch = Channel{Float64}(0)

    pinger = Timer(0.0; interval=1.0) do timer
        put!(ch, ping())
    end

    summer = @task begin
        total = 0.0
        count = 0
        while count < n
            total += take!(ch)
            count += 1
        end
        total / count
    end
    schedule(summer)
    fetch(summer)
end
julia> pinger(3)
19.5

Upvotes: 1

Related Questions