Skip to content

Commit 0852465

Browse files
NHDalyJeffBezanson
authored andcommitted
Simplify Channel constructors, change kwargs to positional args. (#32818)
"Soft" deprecation of the old `Channel(f::Function; csize=0, ctype=Any)` style in favor of the new `Channel{T=Any}(f::Function, size=0)` interface. Removed the old interface from the docs, so that it is not discoverable, and included a `!!! compat` note that the new interface is new in Julia 1.3, and the old interface should not be used.
1 parent d5db35b commit 0852465

File tree

3 files changed

+36
-31
lines changed

3 files changed

+36
-31
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Multi-threading changes
2020
([#32309], [#32174], [#31981], [#32421]).
2121
* The global random number generator (`GLOBAL_RNG`) is now thread-safe (and thread-local) ([#32407]).
2222
* New experimental `Threads.@spawn` macro that runs a task on any available thread ([#32600]).
23+
* Simplified the `Channel` constructor, which is now easier to read and more idiomatic julia.
24+
The old constructor (which used kwargs) is still available, but use is discouraged ([#30855], [#32818]).
2325

2426
Build system changes
2527
--------------------

base/channels.jl

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Representation of a channel passing objects of type `T`.
88
abstract type AbstractChannel{T} end
99

1010
"""
11-
Channel{T}(sz::Int=0)
11+
Channel{T=Any}(size::Int=0)
1212
13-
Constructs a `Channel` with an internal buffer that can hold a maximum of `sz` objects
13+
Constructs a `Channel` with an internal buffer that can hold a maximum of `size` objects
1414
of type `T`.
1515
[`put!`](@ref) calls on a full channel block until an object is removed with [`take!`](@ref).
1616
@@ -24,7 +24,7 @@ Other constructors:
2424
* `Channel(sz)`: equivalent to `Channel{Any}(sz)`
2525
2626
!!! compat "Julia 1.3"
27-
The default constructor `Channel()` and default `sz=0` were added in Julia 1.3.
27+
The default constructor `Channel()` and default `size=0` were added in Julia 1.3.
2828
"""
2929
mutable struct Channel{T} <: AbstractChannel{T}
3030
cond_take::Threads.Condition # waiting for data to become available
@@ -51,26 +51,27 @@ function Channel{T}(sz::Float64) where T
5151
sz = (sz == Inf ? typemax(Int) : convert(Int, sz))
5252
return Channel{T}(sz)
5353
end
54-
Channel(sz) = Channel{Any}(sz)
55-
Channel() = Channel{Any}(0)
54+
Channel(sz=0) = Channel{Any}(sz)
5655

5756
# special constructors
5857
"""
59-
Channel(func::Function; ctype=Any, csize=0, taskref=nothing)
58+
Channel{T=Any}(func::Function, size=0; taskref=nothing)
6059
6160
Create a new task from `func`, bind it to a new channel of type
62-
`ctype` and size `csize`, and schedule the task, all in a single call.
61+
`T` and size `size`, and schedule the task, all in a single call.
6362
6463
`func` must accept the bound channel as its only argument.
6564
6665
If you need a reference to the created task, pass a `Ref{Task}` object via
67-
keyword argument `taskref`.
66+
the keyword argument `taskref`.
6867
6968
Return a `Channel`.
7069
7170
# Examples
7271
```jldoctest
73-
julia> chnl = Channel(c->foreach(i->put!(c,i), 1:4));
72+
julia> chnl = Channel() do ch
73+
foreach(i -> put!(ch, i), 1:4)
74+
end;
7475
7576
julia> typeof(chnl)
7677
Channel{Any}
@@ -89,7 +90,9 @@ Referencing the created task:
8990
```jldoctest
9091
julia> taskref = Ref{Task}();
9192
92-
julia> chnl = Channel(c -> println(take!(c)); taskref=taskref);
93+
julia> chnl = Channel(taskref=taskref) do ch
94+
println(take!(ch))
95+
end;
9396
9497
julia> istaskdone(taskref[])
9598
false
@@ -102,11 +105,8 @@ true
102105
```
103106
104107
!!! compat "Julia 1.3"
105-
The following constructors were added in Julia 1.3.
106-
107-
Other constructors:
108-
* `Channel{T}(func::Function, sz=0)`
109-
* `Channel{T}(func::Function; csize=0, taskref=nothing)`
108+
This constructor was added in Julia 1.3. Earlier versions of Julia used kwargs
109+
to set `size` and `T`, but those constructors are deprecated.
110110
111111
```jldoctest
112112
julia> chnl = Channel{Char}(1) do ch
@@ -120,22 +120,21 @@ julia> String(collect(chnl))
120120
"hello world"
121121
```
122122
"""
123-
function Channel(func::Function; ctype=Any, csize=0, taskref=nothing)
124-
chnl = Channel{ctype}(csize)
123+
function Channel{T}(func::Function, size=0; taskref=nothing) where T
124+
chnl = Channel{T}(size)
125125
task = Task(() -> func(chnl))
126126
bind(chnl, task)
127127
yield(task) # immediately start it
128128

129129
isa(taskref, Ref{Task}) && (taskref[] = task)
130130
return chnl
131131
end
132-
function Channel{T}(f::Function, sz=0) where T
133-
return Channel(f, csize=sz, ctype=T)
134-
end
135-
function Channel{T}(f::Function; csize=0, taskref=nothing) where T
136-
return Channel(f, csize=csize, ctype=T, taskref=taskref)
137-
end
132+
Channel(func::Function, args...; kwargs...) = Channel{Any}(func, args...; kwargs...)
138133

134+
# This constructor is deprecated as of Julia v1.3, and should not be used.
135+
function Channel(func::Function; ctype=Any, csize=0, taskref=nothing)
136+
return Channel{ctype}(func, csize; taskref=taskref)
137+
end
139138

140139
closed_exception() = InvalidStateException("Channel is closed.", :closed)
141140

test/channels.jl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@ end
4444
end
4545

4646
@testset "Task constructors" begin
47-
c = Channel(ctype=Float32, csize=2) do c; map(i->put!(c,i), 1:100); end
48-
@test eltype(c) == Float32
49-
@test c.sz_max == 2
50-
@test isopen(c)
51-
@test collect(c) == 1:100
52-
5347
c = Channel{Int}() do c; map(i->put!(c,i), 1:100); end
5448
@test eltype(c) == Int
5549
@test c.sz_max == 0
@@ -59,18 +53,28 @@ end
5953
@test c.sz_max == 0
6054
@test collect(c) == [1, "hi"]
6155

56+
c = Channel(Inf) do c; put!(c,1); end
57+
@test eltype(c) == Any
58+
@test c.sz_max == typemax(Int)
6259
c = Channel{Int}(Inf) do c; put!(c,1); end
6360
@test eltype(c) == Int
6461
@test c.sz_max == typemax(Int)
6562

6663
taskref = Ref{Task}()
67-
c = Channel{Int}(csize=0, taskref=taskref) do c; put!(c, 0); end
64+
c = Channel{Int}(0, taskref=taskref) do c; put!(c, 0); end
6865
@test eltype(c) == Int
6966
@test c.sz_max == 0
7067
@test istaskstarted(taskref[])
7168
@test !istaskdone(taskref[])
7269
take!(c); wait(taskref[])
7370
@test istaskdone(taskref[])
71+
72+
# Legacy constructor
73+
c = Channel(ctype=Float32, csize=2) do c; map(i->put!(c,i), 1:100); end
74+
@test eltype(c) == Float32
75+
@test c.sz_max == 2
76+
@test isopen(c)
77+
@test collect(c) == 1:100
7478
end
7579

7680
@testset "multiple concurrent put!/take! on a channel for different sizes" begin
@@ -230,7 +234,7 @@ using Distributed
230234

231235
for T in [Any, Int]
232236
taskref = Ref{Task}()
233-
chnl = Channel(tf6, ctype=T, csize=N, taskref=taskref)
237+
chnl = Channel{T}(tf6, N, taskref=taskref)
234238
put!(chnl, 2)
235239
yield()
236240
@test_throws ErrorException wait(chnl)

0 commit comments

Comments
 (0)