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:
Pierre Curto
2023-07-17 20:22:29 +02:00
committed by GitHub
parent 209d994336
commit fd5336c56e
16 changed files with 266 additions and 210 deletions

View File

@@ -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);

View 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(),
};

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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];

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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);
}
/**

View File

@@ -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();

View File

@@ -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;

View 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);
}