Skip to content

Commit

Permalink
Revert "Merge pull request #11669 from JuliaLang/jb/timers"
Browse files Browse the repository at this point in the history
This reverts commit 2d63b4e, reversing
changes made to 2236148.
  • Loading branch information
KristofferC committed Jun 12, 2015
1 parent 069d72e commit d8df4a1
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 111 deletions.
4 changes: 1 addition & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ Library improvements

* You can now tab-complete Emoji characters via their [short names](http://www.emoji-cheat-sheet.com/), using `\:name:<tab>` ([#10709]).

* `gc_enable` subsumes `gc_disable`, and also returns the previous GC state.
* The `gc_enable` and `gc_disable` functions now return the previous GC state.

* `assert`, `@assert` now throws an `AssertionError` exception type ([#9734]).

Expand Down Expand Up @@ -404,8 +404,6 @@ Deprecated or removed

* Instead of `utf32(64,123,...)` use `utf32(UInt32[64,123,...])` ([#11379]).

* `start_timer` and `stop_timer` are replaced by `Timer` and `close`.

Julia v0.3.0 Release Notes
==========================

Expand Down
10 changes: 0 additions & 10 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -517,13 +517,3 @@ end

@deprecate gc_enable() gc_enable(true)
@deprecate gc_disable() gc_enable(false)

@deprecate stop_timer close

function Timer(f::Function)
error("Timer(f) is deprecated. Use Timer(f, delay, repeat) instead.")
end

function start_timer(t, d, r)
error("start_timer is deprecated. Use Timer(callback, delay, repeat) instead.")
end
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,8 @@ export
serialize,
skip,
skipchars,
start_timer,
stop_timer,
takebuf_array,
takebuf_string,
truncate,
Expand Down
7 changes: 4 additions & 3 deletions base/multi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1533,14 +1533,15 @@ function timedwait(testcb::Function, secs::Float64; pollint::Float64=0.1)
catch e
put!(done, :error)
finally
isready(done) && close(aw)
isready(done) && stop_timer(aw)
end
end

if !testcb()
t = Timer(timercb, pollint, pollint)
t = Timer(timercb)
start_timer(t, pollint, pollint)
ret = fetch(done)
close(t)
stop_timer(t)
else
ret = :ok
end
Expand Down
144 changes: 65 additions & 79 deletions base/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ end

function reinit_stdio()
global uv_jl_asynccb = cglobal(:jl_uv_asynccb)
global uv_jl_timercb = cglobal(:jl_uv_timercb)
global uv_jl_alloc_buf = cglobal(:jl_uv_alloc_buf)
global uv_jl_readcb = cglobal(:jl_uv_readcb)
global uv_jl_connectioncb = cglobal(:jl_uv_connectioncb)
Expand Down Expand Up @@ -468,22 +467,13 @@ function reseteof(x::TTY)
nothing
end

function _uv_hook_close(uv::Union(AsyncStream,UVServer))
uv.handle = C_NULL
uv.status = StatusClosed
if isa(uv.closecb, Function)
uv.closecb(uv)
end
notify(uv.closenotify)
try notify(uv.readnotify) end
try notify(uv.connectnotify) end
end

##########################################
# Async Worker
# Async Workers
##########################################

type SingleAsyncWork
abstract AsyncWork

type SingleAsyncWork <: AsyncWork
handle::Ptr{Void}
cb::Function
function SingleAsyncWork(cb::Function)
Expand All @@ -495,95 +485,91 @@ type SingleAsyncWork
end
end

close(t::SingleAsyncWork) = ccall(:jl_close_uv,Void,(Ptr{Void},),t.handle)

_uv_hook_close(uv::SingleAsyncWork) = (uv.handle = C_NULL; unpreserve_handle(uv); nothing)

function _uv_hook_asynccb(async::SingleAsyncWork)
try
async.cb(async)
catch
end
nothing
end

##########################################
# Timer
##########################################

type Timer
type Timer <: AsyncWork
handle::Ptr{Void}
cond::Condition
isopen::Bool

function Timer(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(_sizeof_uv_timer), Condition(), true)
cb::Function
function Timer(cb::Function)
this = new(Libc.malloc(_sizeof_uv_timer), cb)
# We don't want to set a julia struct, but we also
# want to make sure there's no garbage data in the
# ->data field
disassociate_julia_struct(this.handle)
err = ccall(:uv_timer_init,Cint,(Ptr{Void},Ptr{Void}),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

associate_julia_struct(this.handle, this)
preserve_handle(this)

ccall(:uv_update_time, Void, (Ptr{Void},), eventloop())
ccall(:uv_timer_start, Cint, (Ptr{Void},Ptr{Void},UInt64,UInt64),
this.handle, uv_jl_timercb::Ptr{Void},
UInt64(round(timeout*1000))+1, UInt64(round(repeat*1000)))
finalizer(this,uvfinalize)
this
end
end

wait(t::Timer) = wait(t.cond)

isopen(t::Timer) = t.isopen
close(t::AsyncWork) = ccall(:jl_close_uv,Void,(Ptr{Void},),t.handle)

function close(t::Timer)
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)
function _uv_hook_close(uv::Union(AsyncStream,UVServer))
uv.handle = C_NULL
uv.status = StatusClosed
if isa(uv.closecb, Function)
uv.closecb(uv)
end
notify(uv.closenotify)
try notify(uv.readnotify) end
try notify(uv.connectnotify) end
end
_uv_hook_close(uv::Timer) = (uv.handle = C_NULL; nothing)
_uv_hook_close(uv::SingleAsyncWork) = (uv.handle = C_NULL; unpreserve_handle(uv); nothing)

function _uv_hook_close(t::Timer)
unpreserve_handle(t)
disassociate_julia_struct(t)
t.handle = C_NULL
# This serves as a common callback for all async classes
function _uv_hook_asynccb(async::AsyncWork)
if isa(async, Timer)
if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Void},), async.handle) == 0
# timer is stopped now
disassociate_julia_struct(async.handle)
end
end
try
async.cb(async)
catch
end
nothing
end

function _uv_hook_timercb(t::Timer)
if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Void},), t.handle) == 0
# timer is stopped now
close(t)
end
notify(t.cond)
nothing
function start_timer(timer::Timer, timeout::Real, repeat::Real)
timeout 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds"))
repeat 0 || throw(ArgumentError("timer cannot repeat $repeat times"))

associate_julia_struct(timer.handle, timer)
preserve_handle(timer)
ccall(:uv_update_time,Void,(Ptr{Void},),eventloop())
ccall(:uv_timer_start,Cint,(Ptr{Void},Ptr{Void},UInt64,UInt64),
timer.handle, uv_jl_asynccb::Ptr{Void}, UInt64(round(timeout*1000))+1, UInt64(round(repeat*1000)))
end

function sleep(sec::Real)
sec 0 || throw(ArgumentError("cannot sleep for $sec seconds"))
wait(Timer(sec))
nothing
function stop_timer(timer::Timer)
# ignore multiple calls to stop_timer
!haskey(uvhandles, timer) && return
timer.handle == C_NULL && return

ccall(:uv_timer_stop,Cint,(Ptr{Void},),timer.handle)
disassociate_julia_struct(timer.handle)
unpreserve_handle(timer)
end

# timer with repeated callback
function Timer(cb::Function, timeout::Real, repeat::Real=0.0)
t = Timer(timeout, repeat)
@schedule begin
while isopen(t)
wait(t)
cb(t)
end
function sleep(sec::Real)
sec 0 || throw(ArgumentError("cannot sleep for $sec seconds"))
w = Condition()
timer = Timer(function (tmr)
notify(w)
end)
start_timer(timer, float(sec), 0)
try
stream_wait(timer, w)
finally
stop_timer(timer)
end
t
nothing
end

## event loop ##
Expand Down
21 changes: 11 additions & 10 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -930,20 +930,21 @@ Errors
Events
------

.. function:: Timer(callback::Function, delay, repeat=0)
.. function:: Timer(f::Function)

Create a timer to call the given callback function.
The callback is passed one argument, the timer object itself.
The callback will be invoked after the specified initial delay,
and then repeating with the given ``repeat`` interval.
Create a timer to call the given callback function. The callback
is passed one argument, the timer object itself. The timer can be
started and stopped with ``start_timer`` and ``stop_timer``.

.. function:: start_timer(t::Timer, delay, repeat)

Start invoking the callback for a ``Timer`` after the specified initial
delay, and then repeating with the given interval. Times are in seconds.
If ``repeat`` is ``0``, the timer is only triggered once.
Times are in seconds.
A timer is stopped and has its resources freed by calling ``close`` on it.

.. function:: Timer(delay, repeat=0)
.. function:: stop_timer(t::Timer)

Create a timer that wakes up tasks waiting for it (by calling ``wait`` on
the timer object) at a specified interval.
Stop invoking the callback for a timer.

Reflection
----------
Expand Down
6 changes: 0 additions & 6 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ enum CALLBACK_TYPE { CB_PTR, CB_INT32, CB_UINT32, CB_INT64, CB_UINT64 };
XX(connectcb) \
XX(connectioncb) \
XX(asynccb) \
XX(timercb) \
XX(getaddrinfo) \
XX(pollcb) \
XX(fspollcb) \
Expand Down Expand Up @@ -231,11 +230,6 @@ DLLEXPORT void jl_uv_asynccb(uv_handle_t *handle)
JULIA_CB(asynccb,handle->data,0);
}

DLLEXPORT void jl_uv_timercb(uv_handle_t *handle)
{
JULIA_CB(timercb,handle->data,0);
}

DLLEXPORT void jl_uv_pollcb(uv_poll_t *handle, int status, int events)
{
JULIA_CB(pollcb,handle->data,2,CB_INT32,status,CB_INT32,events);
Expand Down

0 comments on commit d8df4a1

Please sign in to comment.