diff --git a/Project.toml b/Project.toml index e2164e8..3c4bfbd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ManualMemory" uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667" authors = ["chriselrod and contributors"] -version = "0.1.3" +version = "0.1.4" [compat] julia = "1.5" diff --git a/src/ManualMemory.jl b/src/ManualMemory.jl index a6b879c..861255c 100644 --- a/src/ManualMemory.jl +++ b/src/ManualMemory.jl @@ -10,6 +10,23 @@ end @inline Base.unsafe_convert(::Type{Ptr{T}}, m::MemoryBuffer) where {T} = Ptr{T}(pointer_from_objref(m)) @inline Base.pointer(m::MemoryBuffer{N,T}) where {N,T} = Ptr{T}(pointer_from_objref(m)) +""" + PseudoPtr(data, position=firstindex(data)) + +Provides a convenient wrapper that functions like `pointer(data)` for instances where `data` +cannot produce a viable pointer. +""" +struct PseudoPtr{T,D} <: Ref{T} + data::D + position::Int + + PseudoPtr(data::D, position) where {D} = new{eltype(D),D}(data, position) + PseudoPtr(data) = PseudoPtr(data, firstindex(data)) +end +Base.:(+)(x::PseudoPtr, y::Int) = PseudoPtr(getfield(x, :data), getfield(x, :position) + y) +Base.:(+)(x::Int, y::PseudoPtr) = y + x + +@inline load(x::PseudoPtr) = @inbounds(getindex(getfield(x, :data), getfield(x, :position))) @generated function load(p::Ptr{T}) where {T} if Base.allocatedinline(T) Expr(:block, Expr(:meta,:inline), :(unsafe_load(p))) @@ -18,6 +35,10 @@ end end end @inline load(p::Ptr{UInt}, ::Type{T}) where {T} = load(p, T, 0)[2] + +@inline function store!(x::PseudoPtr, val) + @inbounds(setindex!(getfield(x, :data), val, getfield(x, :position))) +end @generated function store!(p::Ptr{T}, v::T) where {T} if Base.allocatedinline(T) Expr(:block, Expr(:meta,:inline), :(unsafe_store!(p, v); return nothing)) diff --git a/test/runtests.jl b/test/runtests.jl index a48e388..014336c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using ManualMemory: MemoryBuffer, load, store!, LazyPreserve, preserve +using ManualMemory: MemoryBuffer, load, store!, LazyPreserve, preserve, PseudoPtr using Test @testset "ManualMemory.jl" begin @@ -16,6 +16,14 @@ using Test x = [0 0; 0 0]; preserve(store!, LazyPreserve(x), 1) @test x[1] === 1 + p = PseudoPtr(x, 1) + @test load(p) === 1 + p += 1 + store!(p, 2) + @test load(p) === 2 + p = 1 + p + store!(p, 3) + @test load(p) === 3 end using ThreadingUtilities