mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add tracking allocator. Fix substruct issue.
This commit is contained in:
105
lib/std/core/allocators/tracking_allocator.c3
Normal file
105
lib/std/core/allocators/tracking_allocator.c3
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
|
||||
module std::core::mem::allocator;
|
||||
import std::collections::map;
|
||||
|
||||
define PtrMap = HashMap<uptr, usz>;
|
||||
|
||||
// A simple tracking allocator.
|
||||
// It tracks allocations using a hash map but
|
||||
// is not compatible with allocators that uses mark()
|
||||
struct TrackingAllocator
|
||||
{
|
||||
inline Allocator allocator;
|
||||
Allocator* inner_allocator;
|
||||
PtrMap map;
|
||||
usz mem_total;
|
||||
usz allocs_total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a memory arena for use using the provided bytes.
|
||||
*
|
||||
* @require this != null
|
||||
**/
|
||||
fn void TrackingAllocator.init(TrackingAllocator* this, Allocator* allocator)
|
||||
{
|
||||
*this = { .inner_allocator = allocator, .allocator.function = &tracking_allocator_fn };
|
||||
this.map.init(.allocator = allocator);
|
||||
}
|
||||
|
||||
fn void TrackingAllocator.free(TrackingAllocator* this)
|
||||
{
|
||||
this.map.free();
|
||||
*this = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [inout] data
|
||||
* @require !alignment || math::is_power_of_2(alignment)
|
||||
*/
|
||||
fn void*! tracking_allocator_fn(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private
|
||||
{
|
||||
TrackingAllocator* this = (TrackingAllocator*)data;
|
||||
void* result = this.inner_allocator.function(this.inner_allocator, size, alignment, offset, old_pointer, kind)?;
|
||||
switch (kind)
|
||||
{
|
||||
case CALLOC:
|
||||
case ALIGNED_CALLOC:
|
||||
case ALLOC:
|
||||
case ALIGNED_ALLOC:
|
||||
this.map.set((uptr)result, size);
|
||||
this.mem_total += size;
|
||||
this.allocs_total++;
|
||||
return result;
|
||||
case REALLOC:
|
||||
case ALIGNED_REALLOC:
|
||||
this.map.remove((uptr)old_pointer);
|
||||
this.map.set((uptr)result, size);
|
||||
this.mem_total += size;
|
||||
if (size > 0) this.allocs_total++;
|
||||
return result;
|
||||
case ALIGNED_FREE:
|
||||
case FREE:
|
||||
if (!old_pointer) return null;
|
||||
this.map.remove((uptr)old_pointer);
|
||||
return null;
|
||||
case MARK:
|
||||
// Unsupported
|
||||
return null;
|
||||
case RESET:
|
||||
this.map.clear();
|
||||
return null;
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
|
||||
fn usz TrackingAllocator.allocated(TrackingAllocator* this)
|
||||
{
|
||||
usz allocated = 0;
|
||||
@pool()
|
||||
{
|
||||
foreach (usz allocation : this.map.value_tlist())
|
||||
{
|
||||
allocated += allocation;
|
||||
}
|
||||
};
|
||||
return allocated;
|
||||
}
|
||||
|
||||
fn usz TrackingAllocator.total_allocated(TrackingAllocator* this)
|
||||
{
|
||||
return this.mem_total;
|
||||
}
|
||||
|
||||
fn usz TrackingAllocator.total_allocation_count(TrackingAllocator* this)
|
||||
{
|
||||
return this.allocs_total;
|
||||
}
|
||||
|
||||
fn usz TrackingAllocator.allocation_count(TrackingAllocator* this)
|
||||
{
|
||||
return this.map.count;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Copyright (c) 2021-2023 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
|
||||
module std::core::mem::array;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user