Reference

MemoryViews.DelimitedIterator — Type

Iterator struct created by split_each. Type and parameters are public, but otherwise the interface is defined by split_each,

MemoryViews.MemoryView — Type
MemoryView{T, M} <: DenseVector{T}

MemoryView is the common representation of dense, contiguous, Julia-owned data. String, Vector, Memory and other memory-backed types should have a fast MemoryView constructor.

Construct from memory-backed values x with MemoryView(x).

MemoryViews are guaranteed to point to contiguous, valid CPU memory, except where they have size zero.

The parameter M controls the mutability of the memory view, and may be Mutable or Immutable, corresponding to the the aliases MutableMemoryView{T} and ImmutableMemoryView{T}.

Examples

julia> v = view([1, 2, 3, 4], 2:3);

julia> mem = MemoryView(v)
2-element MutableMemoryView{Int64}:
 2
 3

julia> MemoryView(codeunits("abc")) isa ImmutableMemoryView{UInt8}
true

Extended help

New types T which are backed by dense memory should implement:

  • MemoryView(x::T) to construct a memory view from x. This should always return a MutableMemoryView when the memory of x is mutable.

If MemoryView(x) is implemented, then ImmutableMemoryView(x) will automatically work, even if MemoryView(x) returns a mutable view.

It is not possible to mutate memory though an ImmutableMemoryView, but the existence of the view does not protect the same memory from being mutated though another variable, or through explicitly unsafe functions.

The precise memory layout of the data in a MemoryView follows that of Memory. This includes the fact that some elements in the array, such as Strings, may be stored as pointers, and [isbits Union optimisations] (https://docs.julialang.org/en/v1/devdocs/isbitsunionarrays/).

MemoryView{T, M} is guaranteed to be immutable and to have the same size as a MemoryRef{T} and an Int combined.

MemoryViews.MemoryView — Method
MemoryView{T}(v::RefVector{T}, len::Int)::MutableMemoryView{T}

Construct a mutable memory view of the first len elements of v.

MemoryViews.RefVector — Type
RefVector{T} <: DenseVector{T}
RefVector{T}(undef, len::Integer)
RefVector(memory::Memory)
RefVector(ref::MemoryRef)
RefVector{T}(ref::MemoryRef{T})

A mutable DenseVector backed by Memory.

RefVector{T} is guaranteed to be an immutable struct only containing a MemoryRef{T}. Its length spans from the ref and to the end of the underlying Memory.

Constructing from Memory uses the entire Memory as the backing storage. The undef constructor creates a new uninitialized Memory of the given len.

Constructing from MemoryRef aliases its memory, spanning from the reference to the end of the underlying Memory. This may include uninitialized elements.

Slicing into a RefVector gives a MutableMemoryView aliasing the RefVector.

RefVector has the following notable differences from MemoryView:

  • Its length must run to the end of the underlying Memory

  • RefVector is one word smaller in size than MemoryView

  • Its length is not stored inline; it is behind a pointer dereference.

These properties make RefVector useful as backing storage for wrapper types which carry their own length. For such types, bounds checking may happen relative to the wrapper type, and the RefVector length is rarely queried.

Obtain the inner reference with memoryref(::RefVector).

Examples

julia> mem = fill!(Memory{Int}(undef, 3), 6);

julia> v = RefVector(mem)
3-element RefVector{Int64}:
 6
 6
 6

julia> v[2] = 3;

julia> v == [6, 3, 6]
true

julia> memoryref(v) === memoryref(mem)
true
Base.parent — Method
parent(v::T)::T where {T <: MemoryView}

Get a MemoryView of the same type as v, encompassing the entire underlying Memory.

julia> mem = ImmutableMemoryView([1, 2, 3])[2:3];

julia> parent(mem)
3-element ImmutableMemoryView{Int64}:
 1
 2
 3
Core.memoryref — Method
Base.memoryref(x::MutableMemoryView{T})::MemoryRef{T}

Get the MemoryRef of x. This reference is guaranteed to be inbounds, except if x is empty, where it may point to one element past the end.

To get the MemoryRef from an immutable MemoryView, use unsafe_memoryref

Core.memoryref — Method
Base.memoryref(x::Union{MutableMemoryView{T}, RefVector{T}})::MemoryRef{T}

Get the MemoryRef of x. This reference is guaranteed to be inbounds, except if x is empty, where it may point to one element past the end.

MemoryViews.memory — Method
memory(v::MutableMemoryView{T})::Memory{T}

Get the entire Memory underlying v, including elements outside the view. The returned memory is shared with v, not copied.

To get the underlying Memory from an immutable MemoryView, use unsafe_memory.

Examples

julia> backing = Memory{Int}([1, 2, 3]);

julia> v = MemoryView(backing)[2:3];

julia> memory(v) === backing
true

julia> memory(v)[2] = 4;

julia> v[1]
4
MemoryViews.split_at — Method
split_at(v::T, i::Integer) -> Tuple{T, T} where {T <: MemoryView}

Split a memory view into two at an index.

The first will contain all indices in 1:i-1, the second i:end. This function will throw a LightBoundsError if i is not in 1:end+1.

Examples

julia> split_at(MemoryView([1,2,3,4,5]), 2)
([1], [2, 3, 4, 5])

julia> split_at(MemoryView(Int8[1, 2, 3]), 4)
(Int8[1, 2, 3], Int8[])
MemoryViews.split_each — Method
split_each(data, x::T)

Return an iterator over memory-backed data data of eltype T. Returns MemoryViews of the same elements as data, separated by by x. Items are compared by isequal. The delimiter x must satisfy x isa T.

An empty input data yields no elements. Empty elements are otherwise yielded.

Examples

julia> split_each(b"abbc", UInt8('b')) |> collect |> print
ImmutableMemoryView{UInt8}[[0x61], [], [0x63]]

julia> split_each(b"babceb", UInt8('b')) |> collect |> print
ImmutableMemoryView{UInt8}[[], [0x61], [0x63, 0x65], []]

julia> split_each(UInt8[], UInt8('b')) |> collect |> print
MutableMemoryView{UInt8}[]
MemoryViews.split_first — Method
split_first(v::MemoryView{T}) -> Tuple{T, MemoryView{T}}

Return the first element of v and all other elements as a new memory view.

This function will throw a LightBoundsError if v is empty.

See also: split_last

Examples

julia> v = MemoryView([0x01, 0x02, 0x03]);

julia> split_first(v)
(0x01, UInt8[0x02, 0x03])

julia> split_first(v[1:1])
(0x01, UInt8[])

julia> split_first(v[1:0])
ERROR: LightBoundsErrors.LightBoundsError: out-of-bounds indexing: `collection[1]`, where:
[...]
MemoryViews.split_last — Method
split_last(v::MemoryView{T}) -> Tuple{T, MemoryView{T}}

Return the last element of v and all other elements as a new memory view.

This function will throw a LightBoundsError if v is empty.

See also: split_first

Examples

julia> v = MemoryView([0x01, 0x02, 0x03]);

julia> split_last(v)
(0x03, UInt8[0x01, 0x02])

julia> split_last(v[1:1])
(0x01, UInt8[])

julia> split_last(v[1:0])
ERROR: LightBoundsErrors.LightBoundsError: out-of-bounds indexing: `collection[1]`, where:
[...]
MemoryViews.split_unaligned — Method
split_unaligned(v::T, alignment::Integer) -> Tuple{T, T} where {T <: MemoryView}
split_unaligned(v::T, ::Val{alignment}) -> Tuple{T, T} where {T <: MemoryView}

Split memory view v into two views a and b, where a is the smallest prefix of v that guarantees the starting memory address of b is aligned to alignment bytes. alignment must be a power of two in the range 1:64. The Val form allows the compiler to optimize for a statically known alignment.

If v is empty or already aligned, a will be empty. If no elements of v is aligned, b will be empty and a will be equal to v. The element type of v must be a bitstype.

If b has no elements, no alignment is guaranteed about the empty b.

Warning

When using this function, make sure to GC.@preserve v, to make sure Julia does not move v in memory.

Examples:

julia> split_unaligned(MemoryView(Int16[1, 2, 3]), 8)
(Int16[], Int16[1, 2, 3])

julia> split_unaligned(MemoryView(collect(0x01:0x20))[6:13], 8)
(UInt8[0x06, 0x07, 0x08], UInt8[0x09, 0x0a, 0x0b, 0x0c, 0x0d])
MemoryViews.truncate — Method
truncate(v::MemoryView, to::Integer)::MemoryView

Creates a new memory view from the beginning of v, and up to and including the index to. Returns the same type as the input v. Equivalent to v[1:to], but may be more efficient.

julia> v = MemoryView([8, 9, 3, 2]);

julia> v2 = MemoryViews.truncate(v, 3);

julia> v[1:3] === v2
true
MemoryViews.unsafe_from_parts — Method
unsafe_from_parts(ref::MemoryRef{T}, len::Int)::MutableMemoryView{T}

Create a mutable memory view from its parts.

Safety: Callers are responsible to ensure that:

  • len is not negative

  • All indices i in 1:len are valid for ref (i.e. memoryref(ref, i) would not throw)

  • If ref is derived from immutable memory, it is the caller's responsibility to ensure that the resulting view is not mutated. For example, ref may be derived from a String, and mutating Strings in Julia may result in undefined behaviour. In these cases, the caller may convert to ImmutableMemoryView immediately after calling this function.

Examples

julia> v = [1,2,3,4];

julia> ref = Base.cconvert(Ptr, v);

julia> view = unsafe_from_parts(ref, 3)
3-element MutableMemoryView{Int64}:
 1
 2
 3
MemoryViews.unsafe_memory — Method
unsafe_memory(v::MemoryView{T})::Memory{T}

Get the entire Memory underlying v, including elements outside the view. The returned memory is shared with v, not copied.

Warning

As the resulting Memory is mutable, users must take care that this function allows mutation of memory assumed to be immutable, such as the memory backing a String. This can cause undefined behaviour.

MemoryViews.unsafe_memoryref — Method
unsafe_memoryref(x::MemoryView{T})::MemoryRef{T}

Same as memoryref(::MutableMemoryView), but also works for ImmutableMemoryView. Users must ensure only to mutate the resulting MemoryRef if x does not alias memory assumed to be immutable.

Warning

As the resulting MemoryRef is mutable, users must take care that this function allows mutation of memory assumed to be immutable, such as the memory backing a String. This can cause undefined behavour.