Created
September 2, 2016 17:01
-
-
Save thejoshwolfe/8329b7ce04cdfdd1feb9db59f43c6552 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct AllocatorVtable { | |
allocFn: fn (self: &Allocator, n: usize) -> %[]u8, | |
reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8, | |
freeFn: fn (self: &Allocator, mem: []u8), | |
} | |
pub struct Allocator { | |
vtable: &AllocatorVtable, | |
} | |
struct SpaceSavingAllocator { | |
@attribute("first_element") parent: Allocator, | |
state: SomeStateStuff, | |
fn init(self: &Self) { | |
self.parent = Allocator{ | |
.vtable = &space_saving_allocator_vtable, | |
}; | |
} | |
fn alloc(almostSelf: &Allocator, n: usize) -> %[]u8 { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
fn realloc(almostSelf: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8 { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
fn free(almostSelf: &Allocator, mem: []u8) { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
} | |
// a constant global vtable shared among all SpaceSavingAllocator instances | |
// saves space and provides security by preventing these pointers from changing. | |
const space_saving_allocator_vtable = AllocatorVtable{ | |
.allocFn = SpaceSavingAllocator.alloc, | |
.reallocFn = SpaceSavingAllocator.realloc, | |
.freeFn = SpaceSavingAllocator.free, | |
}; | |
struct CacheFriendlyAllocator { | |
@attribute("first_element") parent: Allocator, | |
// embed the vtable in the object | |
vtable: AllocatorVtable, | |
state: SomeStateStuff, | |
fn init(self: &Self) { | |
self.parent = Allocator{ | |
// point to ourself | |
.vtable = &self.vtable, | |
}; | |
self.vtable = AllocatorVtable{ | |
.allocFn = CacheFriendlyAllocator.alloc, | |
.reallocFn = CacheFriendlyAllocator.realloc, | |
.freeFn = CacheFriendlyAllocator.free, | |
}; | |
} | |
fn alloc(almostSelf: &Allocator, n: usize) -> %[]u8 { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
fn realloc(almostSelf: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8 { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
fn free(almostSelf: &Allocator, mem: []u8) { | |
const self = (&Self)(almostSelf); | |
... | |
} | |
} | |
fn testAllocator(allocator: &Allocator) { | |
var blob = allocator.allocFn(10); | |
blob = allocator.reallocFn(blob, 20); | |
allocator.freeFn(blob); | |
} | |
@attribute("test") | |
fn testMain() { | |
{ | |
var allocatorImpl: SpaceSavingAllocator = undefined; | |
allocatorImpl.init(); | |
testAllocator(&allocatorImpl.parent); | |
} | |
{ | |
var allocatorImpl: CacheFriendlyAllocator = undefined; | |
allocatorImpl.init(); | |
testAllocator(&allocatorImpl.parent); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment