mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
- Remove `[?]` syntax. - Change `int!` to `int?` syntax. - New `fault` declarations. - Enum associated values can reference the calling enum.
148 lines
2.3 KiB
Plaintext
148 lines
2.3 KiB
Plaintext
module thread_test;
|
|
|
|
import std::thread;
|
|
import std::os;
|
|
|
|
const TEST_MAGNITUDE = 10;
|
|
|
|
fn void lock_control_test() @test
|
|
{
|
|
Mutex m;
|
|
m.init()!!;
|
|
m.lock()!!;
|
|
assert(@catch(m.lock()));
|
|
}
|
|
|
|
fn void unlock_control_test() @test
|
|
{
|
|
Mutex m;
|
|
m.init()!!;
|
|
assert(@catch(m.unlock()));
|
|
}
|
|
|
|
fn void lock_with_double_unlock_test() @test
|
|
{
|
|
Mutex m;
|
|
m.init()!!;
|
|
|
|
m.lock()!!;
|
|
m.unlock()!!;
|
|
assert(@catch(m.unlock()));
|
|
}
|
|
|
|
fn void? own_mutex(Mutex* m)
|
|
{
|
|
m.lock()!;
|
|
m.unlock()!;
|
|
}
|
|
|
|
fn void ensure_owner_checks() @test
|
|
{
|
|
Mutex m;
|
|
m.init()!!;
|
|
|
|
Thread[3 * TEST_MAGNITUDE] threads;
|
|
|
|
foreach(&t : threads)
|
|
{
|
|
t.create((ThreadFn)&own_mutex, &m)!!;
|
|
}
|
|
|
|
foreach(&t : threads)
|
|
{
|
|
t.join()!!;
|
|
}
|
|
|
|
own_mutex(&m)!!;
|
|
}
|
|
|
|
struct ArgsWrapper1
|
|
{
|
|
Mutex* m;
|
|
ulong* v;
|
|
}
|
|
|
|
fn void shared_mutex_increment(ArgsWrapper1* args)
|
|
{
|
|
args.m.lock()!!;
|
|
args.v++;
|
|
args.m.unlock()!!;
|
|
}
|
|
|
|
fn void shared_mutex_decrement(ArgsWrapper1* args)
|
|
{
|
|
args.m.lock()!!;
|
|
args.v--;
|
|
args.m.unlock()!!;
|
|
}
|
|
|
|
fn void shared_mutex() @test
|
|
{
|
|
Mutex m;
|
|
m.init()!!;
|
|
m.lock()!!;
|
|
|
|
ulong v;
|
|
|
|
ArgsWrapper1 args =
|
|
{
|
|
.m = &m,
|
|
.v = &v
|
|
};
|
|
|
|
// An even number of threads must be chosen
|
|
Thread[6 * TEST_MAGNITUDE] threads;
|
|
for (int i = 0; i < threads.len / 2; i++)
|
|
{
|
|
(&threads[i]).create((ThreadFn)&shared_mutex_increment, &args)!!;
|
|
}
|
|
for (int i = (threads.len / 2); i < threads.len; i++)
|
|
{
|
|
(&threads[i]).create((ThreadFn)&shared_mutex_decrement, &args)!!;
|
|
}
|
|
|
|
m.unlock()!!;
|
|
foreach(&t : threads)
|
|
{
|
|
t.join()!!;
|
|
}
|
|
assert(v == 0);
|
|
}
|
|
|
|
// Recursive mutex
|
|
|
|
fn void acquire_recursively(RecursiveMutex* m)
|
|
{
|
|
// TODO: The recursive mutex functions can not directly be called via pointer
|
|
|
|
for (usz i = 0; i < 5 * TEST_MAGNITUDE; i++)
|
|
{
|
|
((Mutex*)m).lock()!!;
|
|
}
|
|
|
|
for (usz i = 0; i < 5 * TEST_MAGNITUDE; i++)
|
|
{
|
|
((Mutex*)m).unlock()!!;
|
|
}
|
|
}
|
|
|
|
fn void test_recursive_mutex() @test
|
|
{
|
|
RecursiveMutex m;
|
|
m.init()!!;
|
|
defer m.destroy()!!;
|
|
|
|
Thread[3 * TEST_MAGNITUDE] threads;
|
|
foreach(&t : threads)
|
|
{
|
|
t.create((ThreadFn)&acquire_recursively, &m)!!;
|
|
}
|
|
|
|
foreach(&t : threads)
|
|
{
|
|
t.join()!!;
|
|
}
|
|
|
|
return acquire_recursively(&m);
|
|
}
|