import time struct St { mut: a int } fn (shared x St) f(shared z St) { for _ in 0 .. reads_per_thread { rlock x { // other instances may read at the same time time.sleep(time.millisecond) assert x.a == 7 || x.a == 5 } } lock z { z.a-- } } fn g() shared St { shared x := St{ a: 12 } return x } fn h() ?shared St { return error('no value') } fn k() { shared x := g() shared y := h() or { shared f := St{} f } shared z := h() ? shared p := v v := rlock z { z.a } lock y, z; rlock x, p { z.a = x.a + y.a } println(v) } const ( reads_per_thread = 30 read_threads = 10 writes = 5 ) fn test_shared_lock() { // object with separate read/write lock shared x := &St{ a: 5 } shared z := &St{ a: read_threads } for _ in 0 .. read_threads { go x.f(shared z) } for i in 0 .. writes { lock x { // wait for ongoing reads to finish, don't start new ones x.a = 17 // this value should never be read time.sleep(50 * time.millisecond) x.a = if (i & 1) == 0 { 7 } else { 5 } } // now new reads are possible again time.sleep(20 * time.millisecond) } // wait until all read threads are finished for finished := false; true; { mut rr := 0 rlock z { rr = z.a finished = z.a == 0 } if finished { break } time.sleep(100 * time.millisecond) } }