Skip to content

Commit

Permalink
fix #6466, deprecate write on non-isbits arrays
Browse files Browse the repository at this point in the history
Also remove an unnecessary method, and generalize a `write` method
for `SubArray` from `::IOStream` to `::IO`.
  • Loading branch information
JeffBezanson committed Jul 24, 2017
1 parent 04d76f3 commit 30d929c
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ Deprecated or removed
* The function `showall` is deprecated. Showing entire values is the default, unless an
`IOContext` specifying `:limit=>true` is in use ([#22847]).

* Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or
`serialize` ([#6466]).


Julia v0.6.0 Release Notes
==========================
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,9 @@ end
@deprecate readstring(filename::AbstractString) read(filename, String)
@deprecate readstring(cmd::AbstractCmd) read(cmd, String)

# issue #6466
# `write` on non-isbits arrays is deprecated in io.jl.

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
33 changes: 27 additions & 6 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,21 @@ write(s::IO, x::Bool) = write(s, UInt8(x))
write(to::IO, p::Ptr) = write(to, convert(UInt, p))

function write(s::IO, A::AbstractArray)
if !isbits(eltype(A))
depwarn("Calling `write` on non-isbits arrays is deprecated. Use a loop or `serialize` instead.", :write)
end
nb = 0
for a in A
nb += write(s, a)
end
return nb
end

@noinline function write(s::IO, a::Array{UInt8}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
return unsafe_write(s, pointer(a), sizeof(a))
end

@noinline function write(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
if isbits(T)
@noinline function write(s::IO, a::Array) # mark noinline to ensure the array is gc-rooted somewhere (by the caller)
if isbits(eltype(a))
return unsafe_write(s, pointer(a), sizeof(a))
else
depwarn("Calling `write` on non-isbits arrays is deprecated. Use a loop or `serialize` instead.", :write)
nb = 0
for b in a
nb += write(s, b)
Expand All @@ -337,6 +337,27 @@ end
end
end

function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N}
if !isbits(T)
return invoke(write, Tuple{IO, AbstractArray}, s, a)
end
elsz = sizeof(T)
colsz = size(a,1) * elsz
if stride(a,1) != 1
for idxs in CartesianRange(size(a))
unsafe_write(s, pointer(a, idxs.I), elsz)
end
return elsz * length(a)
elseif N <= 1
return unsafe_write(s, pointer(a, 1), colsz)
else
for idxs in CartesianRange((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, idxs.I), colsz)
end
return colsz * trailingsize(a,2)
end
end


function write(s::IO, ch::Char)
c = reinterpret(UInt32, ch)
Expand Down
15 changes: 0 additions & 15 deletions base/iostream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,6 @@ function unsafe_write(s::IOStream, p::Ptr{UInt8}, nb::UInt)
return Int(ccall(:ios_write, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), s.ios, p, nb))
end

function write(s::IOStream, a::SubArray{T,N,<:Array}) where {T,N}
if !isbits(T) || stride(a,1)!=1
return invoke(write, Tuple{Any, AbstractArray}, s, a)
end
colsz = size(a,1)*sizeof(T)
if N<=1
return unsafe_write(s, pointer(a, 1), colsz)
else
for idxs in CartesianRange((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, idxs.I), colsz)
end
return colsz*trailingsize(a,2)
end
end

# num bytes available without blocking
nb_available(s::IOStream) = ccall(:jl_nb_available, Int32, (Ptr{Void},), s.ios)

Expand Down

0 comments on commit 30d929c

Please sign in to comment.