Skip to content

Commit

Permalink
Merge pull request #103 from JuliaLang/kms/timer-compat
Browse files Browse the repository at this point in the history
RFC: Added compat bindings for new Timer code in v0.4
  • Loading branch information
kmsquire committed Jun 17, 2015
2 parents 2e0ee96 + 1dfd3a2 commit 5b03745
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
79 changes: 79 additions & 0 deletions src/timer.jl
Original file line number Diff line number Diff line change
@@ -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)
15 changes: 15 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 5b03745

Please sign in to comment.