mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
[FEAT] add golang like channel (#1843)
* [feat] add golang like channels * Updated new_init/init. Some fixes for init. --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
337
test/unit/stdlib/threads/channel.c3
Normal file
337
test/unit/stdlib/threads/channel.c3
Normal file
@@ -0,0 +1,337 @@
|
||||
module thread_test;
|
||||
|
||||
import std::thread::channel;
|
||||
import std::thread;
|
||||
import std::time;
|
||||
import std::io;
|
||||
|
||||
fn void init_destroy_buffered() @test
|
||||
{
|
||||
for (usz i = 0; i < 20; i++)
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
}
|
||||
}
|
||||
|
||||
fn void init_destroy_unbuffered() @test
|
||||
{
|
||||
for (usz i = 0; i < 20; i++)
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
}
|
||||
}
|
||||
|
||||
fn void push_to_buffered_channel_no_lock() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.push(1)!!;
|
||||
}
|
||||
|
||||
fn void push_pop_buffered_no_locks() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.push(123)!!;
|
||||
int got = c.pop()!!;
|
||||
assert(got == 123);
|
||||
}
|
||||
|
||||
fn void push_pop_unbuffered_with_locks() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
UnbufferedChannel(<int>) c = (UnbufferedChannel(<int>))arg;
|
||||
c.push(123)!!;
|
||||
c.push(321)!!;
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
int got = c.pop()!!;
|
||||
assert(got == 123);
|
||||
got = c.pop()!!;
|
||||
assert(got == 321);
|
||||
}
|
||||
|
||||
fn void sending_to_closed_unbuffered_chan_is_forbidden() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.close()!!;
|
||||
|
||||
if (catch err = c.push(123))
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void sending_to_closed_buffered_chan_is_forbidden() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.close()!!;
|
||||
|
||||
if (catch err = c.push(123))
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void reading_from_empty_closed_unbuffered_chan_is_forbidden() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.close()!!;
|
||||
|
||||
if (catch err = c.pop())
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void reading_from_empty_closed_buffered_chan_is_forbidden() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.close()!!;
|
||||
|
||||
if (catch err = c.pop())
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void reading_from_non_empty_closed_buffered_chan_is_ok() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(3)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.push(1)!!;
|
||||
c.push(2)!!;
|
||||
c.push(3)!!;
|
||||
|
||||
c.close()!!;
|
||||
|
||||
int got = c.pop()!!;
|
||||
assert(got == 1);
|
||||
got = c.pop()!!;
|
||||
assert(got == 2);
|
||||
got = c.pop()!!;
|
||||
assert(got == 3);
|
||||
|
||||
int! got_err = c.pop();
|
||||
if (catch err = got_err)
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void reading_from_empty_buffered_chan_aborted_by_close() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(3)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
BufferedChannel(<int>) c = (BufferedChannel(<int>))arg;
|
||||
c.close()!!;
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
int! res = c.pop();
|
||||
if (catch err = res)
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void reading_from_unbuffered_chan_aborted_by_close() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
UnbufferedChannel(<int>) c = (UnbufferedChannel(<int>))arg;
|
||||
c.close()!!;
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
int! res = c.pop();
|
||||
if (catch err = res)
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void sending_to_full_buffered_chan_aborted_by_close() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(1)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
c.push(1)!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
BufferedChannel(<int>) c = (BufferedChannel(<int>))arg;
|
||||
c.close()!!;
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
anyfault err = @catch(c.push(1));
|
||||
if (err)
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void sending_to_unbuffered_chan_aborted_by_close() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
UnbufferedChannel(<int>) c = (UnbufferedChannel(<int>))arg;
|
||||
c.close()!!;
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
anyfault err = @catch(c.push(1));
|
||||
if (err)
|
||||
{
|
||||
assert(err == ThreadFault.CHANNEL_CLOSED);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fn void multiple_actions_unbuffered() @test
|
||||
{
|
||||
UnbufferedChannel(<int>) c;
|
||||
c.new_init()!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
UnbufferedChannel(<int>) c = (UnbufferedChannel(<int>))arg;
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
c.push(i)!!;
|
||||
}
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
int sum;
|
||||
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
int! res = c.pop();
|
||||
if (catch err = res)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
sum += res;
|
||||
}
|
||||
|
||||
assert(sum == 5050);
|
||||
}
|
||||
|
||||
fn void multiple_actions_buffered() @test
|
||||
{
|
||||
BufferedChannel(<int>) c;
|
||||
c.new_init(10)!!;
|
||||
defer c.destroy()!!;
|
||||
|
||||
Thread thread;
|
||||
defer thread.join()!!;
|
||||
|
||||
thread.create(fn int(void* arg)
|
||||
{
|
||||
BufferedChannel(<int>) c = (BufferedChannel(<int>))arg;
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
c.push(i)!!;
|
||||
}
|
||||
return 0;
|
||||
}, (void*)c)!!;
|
||||
|
||||
int sum;
|
||||
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
int! res = c.pop();
|
||||
if (catch err = res)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
sum += res;
|
||||
}
|
||||
|
||||
assert(sum == 5050);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user