Struct maskerad_memory_allocators::DoubleEndedStackAllocatorCopy [] [src]

pub struct DoubleEndedStackAllocatorCopy { /* fields omitted */ }

A double-ended allocator for data implementing the Copy trait.

It manages two MemoryChunks to:

  • Allocate bytes in a stack-like fashion, from both ends.

  • Store different types of objects in the same storage.

Differences with DoubleEndedStackAllocator

This double-ended stack allocator slightly differs from the non-copy double-ended stack allocator. The non-copy one must extract some metadata (the vtable) about the object it will allocate, to be able to call the drop function of the object when needed. However, a type implementing the Copy trait doesn't, and can't, implement Drop. There is no need to store extra informations about those types, they don't have destructors.

Instantiation

When instantiated, the memory chunk pre-allocate the given number of bytes, half for one memory chunk, half for the other.

Allocation

When an object is allocated in memory, the DoubleEndedStackAllocator:

  • Asks a pointer to a memory address to its memory chunk,

  • Place the object in this memory address,

  • Update the first unused memory address of the memory chunk according to an offset,

  • And return a mutable reference to the object which has been placed in the memory chunk.

This offset is calculated by the size of the object, its memory-alignment and an offset to align the object in memory.

Roll-back

This structure allows you to get a marker, the index to the first unused memory address of the memory chunk. A stack allocator can be reset to a marker, or reset entirely.

When the allocator is reset to a marker, the memory chunk will set the first unused memory address to the marker.

When the allocator is reset completely, the memory chunk will set the first unused memory address to the bottom of its stack.

Methods

impl DoubleEndedStackAllocatorCopy
[src]

[src]

Creates a DoubleEndedStackAllocatorCopy with the given capacity, in bytes.

Example

#![feature(alloc)]
use maskerad_memory_allocators::DoubleEndedStackAllocatorCopy;

let allocator = DoubleEndedStackAllocatorCopy::with_capacity(100);
assert_eq!(allocator.temp_storage().borrow().capacity(), 50);
assert_eq!(allocator.resident_storage().borrow().capacity(), 50);

[src]

Returns an immutable reference to the memory chunk used for the resident data.

[src]

Returns an immutable reference to the memory chunk used for the temporary data.

[src]

Allocates data in the allocator's memory.

Panics

This function will panic if the allocation exceeds the maximum storage capacity of the allocator.

Example

use maskerad_memory_allocators::DoubleEndedStackAllocatorCopy;
use maskerad_memory_allocators::ChunkType;


let allocator = DoubleEndedStackAllocatorCopy::with_capacity(100);

let my_u64 = allocator.alloc(&ChunkType::TempData, || {
    4587 as u64
});

let bob = allocator.alloc(&ChunkType::ResidentData, || {
    0xb0b as u64
});

assert_eq!(my_u64, &mut 4587);
assert_eq!(bob, &mut 0xb0b);

[src]

Returns the index of the first unused memory address.

Example

use maskerad_memory_allocators::DoubleEndedStackAllocatorCopy;
use maskerad_memory_allocators::ChunkType;

let allocator = DoubleEndedStackAllocatorCopy::with_capacity(100); //50 bytes for each memory chunk.

//Get the raw pointer to the bottom of the memory chunk used for temp data.
let start_allocator_temp = allocator.temp_storage().borrow().as_ptr();

//Get the index of the first unused memory address in the memory chunk used for temp data.
let index_temp = allocator.marker(&ChunkType::TempData);

//Calling offset() on a raw pointer is an unsafe operation.
unsafe {
    //Get the raw pointer, with the index.
    let current_top = start_allocator_temp.offset(index_temp as isize);

    //Nothing has been allocated in the memory chunk used for temp data,
    //the top of the stack is the bottom of the memory chunk.
    assert_eq!(current_top, start_allocator_temp);
}

[src]

Reset the allocator, allocations will occur from the bottom of the stack.

Example

use maskerad_memory_allocators::DoubleEndedStackAllocatorCopy;
use maskerad_memory_allocators::ChunkType;


let allocator = DoubleEndedStackAllocatorCopy::with_capacity(100); // 50 bytes for each memory chunk.

//When nothing has been allocated, the first unused memory address is at index 0.
assert_eq!(allocator.marker(&ChunkType::TempData), 0);
assert_eq!(allocator.marker(&ChunkType::ResidentData), 0);

let my_u64 = allocator.alloc(&ChunkType::TempData, || {
    456 as u64
});

assert_ne!(allocator.marker(&ChunkType::TempData), 0);

let my_i32 = allocator.alloc(&ChunkType::TempData, || {
    12 as i32
});

allocator.reset(&ChunkType::TempData);

//The memory chunk for temp data has been totally reset.

assert_eq!(allocator.marker(&ChunkType::TempData), 0);

[src]

Reset partially the allocator, allocations will occur from the marker.

Example

use maskerad_memory_allocators::DoubleEndedStackAllocatorCopy;
use maskerad_memory_allocators::ChunkType;


let allocator = DoubleEndedStackAllocatorCopy::with_capacity(100); // 100 bytes.

//When nothing has been allocated, the first unused memory address is at index 0.
assert_eq!(allocator.marker(&ChunkType::TempData), 0);

let my_u64 = allocator.alloc(&ChunkType::TempData, || {
    123 as u64
});

//After the u64 allocation, get the index of the first unused memory address in the memory chunk used for temp data.
let index_current_temp = allocator.marker(&ChunkType::TempData);
assert_ne!(index_current_temp, 0);

let my_i32 = allocator.alloc(&ChunkType::TempData, || {
    321 as i32
});

assert_ne!(allocator.marker(&ChunkType::TempData), index_current_temp);

allocator.reset_to_marker(&ChunkType::TempData, index_current_temp);

//The allocator has been partially reset.

assert_eq!(allocator.marker(&ChunkType::TempData), index_current_temp);