Skip to content

Commit 1028584

Browse files
committed
make IOStream thread-safe
1 parent f18808d commit 1028584

File tree

6 files changed

+164
-106
lines changed

6 files changed

+164
-106
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Language changes
1414
Multi-threading changes
1515
-----------------------
1616

17+
* All system-level I/O operations (e.g. files and sockets) are now thread-safe.
18+
This does not include subtypes of `IO` that are entirely in-memory, e.g. `IOBuffer`.
19+
([#32309], [#32174], [#31981], ...).
1720

1821
Build system changes
1922
--------------------

base/Base.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ include("c.jl")
198198

199199
# Core I/O
200200
include("io.jl")
201-
include("iostream.jl")
202201
include("iobuffer.jl")
203202

204203
# strings & printing
@@ -264,6 +263,7 @@ function randn end
264263
# I/O
265264
include("libuv.jl")
266265
include("asyncevent.jl")
266+
include("iostream.jl")
267267
include("stream.jl")
268268
include("filesystem.jl")
269269
using .Filesystem

base/io.jl

+74
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,80 @@ function unsafe_read(s::IO, p::Ptr{UInt8}, n::UInt)
226226
nothing
227227
end
228228

229+
function peek(s::IO)
230+
mark(s)
231+
try read(s, UInt8)
232+
finally
233+
reset(s)
234+
end
235+
end
236+
237+
# Generic `open` methods
238+
239+
"""
240+
open_flags(; keywords...) -> NamedTuple
241+
242+
Compute the `read`, `write`, `create`, `truncate`, `append` flag value for
243+
a given set of keyword arguments to [`open`](@ref) a [`NamedTuple`](@ref).
244+
"""
245+
function open_flags(;
246+
read :: Union{Bool,Nothing} = nothing,
247+
write :: Union{Bool,Nothing} = nothing,
248+
create :: Union{Bool,Nothing} = nothing,
249+
truncate :: Union{Bool,Nothing} = nothing,
250+
append :: Union{Bool,Nothing} = nothing,
251+
)
252+
if write === true && read !== true && append !== true
253+
create === nothing && (create = true)
254+
truncate === nothing && (truncate = true)
255+
end
256+
257+
if truncate === true || append === true
258+
write === nothing && (write = true)
259+
create === nothing && (create = true)
260+
end
261+
262+
write === nothing && (write = false)
263+
read === nothing && (read = !write)
264+
create === nothing && (create = false)
265+
truncate === nothing && (truncate = false)
266+
append === nothing && (append = false)
267+
268+
return (
269+
read = read,
270+
write = write,
271+
create = create,
272+
truncate = truncate,
273+
append = append,
274+
)
275+
end
276+
277+
"""
278+
open(f::Function, args...; kwargs....)
279+
280+
Apply the function `f` to the result of `open(args...; kwargs...)` and close the resulting file
281+
descriptor upon completion.
282+
283+
# Examples
284+
```jldoctest
285+
julia> open("myfile.txt", "w") do io
286+
write(io, "Hello world!")
287+
end;
288+
289+
julia> open(f->read(f, String), "myfile.txt")
290+
"Hello world!"
291+
292+
julia> rm("myfile.txt")
293+
```
294+
"""
295+
function open(f::Function, args...; kwargs...)
296+
io = open(args...; kwargs...)
297+
try
298+
f(io)
299+
finally
300+
close(io)
301+
end
302+
end
229303

230304
# Generic wrappers around other IO objects
231305
abstract type AbstractPipe <: IO end

0 commit comments

Comments
 (0)