From 733f1b6fd97c2a8ee27551e26e9a8205e54c2d48 Mon Sep 17 00:00:00 2001 From: Kevin Squire Date: Sun, 14 Jun 2015 10:34:04 -0700 Subject: [PATCH 1/2] Added compat bindings for new Timer code in v0.4 * Ref: https://github.com/JuliaLang/julia/pull/11669 --- src/Compat.jl | 9 ++++++ src/timer.jl | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 15 +++++++++ 3 files changed, 103 insertions(+) create mode 100644 src/timer.jl diff --git a/src/Compat.jl b/src/Compat.jl index adf5ea708998e..7b3c75928fd6b 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -301,6 +301,11 @@ function _compat(ex::Expr) ex = Expr(:stagedfunction, f.args...) end end + elseif VERSION < v"0.4.0-dev+5322" && ex.head == :(::) && isa(ex.args[end], Symbol) + # Replace Base.Timer with Compat.Timer2 in type declarations + if ex.args[end] == :Timer || ex.args[end] == :(Base.Timer) + ex.args[end] = :(Compat.Timer2) + end end return Expr(ex.head, map(_compat, ex.args)...) end @@ -450,4 +455,8 @@ if VERSION < v"0.4.0-dev+4939" export isvalid end +if VERSION < v"0.4.0-dev+5322" + include("timer.jl") +end + end # module diff --git a/src/timer.jl b/src/timer.jl new file mode 100644 index 0000000000000..6917885082bd3 --- /dev/null +++ b/src/timer.jl @@ -0,0 +1,79 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +########################################## +# Timer2 +########################################## +# +# This is a backported replacement for the new Timer code introduced in v0.4 +# + +type Timer2 + handle::Ptr{Void} + cond::Condition + isopen::Bool + + function Timer2(timeout::Real, repeat::Real=0.0) + timeout ≥ 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds")) + repeat ≥ 0 || throw(ArgumentError("timer cannot repeat $repeat times")) + + this = new(Libc.malloc(Base._sizeof_uv_timer), Condition(), true) + err = ccall(:uv_timer_init,Cint,(Ptr{Void},Ptr{Void}),Base.eventloop(),this.handle) + if err != 0 + #TODO: this codepath is currently not tested + Libc.free(this.handle) + this.handle = C_NULL + throw(UVError("uv_make_timer",err)) + end + + Base.associate_julia_struct(this.handle, this) + Base.preserve_handle(this) + + ccall(:uv_update_time, Void, (Ptr{Void},), Base.eventloop()) + @compat ccall(:uv_timer_start, Cint, (Ptr{Void},Ptr{Void},UInt64,UInt64), + this.handle, Base.uv_jl_asynccb::Ptr{Void}, + UInt64(round(timeout*1000))+1, UInt64(round(repeat*1000))) + this + end +end + +Base.wait(t::Timer2) = wait(t.cond) + +Base.isopen(t::Timer2) = t.isopen + +function Base.close(t::Timer2) + if t.handle != C_NULL + t.isopen = false + ccall(:uv_timer_stop, Cint, (Ptr{Void},), t.handle) + ccall(:jl_close_uv, Void, (Ptr{Void},), t.handle) + end +end + +function Base._uv_hook_close(t::Timer2) + Base.unpreserve_handle(t) + Base.disassociate_julia_struct(t) + t.handle = C_NULL + nothing +end + +function Base._uv_hook_asynccb(t::Timer2) + @compat if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Void},), t.handle) == 0 + # timer is stopped now + close(t) + end + notify(t.cond) + nothing +end + +# timer with repeated callback +function Base.Timer(cb::Function, timeout::Real, repeat::Real=0.0) + t = Timer2(timeout, repeat) + @schedule begin + while isopen(t) + wait(t) + cb(t) + end + end + t +end + +Base.Timer(timeout::Real, repeat::Real=0.0) = Timer2(timeout, repeat) diff --git a/test/runtests.jl b/test/runtests.jl index d987f990e1911..488e18ee2baaa 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -342,3 +342,18 @@ if VERSION > v"0.3.99" @test foo(5) == Int end end + +# Timer +let c = 0, f, t + @compat f(t::Timer) = (c += 1) + t = Timer(f, 0.0, 0.05) + sleep(0.05) + @test c >= 1 + sleep(0.1) + @test c >= 3 + close(t) + sleep(0.1) + val = c + sleep(0.1) + @test val == c +end From 1dfd3a2aac5055a2f3806f2ffc5b1241cca40cbd Mon Sep 17 00:00:00 2001 From: Kevin Squire Date: Sun, 14 Jun 2015 10:55:08 -0700 Subject: [PATCH 2/2] Updated README with Timer changes --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2f9a784c8902d..ed4f84502b056 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ Currently, the `@compat` macro supports the following syntaxes: * `@compat chol(A, Val{:U})` - Julia 0.4 type-stable cholesky factorizations (will not be type-stable on 0.3) +* `@compat f(t::Timer)` - mimic the Julia 0.4 Timer class + ## Type Aliases * `typealias AbstractString String` - `String` has been renamed to `AbstractString` [#8872](https://github.com/JuliaLang/julia/pull/8872) @@ -69,6 +71,8 @@ Currently, the `@compat` macro supports the following syntaxes: * `fma(x,y,z)` and `muladd(x,y,z)` can be used in Julia 0.3 for `x*y+z`. +* `Timer(timeout::Real, repeat::Real=0.0)` and `Timer(cb::Function, timeout::Real, repeat::Real=0.0)` allow julia 0.4-style Timers to be constructed and used. + ## Renamed functions * `itrunc`, `iround`, `iceil`, `ifloor` are now accessed via `trunc(T, x)`, etc. [#9133](https://github.com/JuliaLang/julia/pull/9133)