v/vlib/v/tests/shared_unordered_mixed_test.v

90 lines
1.5 KiB
V

// integer values from -2^191 .. 2^191-1
struct Large {
mut:
l u64
m u64
h u64
}
fn (a Large) clone() Large {
r := Large{
l: a.l
m: a.m
h: a.h
}
return r
}
fn (mut a Large) add(b Large) {
oldl := a.l
a.l += b.l
oldm := a.m
if a.l < oldl {
a.m++
}
a.m += b.m
if a.m < oldm || (a.l < oldl && a.m <= oldm) {
a.h++
}
a.h += b.h
}
fn doub_large(shared a Large, shared b Large, shared c Large, shared d Large, shared e Large) {
for _ in 0 .. 50 {
lock a, b; rlock c, d, e {
// double the sum by adding all objects to a or b
old_a := a.clone()
a.add(b)
b.add(old_a)
a.add(c)
b.add(d)
a.add(e)
}
}
}
fn test_mixed_order_lock_rlock() {
// initialze objects so that their sum = 1
shared a := Large{
l: 4
}
shared b := Large{
l: u64(-7)
m: u64(-1)
h: u64(-1)
}
shared c := Large{
l: 17
}
shared d := Large{
l: u64(-11)
m: u64(-1)
h: u64(-1)
}
shared e := Large{
l: u64(-2)
m: u64(-1)
h: u64(-1)
}
// spawn 3 threads for doubling with different orders of objects
t1 := go doub_large(shared a, shared b, shared c, shared d, shared e)
t2 := go doub_large(shared e, shared b, shared a, shared c, shared d)
t3 := go doub_large(shared b, shared a, shared e, shared d, shared c)
t1.wait()
t2.wait()
t3.wait()
// calculate the sum after 3*50 doublings
mut sum := Large{}
rlock a, b, c, d, e {
sum.add(a)
sum.add(b)
sum.add(c)
sum.add(d)
sum.add(e)
}
// the sum should be 2^150
assert sum.l == 0
assert sum.m == 0
assert sum.h == 4194304
}