Skip to content

Commit

Permalink
make IOStream thread-safe (#32421)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jul 17, 2019
1 parent 29c08a7 commit 261e2b9
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 106 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Language changes
Multi-threading changes
-----------------------

* All system-level I/O operations (e.g. files and sockets) are now thread-safe.
This does not include subtypes of `IO` that are entirely in-memory, such as `IOBuffer`,
although it specifically does include `BufferStream`.
([#32309], [#32174], [#31981], [#32421]).

Build system changes
--------------------
Expand Down
2 changes: 1 addition & 1 deletion base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ include("c.jl")

# Core I/O
include("io.jl")
include("iostream.jl")
include("iobuffer.jl")

# strings & printing
Expand Down Expand Up @@ -264,6 +263,7 @@ function randn end
# I/O
include("libuv.jl")
include("asyncevent.jl")
include("iostream.jl")
include("stream.jl")
include("filesystem.jl")
using .Filesystem
Expand Down
74 changes: 74 additions & 0 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,80 @@ function unsafe_read(s::IO, p::Ptr{UInt8}, n::UInt)
nothing
end

function peek(s::IO)
mark(s)
try read(s, UInt8)
finally
reset(s)
end
end

# Generic `open` methods

"""
open_flags(; keywords...) -> NamedTuple
Compute the `read`, `write`, `create`, `truncate`, `append` flag value for
a given set of keyword arguments to [`open`](@ref) a [`NamedTuple`](@ref).
"""
function open_flags(;
read :: Union{Bool,Nothing} = nothing,
write :: Union{Bool,Nothing} = nothing,
create :: Union{Bool,Nothing} = nothing,
truncate :: Union{Bool,Nothing} = nothing,
append :: Union{Bool,Nothing} = nothing,
)
if write === true && read !== true && append !== true
create === nothing && (create = true)
truncate === nothing && (truncate = true)
end

if truncate === true || append === true
write === nothing && (write = true)
create === nothing && (create = true)
end

write === nothing && (write = false)
read === nothing && (read = !write)
create === nothing && (create = false)
truncate === nothing && (truncate = false)
append === nothing && (append = false)

return (
read = read,
write = write,
create = create,
truncate = truncate,
append = append,
)
end

"""
open(f::Function, args...; kwargs....)
Apply the function `f` to the result of `open(args...; kwargs...)` and close the resulting file
descriptor upon completion.
# Examples
```jldoctest
julia> open("myfile.txt", "w") do io
write(io, "Hello world!")
end;
julia> open(f->read(f, String), "myfile.txt")
"Hello world!"
julia> rm("myfile.txt")
```
"""
function open(f::Function, args...; kwargs...)
io = open(args...; kwargs...)
try
f(io)
finally
close(io)
end
end

# Generic wrappers around other IO objects
abstract type AbstractPipe <: IO end
Expand Down
Loading

0 comments on commit 261e2b9

Please sign in to comment.