Struct NativeMemory
Represents an allocated native memory buffer of unspecified type. Also provides methods for managing native memory allocations, including managing SDL's internal allocators.
public readonly struct NativeMemory : IEquatable<ReadOnlyNativeMemory>, IEqualityOperators<NativeMemory, ReadOnlyNativeMemory, bool>, IEquatable<NativeMemory>, ISpanFormattable, IFormattable, IEqualityOperators<NativeMemory, NativeMemory, bool>
- Implements
- Inherited Members
Remarks
Note: Some of the static methods in this class require the caller to manually free the allocated memory using the appropriate free method (e.g., Free(void*) or AlignedFree(void*)). Failure to do so may result in memory leaks.
Properties
AllocationCount
Gets the number of outstanding (unfreed) allocations
public static int AllocationCount { get; }
Property Value
- int
The number of outstanding (unfreed) allocations, or
-1if allocation counting is disabled
Empty
Gets an empty NativeMemory
public static NativeMemory Empty { get; }
Property Value
- NativeMemory
An empty NativeMemory
IsEmpty
Gets a value indicating whether the allocated memory buffer is empty
public bool IsEmpty { get; }
Property Value
- bool
A value indicating whether the allocated memory buffer is empty
- See Also
IsPinned
Gets a value indicating whether the underlying NativeMemoryManagerBase of this allocated memory buffer is pinned
[MemberNotNullWhen(true, new string[] { "mMemoryManager", "MemoryManager" })]
public bool IsPinned { get; }
Property Value
- bool
A value indicating whether the underlying NativeMemoryManagerBase of this allocated memory buffer is pinned
- See Also
IsValid
Gets a value indicating whether the allocated memory buffer is valid
public bool IsValid { get; }
Property Value
- bool
A value indicating whether the allocated memory buffer is valid
Remarks
A valid NativeMemory might become invalid after the underlying NativeMemoryManager changed (e.g. by calling TryRealloc(ref NativeMemoryManager?, nuint) on it).
Length
Gets the number of bytes in the allocated memory buffer
public nuint Length { get; }
Property Value
- nuint
The number of bytes in the allocated memory buffer
Pointer
Gets a pointer to the start of the allocated memory buffer
public nint Pointer { get; }
Property Value
- nint
A pointer to the start of the allocated memory buffer
Methods
AlignedAlloc(nuint, nuint)
Allocates uninitialized memory that is aligned to a specific alignment
public static void* AlignedAlloc(nuint alignment, nuint size)
Parameters
Returns
Remarks
The memory returned by this method must be freed with AlignedFree(void*), not Free(void*).
If the alignment is less than sizeof(void*), it will be increased to match that instead.
The returned memory address will be a multiple of the alignment, and the actual size of the memory allocated will be a multiple of the alignment too.
AlignedFree(void*)
Frees memory allocated by AlignedAlloc(nuint, nuint)
public static void AlignedFree(void* memory)
Parameters
memoryvoid*A pointer previously returned by AlignedAlloc(nuint, nuint), or
null
Remarks
The memory is no longer valid after a call to this method and pointers into it should not be dereferenced anymore.
If the memory pointer is null, this method does nothing.
Calloc(nuint, nuint)
Allocates zero-initialized memory to hold a given number of elements of a given size
public static void* Calloc(nuint elementCount, nuint elementSize)
Parameters
elementCountnuintThe number of elements to allocate
elementSizenuintThe size in bytes of each individual element
Returns
Remarks
The memory returned by this method must be freed with Free(void*).
If either of elementCount or elementSize are 0, they will both be set to 1 instead.
The returned memory is guaranteed to be aligned to either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
Equals(NativeMemory)
Indicates whether the current object is equal to another object of the same type.
public bool Equals(NativeMemory other)
Parameters
otherNativeMemoryAn object to compare with this object.
Returns
Equals(ReadOnlyNativeMemory)
Indicates whether the current object is equal to another object of the same type.
public bool Equals(ReadOnlyNativeMemory other)
Parameters
otherReadOnlyNativeMemoryAn object to compare with this object.
Returns
Equals(object?)
Indicates whether this instance and a specified object are equal.
public override bool Equals(object? obj)
Parameters
objobjectThe object to compare with the current instance.
Returns
- bool
true if
objand this instance are the same type and represent the same value; otherwise, false.
Free(void*)
Frees allocated memory
public static void Free(void* memory)
Parameters
Remarks
The memory is no longer valid after a call to this method and pointers into it should not be dereferenced anymore.
If the memory pointer is null, this method does nothing.
GetHashCode()
Returns the hash code for this instance.
public override int GetHashCode()
Returns
- int
A 32-bit signed integer that is the hash code for this instance.
GetMemoryFunctions()
Gets the current set of SDL's native memory functions
public static INativeMemoryFunctions GetMemoryFunctions()
Returns
- INativeMemoryFunctions
The current set of SDL's native memory functions
Remarks
This does not hold a lock, so do not call this in the unlikely event of a background thread calling TrySetMemoryFunctions(INativeMemoryFunctions) simultaneously.
GetOriginalMemoryFunctions()
Gets the original set of SDL's native memory functions
public static INativeMemoryFunctions GetOriginalMemoryFunctions()
Returns
- INativeMemoryFunctions
The original set of SDL's native memory functions
Remarks
This is what Malloc(nuint) and friends will use by default, if there has been no change made by a call to TrySetMemoryFunctions(INativeMemoryFunctions).
These functions are not necessarily using the C runtime's malloc and friends functions behind the scenes!
Different platforms and build configurations might do any number of unexpected things.
Malloc(nuint)
Allocates uninitialized memory
public static void* Malloc(nuint size)
Parameters
sizenuintThe size in bytes to allocate
Returns
Remarks
The memory returned by this method must be freed with Free(void*).
If size is 0, it will be set to 1 instead.
The returned memory is guaranteed to be aligned to either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
Use AlignedAlloc(nuint, nuint) if you need to allocate memory aligned to an alignment greater than this guarantee.
MemCmp(void*, void*, nuint)
Compares two buffers of memory
public static int MemCmp(void* firstBuffer, void* secondBuffer, nuint length)
Parameters
firstBuffervoid*The first buffer to compare
secondBuffervoid*The second buffer to compare
lengthnuintThe number of bytes to compare between the buffers
Returns
- int
A value less than
0, iffirstBufferis considered "less than"secondBufferafter the firstlengthbytes; otherwise, a value greater than0, iffirstBufferis considered "greater than"secondBufferafter the firstlengthbytes; otherwise,0, which meansfirstBuffermatchessecondBufferexactly forlengthbytes
Remarks
There are special checks in place, for when firstBuffer or secondBuffer are null:
firstBufferandsecondBufferare bothnullThis method returns0firstBufferisnullwhilesecondBufferis notThis method returns-1firstBufferis notnullwhilesecondBufferisThis method returns1
Notice that in all of the special cases above the length doesn't play a role.
Note: There are no additional checks in place regarding the length of the buffers and the given length parameter.
Make sure that both buffers, firstBuffer and secondBuffer, are safely dereferencable for reading for at least length bytes!
MemCpy(void*, void*, nuint)
Copies specified number of bytes from one buffer of memory into another non-overlapping one
public static void* MemCpy(void* destination, void* source, nuint length)
Parameters
destinationvoid*The destination memory region. Must not overlap with
source.sourcevoid*The source memory region. Must not overlap with
destination.lengthnuintThe length in bytes of both
destinationandsource
Returns
- void*
The same pointer as the given
destination
Remarks
There are special checks in place, for when destination or source are null.
In those cases destination is just returned (even if it's null) without doing anything else.
The memory regions must not overlap! If they might do, use MemMove(void*, void*, nuint) instead.
Note: There are no additional checks in place regarding the length of the buffers and the given length parameter.
Make sure that destination is safely dereferenable for writing and source is safely dereferencable for reading, both for at least length bytes!
MemMove(void*, void*, nuint)
Copies specified number of bytes form one buffer of memory into another one that might overlap
public static void* MemMove(void* destination, void* source, nuint length)
Parameters
destinationvoid*The destination memory region
sourcevoid*The source memory region
lengthnuintThe length in bytes of both
destinationandsource
Returns
- void*
The same pointer as the given
destination
Remarks
There are special checks in place, for when destination or source are null.
In those cases destination is just returned (even if it's null) without doing anything else.
It is okay for the memory regions to overlap. If you are confident that the regions never overlap, you might want to use MemCpy(void*, void*, nuint) instead to improve performance.
Note: There are no additional checks in place regarding the length of the buffers and the given length parameter.
Make sure that destination is safely dereferenable for writing and source is safely dereferencable for reading, both for at least length bytes!
MemSet(void*, byte, nuint)
Initializes all bytes of a buffer of memory to a specified value
public static void* MemSet(void* destination, byte value, nuint length)
Parameters
destinationvoid*The destination memory region
valuebyteThe byte value to set
lengthnuintThe length in bytes to set in
destination
Returns
- void*
The same pointer as the given
destination
Remarks
There is a special check in place, for when destination is null.
In that case null is just returned without doing anything else.
Note: There are no additional checks in place regarding the length of destination and the given length parameter.
Make sure that destination is safely dereferenable for writing for at least length bytes!
MemSet(void*, uint, nuint)
Initializes all 32-bit words of a buffer of memory to a specific value
public static void* MemSet(void* destination, uint value, nuint dwords)
Parameters
destinationvoid*The destination memory region
valueuintThe uint value to set
dwordsnuintThe number of uint values (32-bit words) to set in
destination
Returns
- void*
The same pointer as the given
destination
Remarks
There is a special check in place, for when destination is null.
In that case null is just returned without doing anything else.
Note: There are no additional checks in place regarding the length of destination and the given dwords parameter.
Make sure that destination is safely dereferenable for writing for at least the number of uint values given by dwords (that is sizeof(uint) * bytes)!
dwords
Pin()
Pins the underlying NativeMemoryManager
public NativeMemoryPin Pin()
Returns
- NativeMemoryPin
A pin pinning the underlying NativeMemoryManager
Realloc(void*, nuint)
Changes the size of allocated memory
public static void* Realloc(void* memory, nuint newSize)
Parameters
memoryvoid*A pointer to allocated memory to reallocate, or
nullnewSizenuintThe new size in bytes of the memory
Returns
Remarks
The memory returned by this method must be freed with Free(void*).
If newSize is 0, it will be set to 1 instead.
Note that this is unlike some other C runtime realloc implementations, which may treat Realloc( the same way as memory, 0)Free(.
memory)
If the memory pointer is null, the behavior of this method is equivalent to Malloc(.
Otherwise, the result of this method can have one of three possible outcomes:
newSize)
- If it returns the same pointer as
memory, it means that thememorywas resized in place without freeing - If it returns a different non-
nullpointer, it means that the originalmemorywas freed and cannot be dereferenced there anymore - If it returns
null(indicating failure), then thememorywill remain valid and must still be freed with Free(void*)
The returned memory is guaranteed to be aligned to either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
ToString()
Returns the fully qualified type name of this instance.
public override string ToString()
Returns
- string
The fully qualified type name.
ToString(IFormatProvider?)
Formats the value of the current instance using the specified format.
public string ToString(IFormatProvider? formatProvider)
Parameters
formatProviderIFormatProviderThe provider to use to format the value.
-or-
A null reference (
Nothingin Visual Basic) to obtain the numeric format information from the current locale setting of the operating system.
Returns
- string
The value of the current instance in the specified format.
ToString(string?)
Formats the value of the current instance using the specified format.
public string ToString(string? format)
Parameters
formatstringThe format to use.
-or-
A null reference (
Nothingin Visual Basic) to use the default format defined for the type of the IFormattable implementation.
Returns
- string
The value of the current instance in the specified format.
ToString(string?, IFormatProvider?)
Formats the value of the current instance using the specified format.
public string ToString(string? format, IFormatProvider? formatProvider)
Parameters
formatstringThe format to use.
-or-
A null reference (
Nothingin Visual Basic) to use the default format defined for the type of the IFormattable implementation.formatProviderIFormatProviderThe provider to use to format the value.
-or-
A null reference (
Nothingin Visual Basic) to obtain the numeric format information from the current locale setting of the operating system.
Returns
- string
The value of the current instance in the specified format.
TryAlignedAlloc(nuint, nuint, out NativeMemoryManager?)
Tries to allocate uninitialized memory that is aligned to a specific alignment
public static bool TryAlignedAlloc(nuint alignment, nuint length, out NativeMemoryManager? memoryManager)
Parameters
alignmentnuintThe alignment of the memory
lengthnuintThe size in bytes to allocate
memoryManagerNativeMemoryManagerThe resulting NativeMemoryManager that manages the allocated uninitialized aligned memory, when this method returns
true; otherwise,null
Returns
Remarks
The resulting NativeMemoryManager should be disposed when the memory it's managing is no longer needed. That also frees the allocated memory.
If the alignment is less than sizeof(void*), it will be increased to match that instead.
The value of the resulting NativeMemoryManager's Pointer property will be a multiple of the alignment,
and the actual size of the memory allocated (not necessarily identical to Length) will be a multiple of the alignment too.
TryCalloc(nuint, nuint, out NativeMemoryManager?)
Tries to allocate zero-initialized memory to hold a given number of elements of a given size
public static bool TryCalloc(nuint elementCount, nuint elementSize, out NativeMemoryManager? memoryManager)
Parameters
elementCountnuintThe number of elements to allocate
elementSizenuintThe size in bytes of each individual element
memoryManagerNativeMemoryManagerThe resulting NativeMemoryManager that manages the allocated zero-initialized memory, when this method returns
true; otherwise,null
Returns
Remarks
The resulting NativeMemoryManager should be disposed when the memory it's managing is no longer needed. That also frees the allocated memory.
If either of elementCount or elementSize are 0, they will both be set to 1 instead.
The value of the resulting NativeMemoryManager's Pointer property is guaranteed to be aligned to
either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
TryCompare(ReadOnlyNativeMemory, ReadOnlyNativeMemory, out int)
Tries to compare two allocated memory buffers
public static bool TryCompare(ReadOnlyNativeMemory firstBuffer, ReadOnlyNativeMemory secondBuffer, out int result)
Parameters
firstBufferReadOnlyNativeMemoryThe first buffer to compare
secondBufferReadOnlyNativeMemoryThe second buffer to compare
resultintdefault(int), when this method returnsfalse; otherwise, a value less than0, iffirstBufferis considered "less than"secondBuffer; otherwise, a value greater than0, iffirstBufferis considered "greater than"secondBuffer; otherwise,0, which meansfirstBuffermatchessecondBufferexactly
Returns
- bool
true, iffirstBufferandsecondBufferare both valid and have the same Length; otherwise,false
Remarks
If one of firstBuffer or secondBuffer is empty (or both are), this method returns true and result is 0.
TryCopy(NativeMemory, ReadOnlyNativeMemory)
Tries to copy all bytes from one allocated memory buffer into another non-overlapping one
public static bool TryCopy(NativeMemory destination, ReadOnlyNativeMemory source)
Parameters
destinationNativeMemoryThe destination memory buffer. Must not overlap with
source.sourceReadOnlyNativeMemoryThe source memory buffer. Must not overlap with
destination.
Returns
- bool
true, ifdestinationandsourceare both valid anddestination's Length is at leastsource's Length; otherwise,false
Remarks
The memory regions must not overlap! If they might do, use TryMove(NativeMemory, ReadOnlyNativeMemory) instead.
TryFormat(Span<char>, out int, ReadOnlySpan<char>, IFormatProvider?)
Tries to format the value of the current instance into the provided span of characters.
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider? provider = null)
Parameters
destinationSpan<char>The span in which to write this instance's value formatted as a span of characters.
charsWrittenintWhen this method returns, contains the number of characters that were written in
destination.formatReadOnlySpan<char>A span containing the characters that represent a standard or custom format string that defines the acceptable format for
destination.providerIFormatProviderAn optional object that supplies culture-specific formatting information for
destination.
Returns
TryMalloc(nuint, out NativeMemoryManager?)
Tries to allocate uninitialized memory
public static bool TryMalloc(nuint length, out NativeMemoryManager? memoryManager)
Parameters
lengthnuintThe size in bytes to allocate
memoryManagerNativeMemoryManagerThe resulting NativeMemoryManager that manages the allocated uninitialized memory, when this method returns
true; otherwise,null
Returns
Remarks
The resulting NativeMemoryManager should be disposed when the memory it's managing is no longer needed. That also frees the allocated memory.
If length is 0, it will be set to 1 instead.
The value of the resulting NativeMemoryManager's Pointer property is guaranteed to be aligned to
either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
Use TryAlignedAlloc(nuint, nuint, out NativeMemoryManager?) if you need to allocate memory aligned to an alignment greater than this guarantee.
TryMove(NativeMemory, ReadOnlyNativeMemory)
Tries to copy all bytes from one allocated memory buffer into another one that might overlap
public static bool TryMove(NativeMemory destination, ReadOnlyNativeMemory source)
Parameters
destinationNativeMemoryThe destination memory buffer
sourceReadOnlyNativeMemoryThe source memory buffer
Returns
- bool
true, ifdestinationandsourceare both valid anddestination's Length is at leastsource's Length; otherwise,false
Remarks
It is okay for the memory regions to overlap. If you are confident that the regions never overlap, you might want to use TryCopy(NativeMemory, ReadOnlyNativeMemory) instead to improve performance.
TryRealloc(ref NativeMemoryManager?, nuint)
Tries to change the size of allocated native memory that is managed by a NativeMemoryManager
public static bool TryRealloc(ref NativeMemoryManager? memoryManager, nuint newLength)
Parameters
memoryManagerNativeMemoryManagerA reference to NativeMemoryManager that manages the native memory to reallocate, or a reference to
null. If this reference is referencing anullvalue, it might be referencing an actual NativeMemoryManager when this method returnstrue.newLengthnuintThe new size in bytes of the memory
Returns
Remarks
The resulting NativeMemoryManager should be still disposed when the memory it's managing is no longer needed. That also frees the allocated memory.
The referenced NativeMemoryManager cannot be NativeMemoryManager.IsPinned. Trying to reallocated a pinned memory buffer results in failure.
If newLength is 0, it will be set to 1 instead.
Note that this is unlike some other C runtime realloc implementations, which may treat TryRealloc(ref the same way as memoryManager, 0).
memoryManager.Dispose()
If the reference to memoryManager is referencing a null value, the behavior of this method is equivalent to TryMalloc(.
Otherwise, a call to this method can have one of three possible outcomes:
newLength, out memoryManager)
-
If the result of the call to this method is
trueand the values ofmemoryManager's Pointer, before and after this operation, are the same, it means that the original memory was resized in place without freeing -
If the result of the call to this method is
trueand the values ofmemoryManager's Pointer, before and after this operation, are different, it means that the original memory was freed and all active references to it (e.g. lasting Span<T>s) are invalid and cannot be dereferenced anymore (NativeMemory and NativeMemory<T> instances are safe though) -
The result of the call to this method is
false(indicating failure), then the givenmemoryManagerwill remain valid (if it was non-null) and should be still disposed when it's no longer needed
The value of the resulting NativeMemoryManager's Pointer property is guaranteed to be aligned to
either the fundamental alignment (alignof(max_align_t) in C11 and later) or 2 * sizeof(void*), whichever is smaller.
TrySet(NativeMemory, byte)
Tries to initialize all bytes of an allocated memory buffer to a specified value
public static bool TrySet(NativeMemory destination, byte value)
Parameters
destinationNativeMemoryvaluebyteThe byte value to set
Returns
TrySet(NativeMemory, uint)
Tries to initialize all 32-bit words of an allocated memory buffer to a specific value
public static bool TrySet(NativeMemory destination, uint value)
Parameters
destinationNativeMemoryvalueuintThe uint value to set
Returns
TrySetMemoryFunctions(INativeMemoryFunctions)
Tries to replace SDL's native memory functions with a custom set
public static bool TrySetMemoryFunctions(INativeMemoryFunctions memoryFunctions)
Parameters
memoryFunctionsINativeMemoryFunctionsThe set of custom native memory functions to replace SDL's current one
Returns
- bool
true, if the set of SDL's current native memory functions was successfully replaced by the given custom one; otherwise,false(check TryGet(out string?) for more information)
Remarks
It is not safe to call this method once any allocations have been made, as future calls to Free(void*) will use the new allocator, even if those allocations were allocated by an older set of native memory functions!
If this method is used, usually it needs to be the very first call made using the SDL library, if not the very first thing to do at the program's startup time.
Operators
operator ==(NativeMemory, NativeMemory)
Compares two values to determine equality.
public static bool operator ==(NativeMemory left, NativeMemory right)
Parameters
leftNativeMemoryThe value to compare with
right.rightNativeMemoryThe value to compare with
left.
Returns
operator ==(NativeMemory, ReadOnlyNativeMemory)
Compares two values to determine equality.
public static bool operator ==(NativeMemory left, ReadOnlyNativeMemory right)
Parameters
leftNativeMemoryThe value to compare with
right.rightReadOnlyNativeMemoryThe value to compare with
left.
Returns
implicit operator ReadOnlyNativeMemory(NativeMemory)
Converts an allocated memory buffer of unspecified type to an allocated read-only memory buffer of unspecified type
public static implicit operator ReadOnlyNativeMemory(NativeMemory nativeMemory)
Parameters
nativeMemoryNativeMemoryThe allocated memory buffer of unspecified type to convert to an allocated read-only memory buffer of unspecified type
Returns
- ReadOnlyNativeMemory
An allocated read-only memory buffer of unspecified type spanning the exact same memory region as the given
nativeMemory
operator !=(NativeMemory, NativeMemory)
Compares two values to determine inequality.
public static bool operator !=(NativeMemory left, NativeMemory right)
Parameters
leftNativeMemoryThe value to compare with
right.rightNativeMemoryThe value to compare with
left.
Returns
operator !=(NativeMemory, ReadOnlyNativeMemory)
Compares two values to determine inequality.
public static bool operator !=(NativeMemory left, ReadOnlyNativeMemory right)
Parameters
leftNativeMemoryThe value to compare with
right.rightReadOnlyNativeMemoryThe value to compare with
left.