mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add ONHEAP for List and HashMap
This commit is contained in:
@@ -14,6 +14,9 @@ const float DEFAULT_LOAD_FACTOR = 0.75;
|
||||
const VALUE_IS_EQUATABLE = Value.is_eq;
|
||||
const bool COPY_KEYS = types::implements_copy(Key);
|
||||
|
||||
const Allocator MAP_HEAP_ALLOCATOR = (Allocator)&dummy;
|
||||
|
||||
const HashMap ONHEAP = { .allocator = MAP_HEAP_ALLOCATOR };
|
||||
|
||||
struct Entry
|
||||
{
|
||||
@@ -34,11 +37,11 @@ struct HashMap (Printable)
|
||||
|
||||
|
||||
<*
|
||||
@param [&inout] allocator "The allocator to use"
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@param [&inout] allocator : "The allocator to use"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
fn HashMap* HashMap.init(&self, Allocator allocator, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -51,10 +54,10 @@ fn HashMap* HashMap.init(&self, Allocator allocator, uint capacity = DEFAULT_INI
|
||||
}
|
||||
|
||||
<*
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
fn HashMap* HashMap.tinit(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -62,12 +65,12 @@ fn HashMap* HashMap.tinit(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float
|
||||
}
|
||||
|
||||
<*
|
||||
@param [&inout] allocator "The allocator to use"
|
||||
@require $vacount % 2 == 0 "There must be an even number of arguments provided for keys and values"
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@param [&inout] allocator : "The allocator to use"
|
||||
@require $vacount % 2 == 0 : "There must be an even number of arguments provided for keys and values"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
macro HashMap* HashMap.init_with_key_values(&self, Allocator allocator, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -79,11 +82,11 @@ macro HashMap* HashMap.init_with_key_values(&self, Allocator allocator, ..., uin
|
||||
}
|
||||
|
||||
<*
|
||||
@require $vacount % 2 == 0 "There must be an even number of arguments provided for keys and values"
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@require $vacount % 2 == 0 : "There must be an even number of arguments provided for keys and values"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
macro HashMap* HashMap.tinit_with_key_values(&self, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -91,14 +94,14 @@ macro HashMap* HashMap.tinit_with_key_values(&self, ..., uint capacity = DEFAULT
|
||||
}
|
||||
|
||||
<*
|
||||
@param [in] keys "The keys for the HashMap entries"
|
||||
@param [in] values "The values for the HashMap entries"
|
||||
@param [&inout] allocator "The allocator to use"
|
||||
@require keys.len == values.len "Both keys and values arrays must be the same length"
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@param [in] keys : "The keys for the HashMap entries"
|
||||
@param [in] values : "The values for the HashMap entries"
|
||||
@param [&inout] allocator : "The allocator to use"
|
||||
@require keys.len == values.len : "Both keys and values arrays must be the same length"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
fn HashMap* HashMap.init_from_keys_and_values(&self, Allocator allocator, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -113,13 +116,13 @@ fn HashMap* HashMap.init_from_keys_and_values(&self, Allocator allocator, Key[]
|
||||
|
||||
|
||||
<*
|
||||
@param [in] keys "The keys for the HashMap entries"
|
||||
@param [in] values "The values for the HashMap entries"
|
||||
@require keys.len == values.len "Both keys and values arrays must be the same length"
|
||||
@require capacity > 0 "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 "The load factor must be higher than 0"
|
||||
@require !self.allocator "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
@param [in] keys : "The keys for the HashMap entries"
|
||||
@param [in] values : "The values for the HashMap entries"
|
||||
@require keys.len == values.len : "Both keys and values arrays must be the same length"
|
||||
@require capacity > 0 : "The capacity must be 1 or higher"
|
||||
@require load_factor > 0.0 : "The load factor must be higher than 0"
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
fn HashMap* HashMap.tinit_from_keys_and_values(&self, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
@@ -134,12 +137,13 @@ fn HashMap* HashMap.tinit_from_keys_and_values(&self, Key[] keys, Value[] values
|
||||
*>
|
||||
fn bool HashMap.is_initialized(&map)
|
||||
{
|
||||
return (bool)map.allocator;
|
||||
return map.allocator && map.allocator.ptr != &dummy;
|
||||
}
|
||||
|
||||
<*
|
||||
@param [&inout] allocator "The allocator to use"
|
||||
@param [&in] other_map "The map to copy from."
|
||||
@param [&inout] allocator : "The allocator to use"
|
||||
@param [&in] other_map : "The map to copy from."
|
||||
@require !self.is_initialized() : "Map was already initialized"
|
||||
*>
|
||||
fn HashMap* HashMap.init_from_map(&self, Allocator allocator, HashMap* other_map)
|
||||
{
|
||||
@@ -150,6 +154,7 @@ fn HashMap* HashMap.init_from_map(&self, Allocator allocator, HashMap* other_map
|
||||
|
||||
<*
|
||||
@param [&in] other_map "The map to copy from."
|
||||
@require !map.is_initialized() : "Map was already initialized"
|
||||
*>
|
||||
fn HashMap* HashMap.tinit_from_map(&map, HashMap* other_map)
|
||||
{
|
||||
@@ -224,10 +229,15 @@ fn bool HashMap.has_key(&map, Key key)
|
||||
fn bool HashMap.set(&map, Key key, Value value) @operator([]=)
|
||||
{
|
||||
// If the map isn't initialized, use the defaults to initialize it.
|
||||
if (!map.allocator)
|
||||
{
|
||||
map.tinit();
|
||||
}
|
||||
switch (map.allocator.ptr)
|
||||
{
|
||||
case &dummy:
|
||||
map.init(mem);
|
||||
case null:
|
||||
map.tinit();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint hash = rehash(key.hash());
|
||||
uint index = index_for(hash, map.table.len);
|
||||
for (Entry *e = map.table[index]; e != null; e = e.next)
|
||||
@@ -269,7 +279,7 @@ fn void HashMap.clear(&map)
|
||||
|
||||
fn void HashMap.free(&map)
|
||||
{
|
||||
if (!map.allocator) return;
|
||||
if (!map.is_initialized()) return;
|
||||
map.clear();
|
||||
map.free_internal(map.table.ptr);
|
||||
map.table = {};
|
||||
@@ -578,3 +588,5 @@ macro uint index_for(uint hash, uint capacity) @private
|
||||
{
|
||||
return hash & (capacity - 1);
|
||||
}
|
||||
|
||||
int dummy @local;
|
||||
@@ -9,6 +9,10 @@ def ElementTest = fn bool(Type *type, any context);
|
||||
const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type);
|
||||
const ELEMENT_IS_POINTER = Type.kindof == POINTER;
|
||||
|
||||
const Allocator LIST_HEAP_ALLOCATOR = (Allocator)&dummy;
|
||||
|
||||
const List ONHEAP = { .allocator = LIST_HEAP_ALLOCATOR };
|
||||
|
||||
macro type_is_overaligned() => Type.alignof > mem::DEFAULT_MEM_ALIGNMENT;
|
||||
|
||||
struct List (Printable)
|
||||
@@ -276,7 +280,7 @@ fn Type List.get(&self, usz index) @inline
|
||||
|
||||
fn void List.free(&self)
|
||||
{
|
||||
if (!self.allocator || !self.capacity) return;
|
||||
if (!self.allocator || self.allocator.ptr == &dummy || !self.capacity) return;
|
||||
|
||||
self.pre_free(); // Remove sanitizer annotation
|
||||
|
||||
@@ -341,7 +345,17 @@ fn void List.ensure_capacity(&self, usz min_capacity) @local
|
||||
{
|
||||
if (!min_capacity) return;
|
||||
if (self.capacity >= min_capacity) return;
|
||||
if (!self.allocator) self.allocator = tmem();
|
||||
|
||||
// Get a proper allocator
|
||||
switch (self.allocator.ptr)
|
||||
{
|
||||
case &dummy:
|
||||
self.allocator = mem;
|
||||
case null:
|
||||
self.allocator = tmem();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
self.pre_free(); // Remove sanitizer annotation
|
||||
|
||||
@@ -538,3 +552,5 @@ fn usz List.compact(&self) @if(ELEMENT_IS_POINTER)
|
||||
}
|
||||
return list_common::list_compact(self);
|
||||
}
|
||||
|
||||
int dummy @local;
|
||||
|
||||
Reference in New Issue
Block a user