diff --git a/LICENSE b/LICENSE index a2e0ce9..3cb8b04 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 chriselrod and contributors +Copyright (c) 2021 Julia Computing, Inc. and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/ManualMemory.jl b/src/ManualMemory.jl index e937d54..93856f8 100644 --- a/src/ManualMemory.jl +++ b/src/ManualMemory.jl @@ -1,5 +1,29 @@ module ManualMemory -# Write your package code here. +mutable struct MemoryBuffer{N,T} + data::NTuple{N,T} + @inline function MemoryBuffer{N,T}(::UndefInitializer) where {N,T} + @assert Base.allocatedinline(T) + new{N,T}() + end +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)) + +@generated function load(p::Ptr{T}) where {T} + if Base.allocatedinline(T) + Expr(:block, Expr(:meta,:inline), :(unsafe_load(p))) + else + Expr(:block, Expr(:meta,:inline), :(ccall(:jl_value_ptr, Ref{$T}, (Ptr{Cvoid},), unsafe_load(Base.unsafe_convert(Ptr{Ptr{Cvoid}}, p))))) + end +end +@inline load(p::Ptr{UInt}, ::Type{T}) where {T} = load(reinterpret(Ptr{T}, p)) +@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)) + else + Expr(:block, Expr(:meta,:inline), :(unsafe_store!(Base.unsafe_convert(Ptr{Ptr{Cvoid}}, p), Base.pointer_from_objref(v)); return nothing)) + end +end end diff --git a/test/runtests.jl b/test/runtests.jl index 8eb84be..593ad09 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,15 @@ -using ManualMemory +using ManualMemory: MemoryBuffer, load, store! using Test @testset "ManualMemory.jl" begin - # Write your tests here. + + @test_throws AssertionError MemoryBuffer{4,String}(undef) + m = MemoryBuffer{4,Float64}(undef); + store!(pointer(m), 1.23) + @test load(pointer(m)) == 1.23 + str = "Hello world!" + GC.@preserve str begin + store!(Base.unsafe_convert(Ptr{String}, m), str) + @test load(Base.unsafe_convert(Ptr{String}, m)) === str + end end