Skip to content

Commit 575d8e8

Browse files
Add Timer args to struct and add show method (#57081)
1 parent 8560318 commit 575d8e8

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

NEWS.md

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ New library features
128128
certain compiler plugin workflows ([#56660]).
129129
* `sort` now supports `NTuple`s ([#54494])
130130
* `map!(f, A)` now stores the results in `A`, like `map!(f, A, A)`. or `A .= f.(A)` ([#40632]).
131+
* `Timer` now has readable `timeout` and `interval` properties, and a more descriptive show method ([#57081])
131132

132133
Standard library changes
133134
------------------------

base/asyncevent.jl

+42-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,24 @@ Create a timer that wakes up tasks waiting for it (by calling [`wait`](@ref) on
7474
Waiting tasks are woken after an initial delay of at least `delay` seconds, and then repeating after
7575
at least `interval` seconds again elapse. If `interval` is equal to `0`, the timer is only triggered
7676
once. When the timer is closed (by [`close`](@ref)) waiting tasks are woken with an error. Use
77-
[`isopen`](@ref) to check whether a timer is still active.
77+
[`isopen`](@ref) to check whether a timer is still active. Use `t.timeout` and `t.interval` to read
78+
the setup conditions of a `Timer` `t`.
79+
80+
```julia-repl
81+
julia> t = Timer(1.0; interval=0.5)
82+
Timer (open, timeout: 1.0 s, interval: 0.5 s) @0x000000010f4e6e90
83+
84+
julia> isopen(t)
85+
true
86+
87+
julia> t.timeout
88+
1.0
89+
90+
julia> close(t)
91+
92+
julia> isopen(t)
93+
false
94+
```
7895
7996
!!! note
8097
`interval` is subject to accumulating time skew. If you need precise events at a particular
@@ -84,12 +101,17 @@ once. When the timer is closed (by [`close`](@ref)) waiting tasks are woken with
84101
A `Timer` requires yield points to update its state. For instance, `isopen(t::Timer)` cannot be
85102
used to timeout a non-yielding while loop.
86103
104+
!!! compat "Julia 1.12
105+
The `timeout` and `interval` readable properties were added in Julia 1.12.
106+
87107
"""
88108
mutable struct Timer
89109
@atomic handle::Ptr{Cvoid}
90110
cond::ThreadSynchronizer
91111
@atomic isopen::Bool
92112
@atomic set::Bool
113+
timeout_ms::UInt64
114+
interval_ms::UInt64
93115

94116
function Timer(timeout::Real; interval::Real = 0.0)
95117
timeout 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds"))
@@ -99,7 +121,7 @@ mutable struct Timer
99121
intervalms = ceil(UInt64, interval * 1000)
100122
loop = eventloop()
101123

102-
this = new(Libc.malloc(_sizeof_uv_timer), ThreadSynchronizer(), true, false)
124+
this = new(Libc.malloc(_sizeof_uv_timer), ThreadSynchronizer(), true, false, timeoutms, intervalms)
103125
associate_julia_struct(this.handle, this)
104126
iolock_begin()
105127
err = ccall(:uv_timer_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), loop, this)
@@ -114,6 +136,24 @@ mutable struct Timer
114136
return this
115137
end
116138
end
139+
function getproperty(t::Timer, f::Symbol)
140+
if f == :timeout
141+
t.timeout_ms == 0 && return 0.0
142+
return (t.timeout_ms - 1) / 1000 # remove the +1ms compensation from the constructor
143+
elseif f == :interval
144+
return t.interval_ms / 1000
145+
else
146+
return getfield(t, f)
147+
end
148+
end
149+
propertynames(::Timer) = (:handle, :cond, :isopen, :set, :timeout, :timeout_ms, :interval, :interval_ms)
150+
151+
function show(io::IO, t::Timer)
152+
state = isopen(t) ? "open" : "closed"
153+
interval = t.interval
154+
interval_str = interval > 0 ? ", interval: $(t.interval) s" : ""
155+
print(io, "Timer ($state, timeout: $(t.timeout) s$interval_str) @0x$(string(convert(UInt, pointer_from_objref(t)), base = 16, pad = Sys.WORD_SIZE>>2))")
156+
end
117157

118158
unsafe_convert(::Type{Ptr{Cvoid}}, t::Timer) = t.handle
119159
unsafe_convert(::Type{Ptr{Cvoid}}, async::AsyncCondition) = async.handle

test/channels.jl

+10
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,16 @@ let a = Ref(0)
621621
@test a[] == 1
622622
end
623623

624+
@testset "Timer properties" begin
625+
t = Timer(1.0, interval = 0.5)
626+
@test t.timeout == 1.0
627+
@test t.interval == 0.5
628+
close(t)
629+
@test !isopen(t)
630+
@test t.timeout == 1.0
631+
@test t.interval == 0.5
632+
end
633+
624634
# trying to `schedule` a finished task
625635
let t = @async nothing
626636
wait(t)

0 commit comments

Comments
 (0)