From fd5336c56ef554aee986cadc6fd347afe77ebd11 Mon Sep 17 00:00:00 2001 From: Pierre Curto Date: Mon, 17 Jul 2023 20:22:29 +0200 Subject: [PATCH] lib/std/io/stream: add LimitReader (#858) * lib/std/io/stream: add LimitReader Signed-off-by: Pierre Curto * lib/std: more method conversions to use new receiver notation Signed-off-by: Pierre Curto --------- Signed-off-by: Pierre Curto --- lib/std/collections/map.c3 | 62 +++++++------- lib/std/io/stream/limitreader.c3 | 36 +++++++++ lib/std/math/math.random.c3 | 18 ++--- lib/std/math/math_quaternion.c3 | 6 +- lib/std/math/random/math.lcg.c3 | 16 ++-- lib/std/math/random/math.mcg.c3 | 16 ++-- lib/std/math/random/math.msws.c3 | 20 ++--- lib/std/math/random/math.pcg.c3 | 16 ++-- lib/std/math/random/math.sfc.c3 | 20 ++--- lib/std/math/random/math.simple_random.c3 | 8 +- lib/std/os/subprocess.c3 | 98 +++++++++++------------ lib/std/threads/os/thread_posix.c3 | 38 ++++----- lib/std/threads/os/thread_win32.c3 | 36 ++++----- lib/std/threads/thread.c3 | 34 ++++---- lib/std/time/time.c3 | 32 ++++---- test/unit/stdlib/io/limitreader.c3 | 20 +++++ 16 files changed, 266 insertions(+), 210 deletions(-) create mode 100644 lib/std/io/stream/limitreader.c3 create mode 100644 test/unit/stdlib/io/limitreader.c3 diff --git a/lib/std/collections/map.c3 b/lib/std/collections/map.c3 index f797f5471..e504c4621 100644 --- a/lib/std/collections/map.c3 +++ b/lib/std/collections/map.c3 @@ -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); diff --git a/lib/std/io/stream/limitreader.c3 b/lib/std/io/stream/limitreader.c3 new file mode 100644 index 000000000..d4209317e --- /dev/null +++ b/lib/std/io/stream/limitreader.c3 @@ -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(), +}; \ No newline at end of file diff --git a/lib/std/math/math.random.c3 b/lib/std/math/math.random.c3 index 9f6982bec..e610bbc6e 100644 --- a/lib/std/math/math.random.c3 +++ b/lib/std/math/math.random.c3 @@ -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; } diff --git a/lib/std/math/math_quaternion.c3 b/lib/std/math/math_quaternion.c3 index 67550e845..2e3d0735c 100644 --- a/lib/std/math/math_quaternion.c3 +++ b/lib/std/math/math_quaternion.c3 @@ -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, diff --git a/lib/std/math/random/math.lcg.c3 b/lib/std/math/random/math.lcg.c3 index a4e50dc2c..bab5a5d34 100644 --- a/lib/std/math/random/math.lcg.c3 +++ b/lib/std/math/random/math.lcg.c3 @@ -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); diff --git a/lib/std/math/random/math.mcg.c3 b/lib/std/math/random/math.mcg.c3 index 98e944e65..82fc271c4 100644 --- a/lib/std/math/random/math.mcg.c3 +++ b/lib/std/math/random/math.mcg.c3 @@ -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); diff --git a/lib/std/math/random/math.msws.c3 b/lib/std/math/random/math.msws.c3 index 93580b2eb..7eff36890 100644 --- a/lib/std/math/random/math.msws.c3 +++ b/lib/std/math/random/math.msws.c3 @@ -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; diff --git a/lib/std/math/random/math.pcg.c3 b/lib/std/math/random/math.pcg.c3 index 1b33d8ad7..dabc37a9e 100644 --- a/lib/std/math/random/math.pcg.c3 +++ b/lib/std/math/random/math.pcg.c3 @@ -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; diff --git a/lib/std/math/random/math.sfc.c3 b/lib/std/math/random/math.sfc.c3 index f576e818a..f85333b38 100644 --- a/lib/std/math/random/math.sfc.c3 +++ b/lib/std/math/random/math.sfc.c3 @@ -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]; diff --git a/lib/std/math/random/math.simple_random.c3 b/lib/std/math/random/math.simple_random.c3 index 1691b6192..9c351dbd3 100644 --- a/lib/std/math/random/math.simple_random.c3 +++ b/lib/std/math/random/math.simple_random.c3 @@ -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) diff --git a/lib/std/os/subprocess.c3 b/lib/std/os/subprocess.c3 index 177017a10..b86f6cd01 100644 --- a/lib/std/os/subprocess.c3 +++ b/lib/std/os/subprocess.c3 @@ -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 } \ No newline at end of file diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index 0e57ecc0a..c11348d04 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -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); } diff --git a/lib/std/threads/os/thread_win32.c3 b/lib/std/threads/os/thread_win32.c3 index be763f181..e256dd986 100644 --- a/lib/std/threads/os/thread_win32.c3 +++ b/lib/std/threads/os/thread_win32.c3 @@ -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); } /** diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index b120a85e8..ec38dabf7 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -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(); diff --git a/lib/std/time/time.c3 b/lib/std/time/time.c3 index e308e5f27..9c540f680 100644 --- a/lib/std/time/time.c3 +++ b/lib/std/time/time.c3 @@ -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; \ No newline at end of file +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; \ No newline at end of file diff --git a/test/unit/stdlib/io/limitreader.c3 b/test/unit/stdlib/io/limitreader.c3 new file mode 100644 index 000000000..1d6f13578 --- /dev/null +++ b/test/unit/stdlib/io/limitreader.c3 @@ -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); +} \ No newline at end of file