Skip to content

Commit be72a57

Browse files
authored
Merge pull request #36323 from JuliaLang/teh/io_field_spec
Improve inferrability of stream IO
2 parents e0babe8 + 44f88a8 commit be72a57

File tree

3 files changed

+86
-9
lines changed

3 files changed

+86
-9
lines changed

base/io.jl

+20-1
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,27 @@ function open(f::Function, args...; kwargs...)
333333
end
334334
end
335335

336-
# Generic wrappers around other IO objects
336+
"""
337+
AbstractPipe
338+
339+
`AbstractPipe` is the abstract supertype for IO pipes that provide for communication between processes.
340+
341+
If `pipe isa AbstractPipe`, it must obey the following interface:
342+
343+
- `pipe.in` or `pipe.in_stream`, if present, must be of type `IO` and be used to provide input to the pipe
344+
- `pipe.out` or `pipe.out_stream`, if present, must be of type `IO` and be used for output from the pipe
345+
- `pipe.err` or `pipe.err_stream`, if present, must be of type `IO` and be used for writing errors from the pipe
346+
"""
337347
abstract type AbstractPipe <: IO end
348+
349+
function getproperty(pipe::AbstractPipe, name::Symbol)
350+
if name === :in || name === :in_stream || name === :out || name === :out_stream ||
351+
name === :err || name === :err_stream
352+
return getfield(pipe, name)::IO
353+
end
354+
return getfield(pipe, name)
355+
end
356+
338357
function pipe_reader end
339358
function pipe_writer end
340359

base/show.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ getindex(io::IO, key) = throw(KeyError(key))
340340
get(io::IOContext, key, default) = get(io.dict, key, default)
341341
get(io::IO, key, default) = default
342342

343-
displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize] : displaysize(io.io)
343+
displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize]::Tuple{Int,Int} : displaysize(io.io)
344344

345345
show_circular(io::IO, @nospecialize(x)) = false
346346
function show_circular(io::IOContext, @nospecialize(x))

base/stream.jl

+65-7
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,67 @@ end
1313

1414
## types ##
1515
abstract type IOServer end
16+
"""
17+
LibuvServer
18+
19+
An abstract type for IOServers handled by libuv.
20+
21+
If `server isa LibuvServer`, it must obey the following interface:
22+
23+
- `server.handle` must be a `Ptr{Cvoid}`
24+
- `server.status` must be an `Int`
25+
- `server.cond` must be a `GenericCondition`
26+
"""
1627
abstract type LibuvServer <: IOServer end
28+
29+
function getproperty(server::LibuvServer, name::Symbol)
30+
if name === :handle
31+
return getfield(server, :handle)::Ptr{Cvoid}
32+
elseif name === :status
33+
return getfield(server, :status)::Int
34+
elseif name === :cond
35+
return getfield(server, :cond)::GenericCondition
36+
else
37+
return getfield(server, name)
38+
end
39+
end
40+
41+
"""
42+
LibuvStream
43+
44+
An abstract type for IO streams handled by libuv.
45+
46+
If`stream isa LibuvStream`, it must obey the following interface:
47+
48+
- `stream.handle`, if present, must be a `Ptr{Cvoid}`
49+
- `stream.status`, if present, must be an `Int`
50+
- `stream.buffer`, if present, must be an `IOBuffer`
51+
- `stream.sendbuf`, if present, must be a `Union{Nothing,IOBuffer}`
52+
- `stream.cond`, if present, must be a `GenericCondition`
53+
- `stream.lock`, if present, must be an `AbstractLock`
54+
- `stream.throttle`, if present, must be an `Int`
55+
"""
1756
abstract type LibuvStream <: IO end
1857

58+
function getproperty(stream::LibuvStream, name::Symbol)
59+
if name === :handle
60+
return getfield(stream, :handle)::Ptr{Cvoid}
61+
elseif name === :status
62+
return getfield(stream, :status)::Int
63+
elseif name === :buffer
64+
return getfield(stream, :buffer)::IOBuffer
65+
elseif name === :sendbuf
66+
return getfield(stream, :sendbuf)::Union{Nothing,IOBuffer}
67+
elseif name === :cond
68+
return getfield(stream, :cond)::GenericCondition
69+
elseif name === :lock
70+
return getfield(stream, :lock)::AbstractLock
71+
elseif name === :throttle
72+
return getfield(stream, :throttle)::Int
73+
else
74+
return getfield(stream, name)
75+
end
76+
end
1977

2078
# IO
2179
# +- GenericIOBuffer{T<:AbstractArray{UInt8,1}} (not exported)
@@ -320,7 +378,7 @@ function isopen(x::Union{LibuvStream, LibuvServer})
320378
if x.status == StatusUninit || x.status == StatusInit
321379
throw(ArgumentError("$x is not initialized"))
322380
end
323-
return x.status::Int != StatusClosed && x.status::Int != StatusEOF
381+
return x.status != StatusClosed && x.status != StatusEOF
324382
end
325383

326384
function check_open(x::Union{LibuvStream, LibuvServer})
@@ -395,7 +453,7 @@ function close(stream::Union{LibuvStream, LibuvServer})
395453
stream.status = StatusClosing
396454
elseif isopen(stream) || stream.status == StatusEOF
397455
should_wait = uv_handle_data(stream) != C_NULL
398-
if stream.status::Int != StatusClosing
456+
if stream.status != StatusClosing
399457
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle)
400458
stream.status = StatusClosing
401459
end
@@ -410,7 +468,7 @@ function uvfinalize(uv::Union{LibuvStream, LibuvServer})
410468
iolock_begin()
411469
if uv.handle != C_NULL
412470
disassociate_julia_struct(uv.handle) # not going to call the usual close hooks
413-
if uv.status::Int != StatusUninit
471+
if uv.status != StatusUninit
414472
close(uv)
415473
else
416474
Libc.free(uv.handle)
@@ -524,7 +582,7 @@ function uv_alloc_buf(handle::Ptr{Cvoid}, size::Csize_t, buf::Ptr{Cvoid})
524582
stream = unsafe_pointer_to_objref(hd)::LibuvStream
525583

526584
local data::Ptr{Cvoid}, newsize::Csize_t
527-
if stream.status::Int != StatusActive
585+
if stream.status != StatusActive
528586
data = C_NULL
529587
newsize = 0
530588
else
@@ -557,7 +615,7 @@ function uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid})
557615
if isa(stream, TTY)
558616
stream.status = StatusEOF # libuv called uv_stop_reading already
559617
notify(stream.cond)
560-
elseif stream.status::Int != StatusClosing
618+
elseif stream.status != StatusClosing
561619
# begin shutdown of the stream
562620
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle)
563621
stream.status = StatusClosing
@@ -667,7 +725,7 @@ show(io::IO, stream::Pipe) = print(io,
667725

668726
function open_pipe!(p::PipeEndpoint, handle::OS_HANDLE)
669727
iolock_begin()
670-
if p.status::Int != StatusInit
728+
if p.status != StatusInit
671729
error("pipe is already in use or has been closed")
672730
end
673731
err = ccall(:uv_pipe_open, Int32, (Ptr{Cvoid}, OS_HANDLE), p.handle, handle)
@@ -1061,7 +1119,7 @@ _fd(x::Union{OS_HANDLE, RawFD}) = x
10611119

10621120
function _fd(x::Union{LibuvStream, LibuvServer})
10631121
fd = Ref{OS_HANDLE}(INVALID_OS_HANDLE)
1064-
if x.status::Int != StatusUninit && x.status::Int != StatusClosed
1122+
if x.status != StatusUninit && x.status != StatusClosed
10651123
err = ccall(:uv_fileno, Int32, (Ptr{Cvoid}, Ptr{OS_HANDLE}), x.handle, fd)
10661124
# handle errors by returning INVALID_OS_HANDLE
10671125
end

0 commit comments

Comments
 (0)