mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
lib/std/io/stream: add LimitReader (#858)
* lib/std/io/stream: add LimitReader Signed-off-by: Pierre Curto <pierre.curto@gmail.com> * lib/std: more method conversions to use new receiver notation Signed-off-by: Pierre Curto <pierre.curto@gmail.com> --------- Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
@@ -25,7 +25,7 @@ struct HashMap
|
||||
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
* @require using != null "The allocator must be non-null"
|
||||
**/
|
||||
fn void HashMap.init(HashMap* map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* using = mem::heap())
|
||||
fn void HashMap.init(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* using = mem::heap())
|
||||
{
|
||||
capacity = math::next_power_of_2(capacity);
|
||||
map.allocator = using;
|
||||
@@ -40,7 +40,7 @@ fn void HashMap.init(HashMap* map, uint capacity = DEFAULT_INITIAL_CAPACITY, flo
|
||||
* @require !map.allocator "Map was already initialized"
|
||||
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
**/
|
||||
fn void HashMap.tinit(HashMap* map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
fn void HashMap.tinit(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
map.init(capacity, load_factor, mem::temp());
|
||||
}
|
||||
@@ -51,28 +51,28 @@ fn void HashMap.tinit(HashMap* map, uint capacity = DEFAULT_INITIAL_CAPACITY, fl
|
||||
* @param [&in] map "The hash map we are testing"
|
||||
* @return "Returns true if it has been initialized, false otherwise"
|
||||
**/
|
||||
fn bool HashMap.is_initialized(HashMap* map)
|
||||
fn bool HashMap.is_initialized(&map)
|
||||
{
|
||||
return map.allocator != null;
|
||||
}
|
||||
|
||||
fn void HashMap.init_from_map(HashMap* map, HashMap* other_map, Allocator* using = mem::heap())
|
||||
fn void HashMap.init_from_map(&map, HashMap* other_map, Allocator* using = mem::heap())
|
||||
{
|
||||
map.init(other_map.table.len, other_map.load_factor, using);
|
||||
map.put_all_for_create(other_map);
|
||||
}
|
||||
|
||||
fn void HashMap.tinit_from_map(HashMap* map, HashMap* other_map)
|
||||
fn void HashMap.tinit_from_map(&map, HashMap* other_map)
|
||||
{
|
||||
map.init_from_map(other_map, mem::temp()) @inline;
|
||||
}
|
||||
|
||||
fn bool HashMap.is_empty(HashMap* map) @inline
|
||||
fn bool HashMap.is_empty(&map) @inline
|
||||
{
|
||||
return !map.count;
|
||||
}
|
||||
|
||||
fn Value*! HashMap.get_ref(HashMap* map, Key key)
|
||||
fn Value*! HashMap.get_ref(&map, Key key)
|
||||
{
|
||||
if (!map.count) return SearchResult.MISSING?;
|
||||
uint hash = rehash(key.hash());
|
||||
@@ -83,7 +83,7 @@ fn Value*! HashMap.get_ref(HashMap* map, Key key)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn Entry*! HashMap.get_entry(HashMap* map, Key key)
|
||||
fn Entry*! HashMap.get_entry(&map, Key key)
|
||||
{
|
||||
if (!map.count) return SearchResult.MISSING?;
|
||||
uint hash = rehash(key.hash());
|
||||
@@ -97,7 +97,7 @@ fn Entry*! HashMap.get_entry(HashMap* map, Key key)
|
||||
/**
|
||||
* Get the value or update and
|
||||
**/
|
||||
macro Value HashMap.@get_or_set(HashMap* map, Key key, Value #expr)
|
||||
macro Value HashMap.@get_or_set(&map, Key key, Value #expr)
|
||||
{
|
||||
if (!map.count)
|
||||
{
|
||||
@@ -116,17 +116,17 @@ macro Value HashMap.@get_or_set(HashMap* map, Key key, Value #expr)
|
||||
return val;
|
||||
}
|
||||
|
||||
fn Value! HashMap.get(HashMap* map, Key key) @operator([])
|
||||
fn Value! HashMap.get(&map, Key key) @operator([])
|
||||
{
|
||||
return *map.get_ref(key) @inline;
|
||||
}
|
||||
|
||||
fn bool HashMap.has_key(HashMap* map, Key key)
|
||||
fn bool HashMap.has_key(&map, Key key)
|
||||
{
|
||||
return @ok(map.get_ref(key));
|
||||
}
|
||||
|
||||
fn bool HashMap.set(HashMap* map, Key key, Value value) @operator([]=)
|
||||
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)
|
||||
@@ -147,12 +147,12 @@ fn bool HashMap.set(HashMap* map, Key key, Value value) @operator([]=)
|
||||
return false;
|
||||
}
|
||||
|
||||
fn void! HashMap.remove(HashMap* map, Key key) @maydiscard
|
||||
fn void! HashMap.remove(&map, Key key) @maydiscard
|
||||
{
|
||||
if (!map.remove_entry_for_key(key)) return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn void HashMap.clear(HashMap* map)
|
||||
fn void HashMap.clear(&map)
|
||||
{
|
||||
if (!map.count) return;
|
||||
foreach (Entry** &entry_ref : map.table)
|
||||
@@ -165,22 +165,22 @@ fn void HashMap.clear(HashMap* map)
|
||||
map.count = 0;
|
||||
}
|
||||
|
||||
fn void HashMap.free(HashMap* map)
|
||||
fn void HashMap.free(&map)
|
||||
{
|
||||
if (!map.allocator) return;
|
||||
map.clear();
|
||||
map.free_internal(map.table.ptr);
|
||||
map.table = Entry*[] {};
|
||||
map.table = {};
|
||||
}
|
||||
|
||||
fn Key[] HashMap.key_tlist(HashMap* map)
|
||||
fn Key[] HashMap.key_tlist(&map)
|
||||
{
|
||||
return map.key_list(mem::temp()) @inline;
|
||||
}
|
||||
|
||||
fn Key[] HashMap.key_list(HashMap* map, Allocator* using = mem::heap())
|
||||
fn Key[] HashMap.key_list(&map, Allocator* using = mem::heap())
|
||||
{
|
||||
if (!map.count) return Key[] {};
|
||||
if (!map.count) return {};
|
||||
|
||||
Key[] list = calloc(Key, map.count, .using = using);
|
||||
usz index = 0;
|
||||
@@ -197,14 +197,14 @@ fn Key[] HashMap.key_list(HashMap* map, Allocator* using = mem::heap())
|
||||
|
||||
|
||||
|
||||
fn Value[] HashMap.value_tlist(HashMap* map)
|
||||
fn Value[] HashMap.value_tlist(&map)
|
||||
{
|
||||
return map.value_list(mem::temp()) @inline;
|
||||
}
|
||||
|
||||
fn Value[] HashMap.value_list(HashMap* map, Allocator* using = mem::heap())
|
||||
fn Value[] HashMap.value_list(&map, Allocator* using = mem::heap())
|
||||
{
|
||||
if (!map.count) return Value[] {};
|
||||
if (!map.count) return {};
|
||||
Value[] list = calloc(Value, map.count, .using = using);
|
||||
usz index = 0;
|
||||
foreach (Entry* entry : map.table)
|
||||
@@ -218,7 +218,7 @@ fn Value[] HashMap.value_list(HashMap* map, Allocator* using = mem::heap())
|
||||
return list;
|
||||
}
|
||||
|
||||
fn bool HashMap.has_value(HashMap* map, Value v) @if(VALUE_IS_EQUATABLE)
|
||||
fn bool HashMap.has_value(&map, Value v) @if(VALUE_IS_EQUATABLE)
|
||||
{
|
||||
if (!map.count) return false;
|
||||
foreach (Entry* entry : map.table)
|
||||
@@ -234,7 +234,7 @@ fn bool HashMap.has_value(HashMap* map, Value v) @if(VALUE_IS_EQUATABLE)
|
||||
|
||||
// --- private methods
|
||||
|
||||
fn void HashMap.add_entry(HashMap* map, uint hash, Key key, Value value, uint bucket_index) @private
|
||||
fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private
|
||||
{
|
||||
Entry* entry = malloc(Entry, .using = map.allocator);
|
||||
*entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] };
|
||||
@@ -245,7 +245,7 @@ fn void HashMap.add_entry(HashMap* map, uint hash, Key key, Value value, uint bu
|
||||
}
|
||||
}
|
||||
|
||||
fn void HashMap.resize(HashMap* map, uint new_capacity) @private
|
||||
fn void HashMap.resize(&map, uint new_capacity) @private
|
||||
{
|
||||
Entry*[] old_table = map.table;
|
||||
uint old_capacity = old_table.len;
|
||||
@@ -272,7 +272,7 @@ macro uint index_for(uint hash, uint capacity) @private
|
||||
return hash & (capacity - 1);
|
||||
}
|
||||
|
||||
fn void HashMap.transfer(HashMap* map, Entry*[] new_table) @private
|
||||
fn void HashMap.transfer(&map, Entry*[] new_table) @private
|
||||
{
|
||||
Entry*[] src = map.table;
|
||||
uint new_capacity = new_table.len;
|
||||
@@ -291,7 +291,7 @@ fn void HashMap.transfer(HashMap* map, Entry*[] new_table) @private
|
||||
}
|
||||
}
|
||||
|
||||
fn void HashMap.put_all_for_create(HashMap* map, HashMap* other_map) @private
|
||||
fn void HashMap.put_all_for_create(&map, HashMap* other_map) @private
|
||||
{
|
||||
if (!other_map.count) return;
|
||||
foreach (Entry *e : other_map.table)
|
||||
@@ -301,7 +301,7 @@ fn void HashMap.put_all_for_create(HashMap* map, HashMap* other_map) @private
|
||||
}
|
||||
}
|
||||
|
||||
fn void HashMap.put_for_create(HashMap* map, Key key, Value value) @private
|
||||
fn void HashMap.put_for_create(&map, Key key, Value value) @private
|
||||
{
|
||||
uint hash = rehash(key.hash());
|
||||
uint i = index_for(hash, map.table.len);
|
||||
@@ -316,12 +316,12 @@ fn void HashMap.put_for_create(HashMap* map, Key key, Value value) @private
|
||||
map.create_entry(hash, key, value, i);
|
||||
}
|
||||
|
||||
fn void HashMap.free_internal(HashMap* map, void* ptr) @inline @private
|
||||
fn void HashMap.free_internal(&map, void* ptr) @inline @private
|
||||
{
|
||||
map.allocator.free(ptr)!!;
|
||||
}
|
||||
|
||||
fn bool HashMap.remove_entry_for_key(HashMap* map, Key key) @private
|
||||
fn bool HashMap.remove_entry_for_key(&map, Key key) @private
|
||||
{
|
||||
uint hash = rehash(key.hash());
|
||||
uint i = index_for(hash, map.table.len);
|
||||
@@ -350,7 +350,7 @@ fn bool HashMap.remove_entry_for_key(HashMap* map, Key key) @private
|
||||
return false;
|
||||
}
|
||||
|
||||
fn void HashMap.create_entry(HashMap* map, uint hash, Key key, Value value, int bucket_index) @private
|
||||
fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private
|
||||
{
|
||||
Entry *e = map.table[bucket_index];
|
||||
Entry* entry = malloc(Entry, .using = map.allocator);
|
||||
|
||||
36
lib/std/io/stream/limitreader.c3
Normal file
36
lib/std/io/stream/limitreader.c3
Normal file
@@ -0,0 +1,36 @@
|
||||
module std::io::stream;
|
||||
|
||||
struct LimitReader
|
||||
{
|
||||
Stream reader;
|
||||
usz limit;
|
||||
}
|
||||
|
||||
fn void LimitReader.init(&self, Stream reader, usz limit)
|
||||
{
|
||||
*self = { .reader = reader, .limit = limit };
|
||||
}
|
||||
|
||||
fn usz! LimitReader.read(&self, char[] bytes)
|
||||
{
|
||||
if (self.limit == 0) return IoError.EOF?;
|
||||
usz m = min(bytes.len, self.limit);
|
||||
usz n = self.reader.read(bytes[:m])!;
|
||||
self.limit -= n;
|
||||
return n;
|
||||
}
|
||||
|
||||
fn Stream LimitReader.as_stream(&self)
|
||||
{
|
||||
return { .fns = &limitreader_interface, .data = self };
|
||||
}
|
||||
|
||||
fn usz LimitReader.available(&self)
|
||||
{
|
||||
return self.limit;
|
||||
}
|
||||
|
||||
StreamInterface limitreader_interface = {
|
||||
.read_fn = fn(s, char[] bytes) => ((LimitReader*)s.data).read(bytes),
|
||||
.available_fn = fn(s) => ((LimitReader*)s.data).available(),
|
||||
};
|
||||
@@ -21,7 +21,7 @@ struct RandomInterface
|
||||
* @param [&inout] random
|
||||
* @param [inout] buffer
|
||||
**/
|
||||
fn void Random.next_bytes(Random* random, char[] buffer)
|
||||
fn void Random.next_bytes(&random, char[] buffer)
|
||||
{
|
||||
if (!buffer.len) return;
|
||||
if (RandomNextBytesFn func = random.fns.next_bytes_fn)
|
||||
@@ -50,7 +50,7 @@ fn void Random.next_bytes(Random* random, char[] buffer)
|
||||
* @param [&inout] random
|
||||
* @require bits >= 0 && bits <= 32
|
||||
**/
|
||||
fn uint Random.next(Random* random, int bits)
|
||||
fn uint Random.next(&random, int bits)
|
||||
{
|
||||
if (bits == 0) return 0;
|
||||
if (RandomNextFn func = random.fns.next_fn) return func(random, bits);
|
||||
@@ -71,7 +71,7 @@ fn uint Random.next(Random* random, int bits)
|
||||
/**
|
||||
* @param [&inout] random
|
||||
**/
|
||||
fn ulong Random.next_long(Random* random)
|
||||
fn ulong Random.next_long(&random)
|
||||
{
|
||||
char[8] buffer;
|
||||
random.next_bytes(&buffer);
|
||||
@@ -81,7 +81,7 @@ fn ulong Random.next_long(Random* random)
|
||||
/**
|
||||
* @param [&inout] random
|
||||
**/
|
||||
fn void Random.set_seed(Random* random, long seed)
|
||||
fn void Random.set_seed(&random, long seed)
|
||||
{
|
||||
random.fns.seed_fn(random, &&bitcast(seed, char[8])) @inline;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ fn void Random.set_seed(Random* random, long seed)
|
||||
* @param [&inout] random
|
||||
* @param [in] seed
|
||||
**/
|
||||
fn void Random.set_seeds(Random* random, char[] seed)
|
||||
fn void Random.set_seeds(&random, char[] seed)
|
||||
{
|
||||
random.fns.seed_fn(random, seed);
|
||||
}
|
||||
@@ -98,22 +98,22 @@ fn void Random.set_seeds(Random* random, char[] seed)
|
||||
/**
|
||||
* @param [&inout] random
|
||||
**/
|
||||
fn bool Random.next_bool(Random* random)
|
||||
fn bool Random.next_bool(&random)
|
||||
{
|
||||
return random.next(1) != 0;
|
||||
}
|
||||
|
||||
fn float Random.next_float(Random* r)
|
||||
fn float Random.next_float(&r)
|
||||
{
|
||||
return r.next(24) / (float)(1 << 24);
|
||||
}
|
||||
|
||||
fn double Random.next_double(Random* r)
|
||||
fn double Random.next_double(&r)
|
||||
{
|
||||
return (((long)(r.next(26)) << 27) + r.next(27)) * 0x1.0p-53;
|
||||
}
|
||||
|
||||
fn uint Random.next_int(Random* r)
|
||||
fn uint Random.next_int(&r)
|
||||
{
|
||||
return r.next(32) @inline;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ macro Matrix4f Quaternion.to_matrixf(Quaternion* q) => into_matrix(q, Matrix4f);
|
||||
macro Matrix4 Quaternion.to_matrix(Quaternion* q) => into_matrix(q, Matrix4);
|
||||
fn Quaternion Quaternion.nlerp(Quaternion q1, Quaternion q2, Real amount) => { .v = q1.v.lerp(q2.v, amount).normalize() };
|
||||
|
||||
fn Quaternion Quaternion.invert(Quaternion q)
|
||||
fn Quaternion Quaternion.invert(q)
|
||||
{
|
||||
Real length_sq = q.v.dot(q.v);
|
||||
if (length_sq <= 0) return q;
|
||||
@@ -30,7 +30,7 @@ fn Quaternion Quaternion.invert(Quaternion q)
|
||||
return { q.v[0] * -inv_length, q.v[1] * -inv_length, q.v[2] * -inv_length, q.v[3] * inv_length };
|
||||
}
|
||||
|
||||
fn Quaternion Quaternion.slerp(Quaternion q1, Quaternion q2, Real amount)
|
||||
fn Quaternion Quaternion.slerp(q1, Quaternion q2, Real amount)
|
||||
{
|
||||
Quaternion result = {};
|
||||
|
||||
@@ -59,7 +59,7 @@ fn Quaternion Quaternion.slerp(Quaternion q1, Quaternion q2, Real amount)
|
||||
return { .v = q1v * ratio_a + q2v * ratio_b };
|
||||
}
|
||||
|
||||
fn Quaternion Quaternion.mul(Quaternion a, Quaternion b)
|
||||
fn Quaternion Quaternion.mul(a, Quaternion b)
|
||||
{
|
||||
return { a.i * b.l + a.l * b.i + a.j * b.k - a.k * b.j,
|
||||
a.j * b.l + a.l * b.j + a.k * b.i - a.i * b.k,
|
||||
|
||||
@@ -16,12 +16,12 @@ const MUL_LCG16 @local = 0x915d; // TODO: Find good constant
|
||||
|
||||
def Lcg128_64 = distinct uint128;
|
||||
|
||||
fn void Lcg128_64.seed(Lcg128_64* lcg, char[16] seed)
|
||||
fn void Lcg128_64.seed(&lcg, char[16] seed)
|
||||
{
|
||||
*lcg = bitcast(seed, Lcg128_64);
|
||||
}
|
||||
|
||||
fn ulong Lcg128_64.next(Lcg128_64* lcg)
|
||||
fn ulong Lcg128_64.next(&lcg)
|
||||
{
|
||||
uint128* s = (uint128*)lcg;
|
||||
ulong result = (ulong)(*s >> 64);
|
||||
@@ -34,12 +34,12 @@ fn ulong Lcg128_64.next(Lcg128_64* lcg)
|
||||
|
||||
def Lcg64_32 = distinct ulong;
|
||||
|
||||
fn void Lcg64_32.seed(Lcg64_32* lcg, char[8] seed)
|
||||
fn void Lcg64_32.seed(&lcg, char[8] seed)
|
||||
{
|
||||
*lcg = bitcast(seed, Lcg64_32);
|
||||
}
|
||||
|
||||
fn uint Lcg64_32.next(Lcg64_32* lcg)
|
||||
fn uint Lcg64_32.next(&lcg)
|
||||
{
|
||||
ulong* s = (ulong*)lcg;
|
||||
uint result = (uint)(*s >> 32);
|
||||
@@ -52,12 +52,12 @@ fn uint Lcg64_32.next(Lcg64_32* lcg)
|
||||
|
||||
def Lcg32_16 = distinct uint;
|
||||
|
||||
fn void Lcg32_16.seed(Lcg32_16* lcg, char[4] seed)
|
||||
fn void Lcg32_16.seed(&lcg, char[4] seed)
|
||||
{
|
||||
*lcg = bitcast(seed, Lcg32_16);
|
||||
}
|
||||
|
||||
fn ushort Lcg32_16.next(Lcg32_16* lcg)
|
||||
fn ushort Lcg32_16.next(&lcg)
|
||||
{
|
||||
uint* s = (uint*)lcg;
|
||||
ushort result = (ushort)(*s >> 16);
|
||||
@@ -70,12 +70,12 @@ fn ushort Lcg32_16.next(Lcg32_16* lcg)
|
||||
|
||||
def Lcg16_8 = distinct ushort;
|
||||
|
||||
fn void Lcg16_8.seed(Lcg16_8* lcg, char[2] seed)
|
||||
fn void Lcg16_8.seed(&lcg, char[2] seed)
|
||||
{
|
||||
*lcg = bitcast(seed, Lcg16_8);
|
||||
}
|
||||
|
||||
fn char Lcg16_8.next(Lcg16_8* lcg)
|
||||
fn char Lcg16_8.next(&lcg)
|
||||
{
|
||||
ushort* s = (ushort*)lcg;
|
||||
char result = (char)(*s >> 8);
|
||||
|
||||
@@ -9,12 +9,12 @@ const MUL_MCG16 @local = 0x93d5; // TODO: Find good constant
|
||||
|
||||
def Mcg128_64 = distinct uint128;
|
||||
|
||||
fn void Mcg128_64.seed(Mcg128_64* mcg, char[16] seed)
|
||||
fn void Mcg128_64.seed(&mcg, char[16] seed)
|
||||
{
|
||||
*mcg = bitcast(seed, Mcg128_64) | 1;
|
||||
}
|
||||
|
||||
fn ulong Mcg128_64.next(Mcg128_64* mcg)
|
||||
fn ulong Mcg128_64.next(&mcg)
|
||||
{
|
||||
uint128* s = (uint128*)mcg;
|
||||
ulong result = (ulong)(*s >> 64);
|
||||
@@ -27,12 +27,12 @@ fn ulong Mcg128_64.next(Mcg128_64* mcg)
|
||||
|
||||
def Mcg64_32 = distinct ulong;
|
||||
|
||||
fn void Mcg64_32.seed(Mcg64_32* mcg, char[8] seed)
|
||||
fn void Mcg64_32.seed(&mcg, char[8] seed)
|
||||
{
|
||||
*mcg = bitcast(seed, Mcg64_32) | 1;
|
||||
}
|
||||
|
||||
fn uint Mcg64_32.next(Mcg64_32* mcg)
|
||||
fn uint Mcg64_32.next(&mcg)
|
||||
{
|
||||
ulong* s = (ulong*)mcg;
|
||||
uint result = (uint)(*s >> 32);
|
||||
@@ -45,12 +45,12 @@ fn uint Mcg64_32.next(Mcg64_32* mcg)
|
||||
|
||||
def Mcg32_16 = distinct uint;
|
||||
|
||||
fn void Mcg32_16.seed(Mcg32_16* mcg, char[4] seed)
|
||||
fn void Mcg32_16.seed(&mcg, char[4] seed)
|
||||
{
|
||||
*mcg = bitcast(seed, Mcg32_16) | 1;
|
||||
}
|
||||
|
||||
fn ushort Mcg32_16.next(Mcg32_16* mcg)
|
||||
fn ushort Mcg32_16.next(&mcg)
|
||||
{
|
||||
uint* s = (uint*)mcg;
|
||||
ushort result = (ushort)(*s >> 16);
|
||||
@@ -63,12 +63,12 @@ fn ushort Mcg32_16.next(Mcg32_16* mcg)
|
||||
|
||||
def Mcg16_8 = distinct ushort;
|
||||
|
||||
fn void Mcg16_8.seed(Mcg16_8* mcg, char[2] seed)
|
||||
fn void Mcg16_8.seed(&mcg, char[2] seed)
|
||||
{
|
||||
*mcg = bitcast(seed, Mcg16_8) | 1;
|
||||
}
|
||||
|
||||
fn char Mcg16_8.next(Mcg16_8* mcg)
|
||||
fn char Mcg16_8.next(&mcg)
|
||||
{
|
||||
ushort* s = (ushort*)mcg;
|
||||
char result = (char)(*s >> 8);
|
||||
|
||||
@@ -15,12 +15,12 @@ struct Msws128 {
|
||||
uint128 weyl0, weyl1;
|
||||
}
|
||||
|
||||
fn void Msws128.seed(Msws128* msws, char[16 * 4] seed)
|
||||
fn void Msws128.seed(&msws, char[16 * 4] seed)
|
||||
{
|
||||
*msws = bitcast(seed, Msws128);
|
||||
}
|
||||
|
||||
fn uint128 Msws128.next(Msws128* msws)
|
||||
fn uint128 Msws128.next(&msws)
|
||||
{
|
||||
uint128 s0 = msws.state0;
|
||||
msws.state0 = msws.state0 * msws.state0 + msws.weyl0;
|
||||
@@ -43,12 +43,12 @@ struct Msws64 {
|
||||
ulong weyl0, weyl1;
|
||||
}
|
||||
|
||||
fn void Msws64.seed(Msws64* msws, char[8 * 4] seed)
|
||||
fn void Msws64.seed(&msws, char[8 * 4] seed)
|
||||
{
|
||||
*msws = bitcast(seed, Msws64);
|
||||
}
|
||||
|
||||
fn ulong Msws64.next(Msws64* msws)
|
||||
fn ulong Msws64.next(&msws)
|
||||
{
|
||||
ulong s0 = msws.state0;
|
||||
msws.state0 = msws.state0 * msws.state0 + msws.weyl0;
|
||||
@@ -71,12 +71,12 @@ struct Msws32 {
|
||||
uint weyl0, weyl1;
|
||||
}
|
||||
|
||||
fn void Msws32.seed(Msws32* msws, char[4 * 4] seed)
|
||||
fn void Msws32.seed(&msws, char[4 * 4] seed)
|
||||
{
|
||||
*msws = bitcast(seed, Msws32);
|
||||
}
|
||||
|
||||
fn uint Msws32.next(Msws32* msws)
|
||||
fn uint Msws32.next(&msws)
|
||||
{
|
||||
uint s0 = msws.state0;
|
||||
msws.state0 = msws.state0 * msws.state0 + msws.weyl0;
|
||||
@@ -99,12 +99,12 @@ struct Msws16 {
|
||||
ushort weyl0, weyl1;
|
||||
}
|
||||
|
||||
fn void Msws16.seed(Msws16* msws, char[2 * 4] seed)
|
||||
fn void Msws16.seed(&msws, char[2 * 4] seed)
|
||||
{
|
||||
*msws = bitcast(seed, Msws16);
|
||||
}
|
||||
|
||||
fn ushort Msws16.next(Msws16* msws)
|
||||
fn ushort Msws16.next(&msws)
|
||||
{
|
||||
ushort s0 = msws.state0;
|
||||
msws.state0 = msws.state0 * msws.state0 + msws.weyl0;
|
||||
@@ -127,12 +127,12 @@ struct Msws8 {
|
||||
char weyl0, weyl1;
|
||||
}
|
||||
|
||||
fn void Msws8.seed(Msws8* msws, char[1 * 4] seed)
|
||||
fn void Msws8.seed(&msws, char[1 * 4] seed)
|
||||
{
|
||||
*msws = bitcast(seed, Msws8);
|
||||
}
|
||||
|
||||
fn char Msws8.next(Msws8* msws)
|
||||
fn char Msws8.next(&msws)
|
||||
{
|
||||
char s0 = msws.state0;
|
||||
msws.state0 = msws.state0 * msws.state0 + msws.weyl0;
|
||||
|
||||
@@ -16,12 +16,12 @@ const MUL_LCG16 @local = 0x915d; // TODO: Find good constant
|
||||
|
||||
def Pcg128_64 = distinct uint128;
|
||||
|
||||
fn void Pcg128_64.seed(Pcg128_64* pcg, char[16] seed)
|
||||
fn void Pcg128_64.seed(&pcg, char[16] seed)
|
||||
{
|
||||
*pcg = bitcast(seed, Pcg128_64);
|
||||
}
|
||||
|
||||
fn ulong Pcg128_64.next(Pcg128_64* pcg)
|
||||
fn ulong Pcg128_64.next(&pcg)
|
||||
{
|
||||
const ROT_SHIFT = 64 - 6;
|
||||
uint128* s = (uint128*)pcg;
|
||||
@@ -36,12 +36,12 @@ fn ulong Pcg128_64.next(Pcg128_64* pcg)
|
||||
|
||||
def Pcg64_32 = distinct ulong;
|
||||
|
||||
fn void Pcg64_32.seed(Pcg64_32* pcg, char[8] seed)
|
||||
fn void Pcg64_32.seed(&pcg, char[8] seed)
|
||||
{
|
||||
*pcg = bitcast(seed, Pcg64_32);
|
||||
}
|
||||
|
||||
fn uint Pcg64_32.next(Pcg64_32* pcg)
|
||||
fn uint Pcg64_32.next(&pcg)
|
||||
{
|
||||
const ROT_SHIFT = 32 - 5;
|
||||
ulong* s = (ulong*)pcg;
|
||||
@@ -56,12 +56,12 @@ fn uint Pcg64_32.next(Pcg64_32* pcg)
|
||||
|
||||
def Pcg32_16 = distinct uint;
|
||||
|
||||
fn void Pcg32_16.seed(Pcg32_16* pcg, char[4] seed)
|
||||
fn void Pcg32_16.seed(&pcg, char[4] seed)
|
||||
{
|
||||
*pcg = bitcast(seed, Pcg32_16);
|
||||
}
|
||||
|
||||
fn ushort Pcg32_16.next(Pcg32_16* pcg)
|
||||
fn ushort Pcg32_16.next(&pcg)
|
||||
{
|
||||
const ROT_SHIFT = 16 - 4;
|
||||
uint* s = (uint*)pcg;
|
||||
@@ -76,12 +76,12 @@ fn ushort Pcg32_16.next(Pcg32_16* pcg)
|
||||
|
||||
def Pcg16_8 = distinct ushort;
|
||||
|
||||
fn void Pcg16_8.seed(Pcg16_8* pcg, char[2] seed)
|
||||
fn void Pcg16_8.seed(&pcg, char[2] seed)
|
||||
{
|
||||
*pcg = bitcast(seed, Pcg16_8);
|
||||
}
|
||||
|
||||
fn char Pcg16_8.next(Pcg16_8* pcg)
|
||||
fn char Pcg16_8.next(&pcg)
|
||||
{
|
||||
const ROT_SHIFT = 8 - 3;
|
||||
ushort* s = (ushort*)pcg;
|
||||
|
||||
@@ -12,12 +12,12 @@ const ODD_PHI8 @local = 0x9f;
|
||||
|
||||
def Sfc128 = distinct uint128[4];
|
||||
|
||||
fn void Sfc128.seed(Sfc128* sfc, char[16 * 4] seed)
|
||||
fn void Sfc128.seed(&sfc, char[16 * 4] seed)
|
||||
{
|
||||
*sfc = bitcast(seed, Sfc128);
|
||||
}
|
||||
|
||||
fn uint128 Sfc128.next(Sfc128* sfc) // TODO: Find good constant
|
||||
fn uint128 Sfc128.next(&sfc) // TODO: Find good constant
|
||||
{
|
||||
uint128* s = (uint128[4]*)sfc;
|
||||
uint128 result = s[0] + s[1] + s[3];
|
||||
@@ -33,12 +33,12 @@ fn uint128 Sfc128.next(Sfc128* sfc) // TODO: Find good constant
|
||||
|
||||
def Sfc64 = distinct ulong[4];
|
||||
|
||||
fn void Sfc64.seed(Sfc64* sfc, char[8 * 4] seed)
|
||||
fn void Sfc64.seed(&sfc, char[8 * 4] seed)
|
||||
{
|
||||
*sfc = bitcast(seed, Sfc64);
|
||||
}
|
||||
|
||||
fn ulong Sfc64.next(Sfc64* sfc)
|
||||
fn ulong Sfc64.next(&sfc)
|
||||
{
|
||||
ulong* s = (ulong[4]*)sfc;
|
||||
ulong result = s[0] + s[1] + s[3];
|
||||
@@ -54,12 +54,12 @@ fn ulong Sfc64.next(Sfc64* sfc)
|
||||
|
||||
def Sfc32 = distinct uint[4];
|
||||
|
||||
fn void Sfc32.seed(Sfc32* sfc, char[4 * 4] seed)
|
||||
fn void Sfc32.seed(&sfc, char[4 * 4] seed)
|
||||
{
|
||||
*sfc = bitcast(seed, Sfc32);
|
||||
}
|
||||
|
||||
fn uint Sfc32.next(Sfc32* sfc)
|
||||
fn uint Sfc32.next(&sfc)
|
||||
{
|
||||
uint* s = (uint[4]*)sfc;
|
||||
uint result = s[0] + s[1] + s[3];
|
||||
@@ -75,12 +75,12 @@ fn uint Sfc32.next(Sfc32* sfc)
|
||||
|
||||
def Sfc16 = distinct ushort[4];
|
||||
|
||||
fn void Sfc16.seed(Sfc16* sfc, char[2 * 4] seed)
|
||||
fn void Sfc16.seed(&sfc, char[2 * 4] seed)
|
||||
{
|
||||
*sfc = bitcast(seed, Sfc16);
|
||||
}
|
||||
|
||||
fn ushort Sfc16.next(Sfc16* sfc)
|
||||
fn ushort Sfc16.next(&sfc)
|
||||
{
|
||||
ushort* s = (ushort[4]*)sfc;
|
||||
ushort result = s[0] + s[1] + s[3];
|
||||
@@ -96,12 +96,12 @@ fn ushort Sfc16.next(Sfc16* sfc)
|
||||
|
||||
def Sfc8 = distinct char[4];
|
||||
|
||||
fn void Sfc8.seed(Sfc8* sfc, char[1 * 4] seed)
|
||||
fn void Sfc8.seed(&sfc, char[1 * 4] seed)
|
||||
{
|
||||
*sfc = bitcast(seed, Sfc8);
|
||||
}
|
||||
|
||||
fn char Sfc8.next(Sfc8* sfc) // TODO: Find better constants
|
||||
fn char Sfc8.next(&sfc) // TODO: Find better constants
|
||||
{
|
||||
char* s = (char[4]*)sfc;
|
||||
char result = s[0] + s[1] + s[3];
|
||||
|
||||
@@ -11,23 +11,23 @@ RandomInterface simple_random_interface = {
|
||||
.next_fn = fn (random, bits) => ((SimpleRandom*)random.state).next(bits)
|
||||
};
|
||||
|
||||
fn Random SimpleRandom.as_random(SimpleRandom* random)
|
||||
fn Random SimpleRandom.as_random(&random)
|
||||
{
|
||||
return { .fns = simple_random_interface, .state = random };
|
||||
}
|
||||
|
||||
fn uint SimpleRandom.next(SimpleRandom* r, int bits)
|
||||
fn uint SimpleRandom.next(&r, int bits)
|
||||
{
|
||||
ulong nextseed = ((ulong)*r * SIMPLE_RANDOM_MULTIPLIER + SIMPLE_RANDOM_ADDEND) & SIMPLE_RANDOM_MASK;
|
||||
*r = (SimpleRandom)nextseed;
|
||||
return (uint)(nextseed >> (48 - bits));
|
||||
}
|
||||
|
||||
fn void SimpleRandom.set_seed(SimpleRandom* r, ulong seed)
|
||||
fn void SimpleRandom.set_seed(&r, ulong seed)
|
||||
{
|
||||
*r = (SimpleRandom)((seed ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK);
|
||||
}
|
||||
fn void SimpleRandom.set_seeds(SimpleRandom* r, char[] seed)
|
||||
fn void SimpleRandom.set_seeds(&r, char[] seed)
|
||||
{
|
||||
char[8] full;
|
||||
foreach (i, c : seed)
|
||||
|
||||
@@ -333,71 +333,71 @@ fn SubProcess! create(String[] command_line, SubProcessOptions options = {}, Str
|
||||
};
|
||||
}
|
||||
|
||||
fn CInt! SubProcess.join(SubProcess *this) @if(env::POSIX)
|
||||
fn CInt! SubProcess.join(&self) @if(env::POSIX)
|
||||
{
|
||||
if (this.stdin_file)
|
||||
if (self.stdin_file)
|
||||
{
|
||||
libc::fclose(this.stdin_file);
|
||||
this.stdin_file = null;
|
||||
libc::fclose(self.stdin_file);
|
||||
self.stdin_file = null;
|
||||
}
|
||||
CInt status;
|
||||
if (this.child && this.child != posix::waitpid(this.child, &status, 0)) return SubProcessResult.PROCESS_JOIN_FAILED?;
|
||||
if (self.child && self.child != posix::waitpid(self.child, &status, 0)) return SubProcessResult.PROCESS_JOIN_FAILED?;
|
||||
|
||||
this.child = 0;
|
||||
this.is_alive = false;
|
||||
self.child = 0;
|
||||
self.is_alive = false;
|
||||
|
||||
return this.return_status = posix::wIFEXITED(status) ? posix::wEXITSTATUS(status) : libc::EXIT_FAILURE;
|
||||
return self.return_status = posix::wIFEXITED(status) ? posix::wEXITSTATUS(status) : libc::EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fn File SubProcess.stdout(SubProcess* this)
|
||||
fn File SubProcess.stdout(&self)
|
||||
{
|
||||
return file::from_libc(this.stdout_file);
|
||||
return file::from_libc(self.stdout_file);
|
||||
}
|
||||
|
||||
fn CInt! SubProcess.join(SubProcess *this) @if(env::WIN32)
|
||||
fn CInt! SubProcess.join(&self) @if(env::WIN32)
|
||||
{
|
||||
if (this.stdin_file)
|
||||
if (self.stdin_file)
|
||||
{
|
||||
libc::fclose(this.stdin_file);
|
||||
this.stdin_file = null;
|
||||
libc::fclose(self.stdin_file);
|
||||
self.stdin_file = null;
|
||||
}
|
||||
if (this.hStdInput)
|
||||
if (self.hStdInput)
|
||||
{
|
||||
win32::closeHandle(this.hStdInput);
|
||||
this.hStdInput = null;
|
||||
win32::closeHandle(self.hStdInput);
|
||||
self.hStdInput = null;
|
||||
}
|
||||
win32::waitForSingleObject(this.hProcess, win32::INFINITE);
|
||||
win32::waitForSingleObject(self.hProcess, win32::INFINITE);
|
||||
Win32_DWORD return_code @noinit;
|
||||
if (!win32::getExitCodeProcess(this.hProcess, &return_code)) return SubProcessResult.PROCESS_JOIN_FAILED?;
|
||||
this.is_alive = false;
|
||||
if (!win32::getExitCodeProcess(self.hProcess, &return_code)) return SubProcessResult.PROCESS_JOIN_FAILED?;
|
||||
self.is_alive = false;
|
||||
return return_code;
|
||||
}
|
||||
|
||||
fn bool SubProcess.destroy(SubProcess* this)
|
||||
fn bool SubProcess.destroy(&self)
|
||||
{
|
||||
if (this.stdin_file) libc::fclose(this.stdin_file);
|
||||
if (this.stdout_file)
|
||||
if (self.stdin_file) libc::fclose(self.stdin_file);
|
||||
if (self.stdout_file)
|
||||
{
|
||||
libc::fclose(this.stdout_file);
|
||||
if (this.stdout_file != this.stderr_file) libc::fclose(this.stderr_file);
|
||||
libc::fclose(self.stdout_file);
|
||||
if (self.stdout_file != self.stderr_file) libc::fclose(self.stderr_file);
|
||||
}
|
||||
this.stdin_file = this.stdout_file = this.stderr_file = null;
|
||||
self.stdin_file = self.stdout_file = self.stderr_file = null;
|
||||
$if env::WIN32:
|
||||
if (this.hProcess) win32::closeHandle(this.hProcess);
|
||||
if (this.hStdInput) win32::closeHandle(this.hStdInput);
|
||||
if (this.hEventOutput) win32::closeHandle(this.hEventOutput);
|
||||
if (this.hEventError) win32::closeHandle(this.hEventError);
|
||||
this.hProcess = this.hStdInput = this.hEventOutput = this.hEventError = null;
|
||||
if (self.hProcess) win32::closeHandle(self.hProcess);
|
||||
if (self.hStdInput) win32::closeHandle(self.hStdInput);
|
||||
if (self.hEventOutput) win32::closeHandle(self.hEventOutput);
|
||||
if (self.hEventError) win32::closeHandle(self.hEventError);
|
||||
self.hProcess = self.hStdInput = self.hEventOutput = self.hEventError = null;
|
||||
$endif;
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void! SubProcess.terminate(SubProcess* this)
|
||||
fn void! SubProcess.terminate(&self)
|
||||
{
|
||||
$if env::WIN32:
|
||||
if (!win32::terminateProcess(this.hProcess, 99)) return SubProcessResult.PROCESS_TERMINATION_FAILED?;
|
||||
if (!win32::terminateProcess(self.hProcess, 99)) return SubProcessResult.PROCESS_TERMINATION_FAILED?;
|
||||
$else
|
||||
if (posix::kill(this.child, 9)) return SubProcessResult.PROCESS_TERMINATION_FAILED?;
|
||||
if (posix::kill(self.child, 9)) return SubProcessResult.PROCESS_TERMINATION_FAILED?;
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -437,39 +437,39 @@ fn usz! read_from_file_posix(CFile file, char* buffer, usz size) @if(env::POSIX)
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
fn usz! SubProcess.read_stdout(SubProcess* this, char* buffer, usz size)
|
||||
fn usz! SubProcess.read_stdout(&self, char* buffer, usz size)
|
||||
{
|
||||
$if env::WIN32:
|
||||
return read_from_file_win32(this.stdout_file, this.hEventOutput, buffer, size);
|
||||
return read_from_file_win32(self.stdout_file, self.hEventOutput, buffer, size);
|
||||
$else
|
||||
return read_from_file_posix(this.stdout_file, buffer, size);
|
||||
return read_from_file_posix(self.stdout_file, buffer, size);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn usz! SubProcess.read_stderr(SubProcess* this, char* buffer, usz size)
|
||||
fn usz! SubProcess.read_stderr(&self, char* buffer, usz size)
|
||||
{
|
||||
$if env::WIN32:
|
||||
return read_from_file_win32(this.stderr_file, this.hEventError, buffer, size);
|
||||
return read_from_file_win32(self.stderr_file, self.hEventError, buffer, size);
|
||||
$else
|
||||
return read_from_file_posix(this.stderr_file, buffer, size);
|
||||
return read_from_file_posix(self.stderr_file, buffer, size);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool! SubProcess.is_alive(SubProcess* this)
|
||||
fn bool! SubProcess.is_alive(&self)
|
||||
{
|
||||
if (!this.is_alive) return false;
|
||||
if (!self.is_alive) return false;
|
||||
$if env::WIN32:
|
||||
bool is_alive = win32::waitForSingleObject(this.hProcess, 0) != win32::WAIT_OBJECT_0;
|
||||
if (!is_alive) this.is_alive = false;
|
||||
bool is_alive = win32::waitForSingleObject(self.hProcess, 0) != win32::WAIT_OBJECT_0;
|
||||
if (!is_alive) self.is_alive = false;
|
||||
return is_alive;
|
||||
$else
|
||||
CInt status;
|
||||
bool is_alive = posix::waitpid(this.child, &status, posix::WNOHANG) == 0;
|
||||
bool is_alive = posix::waitpid(self.child, &status, posix::WNOHANG) == 0;
|
||||
if (is_alive) return true;
|
||||
this.is_alive = false;
|
||||
this.return_status = posix::wIFEXITED(status) ? posix::wEXITSTATUS(status) : libc::EXIT_FAILURE;
|
||||
this.child = 0;
|
||||
this.join()!;
|
||||
self.is_alive = false;
|
||||
self.return_status = posix::wIFEXITED(status) ? posix::wEXITSTATUS(status) : libc::EXIT_FAILURE;
|
||||
self.child = 0;
|
||||
self.join()!;
|
||||
return false;
|
||||
$endif
|
||||
}
|
||||
@@ -6,7 +6,7 @@ def NativeConditionVariable = Pthread_cond_t;
|
||||
def NativeThread = Pthread_t;
|
||||
def NativeOnceFlag = Pthread_once_t;
|
||||
|
||||
fn void! NativeMutex.init(NativeMutex* mutex, MutexType type)
|
||||
fn void! NativeMutex.init(&mtx, MutexType type)
|
||||
{
|
||||
Pthread_mutexattr_t attr;
|
||||
if (pthread_mutexattr_init(&attr)) return ThreadFault.INIT_FAILED?;
|
||||
@@ -15,20 +15,20 @@ fn void! NativeMutex.init(NativeMutex* mutex, MutexType type)
|
||||
{
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return ThreadFault.INIT_FAILED?;
|
||||
}
|
||||
if (pthread_mutex_init(mutex, &attr)) return ThreadFault.INIT_FAILED?;
|
||||
if (pthread_mutex_init(mtx, &attr)) return ThreadFault.INIT_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.destroy(NativeMutex* mtx)
|
||||
fn void! NativeMutex.destroy(&mtx)
|
||||
{
|
||||
if (pthread_mutex_destroy(mtx)) return ThreadFault.DESTROY_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.lock(NativeMutex* mtx)
|
||||
fn void! NativeMutex.lock(&mtx)
|
||||
{
|
||||
if (pthread_mutex_lock(mtx)) return ThreadFault.LOCK_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.lock_timeoutout(NativeMutex* mtx, ulong ms)
|
||||
fn void! NativeMutex.lock_timeoutout(&mtx, ulong ms)
|
||||
{
|
||||
/* Try to acquire the lock and, if we fail, sleep for 5ms. */
|
||||
Errno result;
|
||||
@@ -51,42 +51,42 @@ fn void! NativeMutex.lock_timeoutout(NativeMutex* mtx, ulong ms)
|
||||
}
|
||||
}
|
||||
|
||||
fn bool NativeMutex.try_lock(NativeMutex* mtx)
|
||||
fn bool NativeMutex.try_lock(&mtx)
|
||||
{
|
||||
return !pthread_mutex_trylock(mtx);
|
||||
}
|
||||
|
||||
fn void! NativeMutex.unlock(NativeMutex* mtx)
|
||||
fn void! NativeMutex.unlock(&mtx)
|
||||
{
|
||||
if (pthread_mutex_unlock(mtx)) return ThreadFault.UNLOCK_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.init(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.init(&cond)
|
||||
{
|
||||
if (pthread_cond_init(cond, null)) return ThreadFault.INIT_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.destroy(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.destroy(&cond)
|
||||
{
|
||||
if (pthread_cond_destroy(cond)) return ThreadFault.DESTROY_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.signal(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.signal(&cond)
|
||||
{
|
||||
if (pthread_cond_signal(cond)) return ThreadFault.SIGNAL_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.broadcast(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.broadcast(&cond)
|
||||
{
|
||||
if (pthread_cond_broadcast(cond)) return ThreadFault.SIGNAL_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.wait(NativeConditionVariable* cond, NativeMutex* mtx)
|
||||
fn void! NativeConditionVariable.wait(&cond, NativeMutex* mtx)
|
||||
{
|
||||
if (pthread_cond_wait(cond, mtx)) return ThreadFault.WAIT_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.wait_timeout(NativeConditionVariable* cond, NativeMutex* mtx, ulong ms)
|
||||
fn void! NativeConditionVariable.wait_timeout(&cond, NativeMutex* mtx, ulong ms)
|
||||
{
|
||||
TimeSpec now;
|
||||
if (libc::timespec_get(&now, libc::TIME_UTC) != libc::TIME_UTC) return ThreadFault.WAIT_FAILED?;
|
||||
@@ -110,7 +110,7 @@ fn void* callback(void* arg) @private
|
||||
return (void*)(iptr)data.thread_fn(data.arg);
|
||||
}
|
||||
|
||||
fn void! NativeThread.create(NativeThread* thread, ThreadFn thread_fn, void* arg)
|
||||
fn void! NativeThread.create(&thread, ThreadFn thread_fn, void* arg)
|
||||
{
|
||||
PosixThreadData *thread_data = malloc(PosixThreadData);
|
||||
*thread_data = { .thread_fn = thread_fn, .arg = arg };
|
||||
@@ -122,7 +122,7 @@ fn void! NativeThread.create(NativeThread* thread, ThreadFn thread_fn, void* arg
|
||||
}
|
||||
}
|
||||
|
||||
fn void! NativeThread.detach(NativeThread thread)
|
||||
fn void! NativeThread.detach(thread)
|
||||
{
|
||||
if (!pthread_detach(thread)) return ThreadFault.DETACH_FAILED?;
|
||||
}
|
||||
@@ -137,19 +137,19 @@ fn NativeThread native_thread_current()
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
fn bool NativeThread.equals(NativeThread this, NativeThread other)
|
||||
fn bool NativeThread.equals(thread, NativeThread other)
|
||||
{
|
||||
return (bool)pthread_equal(this, other);
|
||||
return (bool)pthread_equal(thread, other);
|
||||
}
|
||||
|
||||
fn int! NativeThread.join(NativeThread thread)
|
||||
fn int! NativeThread.join(thread)
|
||||
{
|
||||
void *pres;
|
||||
if (pthread_join(thread, &pres)) return ThreadFault.JOIN_FAILED?;
|
||||
return (int)(iptr)pres;
|
||||
}
|
||||
|
||||
fn void NativeOnceFlag.call_once(NativeOnceFlag* flag, OnceFn func)
|
||||
fn void NativeOnceFlag.call_once(&flag, OnceFn func)
|
||||
{
|
||||
pthread_once(flag, func);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module std::thread::os @if(env::WIN32);
|
||||
import std::os::win32;
|
||||
|
||||
fn void! NativeMutex.init(NativeMutex* mtx, MutexType type)
|
||||
fn void! NativeMutex.init(&mtx, MutexType type)
|
||||
{
|
||||
mtx.already_locked = false;
|
||||
mtx.recursive = (bool)(type & thread::MUTEX_RECURSIVE);
|
||||
@@ -14,7 +14,7 @@ fn void! NativeMutex.init(NativeMutex* mtx, MutexType type)
|
||||
if (!(mtx.handle = win32::createMutex(null, false, null))) return ThreadFault.INIT_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.destroy(NativeMutex* mtx)
|
||||
fn void! NativeMutex.destroy(&mtx)
|
||||
{
|
||||
if (!mtx.timed)
|
||||
{
|
||||
@@ -24,7 +24,7 @@ fn void! NativeMutex.destroy(NativeMutex* mtx)
|
||||
if (!win32::closeHandle(mtx.handle)) return ThreadFault.DESTROY_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.lock(NativeMutex* mtx)
|
||||
fn void! NativeMutex.lock(&mtx)
|
||||
{
|
||||
if (!mtx.timed)
|
||||
{
|
||||
@@ -53,7 +53,7 @@ fn void! NativeMutex.lock(NativeMutex* mtx)
|
||||
/**
|
||||
* @require mtx.timed "Only available for timed locks"
|
||||
**/
|
||||
fn void! NativeMutex.lock_timeout(NativeMutex* mtx, uint ms)
|
||||
fn void! NativeMutex.lock_timeout(&mtx, uint ms)
|
||||
{
|
||||
switch (win32::waitForSingleObject(mtx.handle, ms))
|
||||
{
|
||||
@@ -72,7 +72,7 @@ fn void! NativeMutex.lock_timeout(NativeMutex* mtx, uint ms)
|
||||
}
|
||||
}
|
||||
|
||||
fn bool NativeMutex.try_lock(NativeMutex* mtx)
|
||||
fn bool NativeMutex.try_lock(&mtx)
|
||||
{
|
||||
bool success = mtx.timed
|
||||
? win32::waitForSingleObject(mtx.handle, 0) == win32::WAIT_OBJECT_0
|
||||
@@ -92,7 +92,7 @@ fn bool NativeMutex.try_lock(NativeMutex* mtx)
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void! NativeMutex.unlock(NativeMutex* mtx)
|
||||
fn void! NativeMutex.unlock(&mtx)
|
||||
{
|
||||
mtx.already_locked = false;
|
||||
if (!mtx.timed)
|
||||
@@ -106,7 +106,7 @@ fn void! NativeMutex.unlock(NativeMutex* mtx)
|
||||
const int CONDITION_EVENT_ONE = 0;
|
||||
const int CONDITION_EVENT_ALL = 1;
|
||||
|
||||
fn void! NativeConditionVariable.init(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.init(&cond)
|
||||
{
|
||||
cond.waiters_count = 0;
|
||||
win32::initializeCriticalSection(&cond.waiters_count_lock);
|
||||
@@ -125,14 +125,14 @@ fn void! NativeConditionVariable.init(NativeConditionVariable* cond)
|
||||
}
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.destroy(NativeConditionVariable* cond) @maydiscard
|
||||
fn void! NativeConditionVariable.destroy(&cond) @maydiscard
|
||||
{
|
||||
if (cond.event_one) win32::closeHandle(cond.event_one);
|
||||
if (cond.event_all) win32::closeHandle(cond.event_all);
|
||||
win32::deleteCriticalSection(&cond.waiters_count_lock);
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.signal(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.signal(&cond)
|
||||
{
|
||||
win32::enterCriticalSection(&cond.waiters_count_lock);
|
||||
bool have_waiters = cond.waiters_count > 0;
|
||||
@@ -140,7 +140,7 @@ fn void! NativeConditionVariable.signal(NativeConditionVariable* cond)
|
||||
if (have_waiters && !win32::setEvent(cond.event_one)) return ThreadFault.SIGNAL_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.broadcast(NativeConditionVariable* cond)
|
||||
fn void! NativeConditionVariable.broadcast(&cond)
|
||||
{
|
||||
win32::enterCriticalSection(&cond.waiters_count_lock);
|
||||
bool have_waiters = cond.waiters_count > 0;
|
||||
@@ -187,22 +187,22 @@ fn void! timedwait(NativeConditionVariable* cond, NativeMutex* mtx, uint timeout
|
||||
mtx.lock()!;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.wait(NativeConditionVariable* cond, NativeMutex* mtx) @inline
|
||||
fn void! NativeConditionVariable.wait(&cond, NativeMutex* mtx) @inline
|
||||
{
|
||||
return timedwait(cond, mtx, win32::INFINITE) @inline;
|
||||
}
|
||||
|
||||
fn void! NativeConditionVariable.wait_timeout(NativeConditionVariable* cond, NativeMutex* mtx, uint time) @inline
|
||||
fn void! NativeConditionVariable.wait_timeout(&cond, NativeMutex* mtx, uint time) @inline
|
||||
{
|
||||
return timedwait(cond, mtx, time) @inline;
|
||||
}
|
||||
|
||||
fn void! NativeThread.create(NativeThread* thread, ThreadFn func, void* args)
|
||||
fn void! NativeThread.create(&thread, ThreadFn func, void* args)
|
||||
{
|
||||
if (!(*thread = win32::createThread(null, 0, func, args, 0, null))) return ThreadFault.INIT_FAILED?;
|
||||
}
|
||||
|
||||
fn void! NativeThread.detach(NativeThread thread) @inline
|
||||
fn void! NativeThread.detach(thread) @inline
|
||||
{
|
||||
if (!win32::closeHandle(thread)) return ThreadFault.DETACH_FAILED?;
|
||||
}
|
||||
@@ -218,7 +218,7 @@ fn void native_thread_yield()
|
||||
win32::sleep(0);
|
||||
}
|
||||
|
||||
fn void NativeOnceFlag.call_once(NativeOnceFlag* flag, OnceFn func)
|
||||
fn void NativeOnceFlag.call_once(&flag, OnceFn func)
|
||||
{
|
||||
while (@volatile_load(flag.status) < 3)
|
||||
{
|
||||
@@ -246,7 +246,7 @@ fn void NativeOnceFlag.call_once(NativeOnceFlag* flag, OnceFn func)
|
||||
}
|
||||
}
|
||||
|
||||
fn void! NativeThread.join(NativeThread thread, int *res)
|
||||
fn void! NativeThread.join(thread, int *res)
|
||||
{
|
||||
if (win32::waitForSingleObject(thread, win32::INFINITE) == win32::WAIT_FAILED) return ThreadFault.JOIN_FAILED?;
|
||||
if (!win32::getExitCodeThread(thread, (uint*)res)) return ThreadFault.JOIN_FAILED?;
|
||||
@@ -258,9 +258,9 @@ fn NativeThread native_thread_current()
|
||||
return win32::getCurrentThread();
|
||||
}
|
||||
|
||||
fn bool NativeThread.equals(NativeThread this, NativeThread other)
|
||||
fn bool NativeThread.equals(thread, NativeThread other)
|
||||
{
|
||||
return win32::getThreadId(this) == win32::getThreadId(other);
|
||||
return win32::getThreadId(thread) == win32::getThreadId(other);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,33 +40,33 @@ fault ThreadFault
|
||||
INTERRUPTED,
|
||||
}
|
||||
|
||||
macro void! Mutex.init(Mutex* mutex, MutexType type) => NativeMutex.init((NativeMutex*)mutex, type);
|
||||
macro void! Mutex.destroy(Mutex* mutex) => NativeMutex.destroy((NativeMutex*)mutex);
|
||||
macro void! Mutex.lock(Mutex* mutex) => NativeMutex.lock((NativeMutex*)mutex);
|
||||
macro void! Mutex.lock_timeout(Mutex* mutex, ulong ms) => NativeMutex.lock((NativeMutex*)mutex, ms);
|
||||
macro bool Mutex.try_lock(Mutex* mutex) => NativeMutex.try_lock((NativeMutex*)mutex);
|
||||
macro bool Mutex.unlock(Mutex* mutex) => NativeMutex.unlock((NativeMutex*)mutex);
|
||||
macro void! Mutex.init(&mutex, MutexType type) => NativeMutex.init((NativeMutex*)mutex, type);
|
||||
macro void! Mutex.destroy(&mutex) => NativeMutex.destroy((NativeMutex*)mutex);
|
||||
macro void! Mutex.lock(&mutex) => NativeMutex.lock((NativeMutex*)mutex);
|
||||
macro void! Mutex.lock_timeout(&mutex, ulong ms) => NativeMutex.lock((NativeMutex*)mutex, ms);
|
||||
macro bool Mutex.try_lock(&mutex) => NativeMutex.try_lock((NativeMutex*)mutex);
|
||||
macro bool Mutex.unlock(&mutex) => NativeMutex.unlock((NativeMutex*)mutex);
|
||||
|
||||
macro void! ConditionVariable.init(ConditionVariable* cond) => NativeConditionVariable.init((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.destroy(ConditionVariable* cond) => NativeConditionVariable.destroy((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.signal(ConditionVariable* cond) => NativeConditionVariable.signal((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.broadcast(ConditionVariable* cond) => NativeConditionVariable.broadcast((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.wait(ConditionVariable* cond, Mutex* mutex)
|
||||
macro void! ConditionVariable.init(&cond) => NativeConditionVariable.init((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.destroy(&cond) => NativeConditionVariable.destroy((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.signal(&cond) => NativeConditionVariable.signal((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.broadcast(&cond) => NativeConditionVariable.broadcast((NativeConditionVariable*)cond);
|
||||
macro void! ConditionVariable.wait(&cond, Mutex* mutex)
|
||||
{
|
||||
return NativeConditionVariable.wait((NativeConditionVariable*)cond, (NativeMutex*)mutex);
|
||||
}
|
||||
macro void! ConditionVariable.wait_timeout(ConditionVariable* cond, Mutex* mutex, ulong timeout)
|
||||
macro void! ConditionVariable.wait_timeout(&cond, Mutex* mutex, ulong timeout)
|
||||
{
|
||||
return NativeConditionVariable.wait_timeout((NativeConditionVariable*)cond, (NativeMutex*)mutex, timeout);
|
||||
}
|
||||
|
||||
|
||||
macro void! Thread.create(Thread* thread, ThreadFn thread_fn, void* arg) => NativeThread.create((NativeThread*)thread, thread_fn, arg);
|
||||
macro void! Thread.detach(Thread thread) => NativeThread.detach((NativeThread)thread);
|
||||
macro int! Thread.join(Thread thread) => NativeThread.join((NativeThread)thread);
|
||||
macro bool Thread.equals(Thread thread, Thread other) => NativeThread.equals((NativeThread)this, (NativeThread)other);
|
||||
macro void! Thread.create(&thread, ThreadFn thread_fn, void* arg) => NativeThread.create((NativeThread*)thread, thread_fn, arg);
|
||||
macro void! Thread.detach(thread) => NativeThread.detach((NativeThread)thread);
|
||||
macro int! Thread.join(thread) => NativeThread.join((NativeThread)thread);
|
||||
macro bool Thread.equals(thread, Thread other) => NativeThread.equals((NativeThread)this, (NativeThread)other);
|
||||
|
||||
macro void OnceFlag.call_once(OnceFlag* flag, OnceFn func) => NativeOnceFlag.call_once((NativeOnceFlag*)flag, func);
|
||||
macro void OnceFlag.call_once(&flag, OnceFn func) => NativeOnceFlag.call_once((NativeOnceFlag*)flag, func);
|
||||
|
||||
macro void yield() => os::native_thread_yield();
|
||||
macro Thread current() => os::native_thread_current();
|
||||
|
||||
@@ -68,20 +68,20 @@ fn Time now()
|
||||
$endif
|
||||
}
|
||||
|
||||
fn Time Time.add_seconds(Time time, long seconds) => time + (Time)(seconds * (long)MICROSECONDS_PER_SECOND);
|
||||
fn Time Time.add_minutes(Time time, long minutes) => time + (Time)(minutes * (long)MICROSECONDS_PER_MINUTE);
|
||||
fn Time Time.add_hours(Time time, long hours) => time + (Time)(hours * (long)MICROSECONDS_PER_HOUR);
|
||||
fn Time Time.add_days(Time time, long days) => time + (Time)(days * (long)MICROSECONDS_PER_DAY);
|
||||
fn Time Time.add_weeks(Time time, long weeks) => time + (Time)(weeks * (long)MICROSECONDS_PER_WEEK);
|
||||
fn double Time.to_seconds(Time time) => (long)time / (double)MICROSECONDS_PER_SECOND;
|
||||
fn TimeDuration Time.diff_us(Time time, Time other) => (TimeDuration)(time - other);
|
||||
fn double Time.diff_sec(Time time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_SECOND;
|
||||
fn double Time.diff_min(Time time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_MINUTE;
|
||||
fn double Time.diff_hour(Time time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_HOUR;
|
||||
fn double Time.diff_days(Time time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_DAY;
|
||||
fn double Time.diff_weeks(Time time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_WEEK;
|
||||
fn Time Time.add_seconds(time, long seconds) => time + (Time)(seconds * (long)MICROSECONDS_PER_SECOND);
|
||||
fn Time Time.add_minutes(time, long minutes) => time + (Time)(minutes * (long)MICROSECONDS_PER_MINUTE);
|
||||
fn Time Time.add_hours(time, long hours) => time + (Time)(hours * (long)MICROSECONDS_PER_HOUR);
|
||||
fn Time Time.add_days(time, long days) => time + (Time)(days * (long)MICROSECONDS_PER_DAY);
|
||||
fn Time Time.add_weeks(time, long weeks) => time + (Time)(weeks * (long)MICROSECONDS_PER_WEEK);
|
||||
fn double Time.to_seconds(time) => (long)time / (double)MICROSECONDS_PER_SECOND;
|
||||
fn TimeDuration Time.diff_us(time, Time other) => (TimeDuration)(time - other);
|
||||
fn double Time.diff_sec(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_SECOND;
|
||||
fn double Time.diff_min(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_MINUTE;
|
||||
fn double Time.diff_hour(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_HOUR;
|
||||
fn double Time.diff_days(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_DAY;
|
||||
fn double Time.diff_weeks(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_WEEK;
|
||||
|
||||
fn double NanoDuration.to_sec(NanoDuration nd) => (double)nd / 1_000_000_000.0;
|
||||
fn long NanoDuration.to_ms(NanoDuration nd) => (long)nd / 1_000_000;
|
||||
fn TimeDuration NanoDuration.to_duration(NanoDuration nd) => (TimeDuration)nd / 1_000;
|
||||
fn NanoDuration TimeDuration.to_nano(TimeDuration td) => (NanoDuration)td * 1_000;
|
||||
fn double NanoDuration.to_sec(nd) => (double)nd / 1_000_000_000.0;
|
||||
fn long NanoDuration.to_ms(nd) => (long)nd / 1_000_000;
|
||||
fn TimeDuration NanoDuration.to_duration(nd) => (TimeDuration)nd / 1_000;
|
||||
fn NanoDuration TimeDuration.to_nano(td) => (NanoDuration)td * 1_000;
|
||||
20
test/unit/stdlib/io/limitreader.c3
Normal file
20
test/unit/stdlib/io/limitreader.c3
Normal file
@@ -0,0 +1,20 @@
|
||||
module std::io @test;
|
||||
|
||||
|
||||
fn void! limitreader()
|
||||
{
|
||||
const DATA = "Hello World!";
|
||||
ByteReader src;
|
||||
src.init(DATA);
|
||||
const LIMIT = 5;
|
||||
LimitReader lmr;
|
||||
lmr.init(src.as_stream(), LIMIT);
|
||||
|
||||
char[DATA.len] bytes;
|
||||
usz n = lmr.read(bytes[..])!;
|
||||
|
||||
assert(n == LIMIT, "got %d; want %d", n, LIMIT);
|
||||
String got = (String)bytes[:n];
|
||||
String want = DATA[:LIMIT];
|
||||
assert(got == want, "got %d; want %d", got, want);
|
||||
}
|
||||
Reference in New Issue
Block a user