Files
c3c/test/unit/stdlib/threads/mutex.c3
Alex Veden 5046608d1f added io::stdout().flush() - to force printing test name before possible deadlock
mem::scoped() and long jump resilience fixed #1963
fixed --test-nosort argument + extra test for teardown_fn memory leak
Some renaming. Simplify robust test allocator handling. Pop temp allocators in test runner.
`Thread` no longer allocates memory on posix.
Update unprintable struct output.
Correctly give an error if a character literal contains a line break.
2025-02-20 01:15:48 +01:00

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