From 7d1dec5b44a7dac8e05d86603b2ca89f967b8cc9 Mon Sep 17 00:00:00 2001 From: Taillook Date: Mon, 6 Dec 2021 02:44:25 +0900 Subject: [PATCH] sync: add sync.ManyTimes (#12729) --- cmd/tools/vtest-self.v | 1 + vlib/sync/many_times.v | 36 +++++++++++++++++++++++++++ vlib/sync/many_times_test.v | 49 +++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 vlib/sync/many_times.v create mode 100644 vlib/sync/many_times_test.v diff --git a/cmd/tools/vtest-self.v b/cmd/tools/vtest-self.v index 7162ea53d..859029ef3 100644 --- a/cmd/tools/vtest-self.v +++ b/cmd/tools/vtest-self.v @@ -115,6 +115,7 @@ const ( 'vlib/vweb/request_test.v', 'vlib/net/http/request_test.v', 'vlib/vweb/route_test.v', + 'vlib/sync/many_times_test.v', 'vlib/sync/once_test.v', ] skip_on_non_windows = [ diff --git a/vlib/sync/many_times.v b/vlib/sync/many_times.v new file mode 100644 index 000000000..286defc34 --- /dev/null +++ b/vlib/sync/many_times.v @@ -0,0 +1,36 @@ +module sync + +import sync.atomic2 + +pub struct ManyTimes { +mut: + m RwMutex +pub: + times u64 = 1 + count u64 +} + +// new_many_times return a new ManyTimes struct. +pub fn new_many_times(times u64) &ManyTimes { + mut many_times := &ManyTimes{ + times: times + } + many_times.m.init() + return many_times +} + +// do execute the function only setting times. +pub fn (mut m ManyTimes) do(f fn ()) { + if atomic2.load_u64(&m.count) < m.times { + m.do_slow(f) + } +} + +fn (mut m ManyTimes) do_slow(f fn ()) { + m.m.@lock() + if m.count < m.times { + atomic2.store_u64(&m.count, m.count + 1) + f() + } + m.m.unlock() +} diff --git a/vlib/sync/many_times_test.v b/vlib/sync/many_times_test.v new file mode 100644 index 000000000..e2ddca3ae --- /dev/null +++ b/vlib/sync/many_times_test.v @@ -0,0 +1,49 @@ +import sync + +struct Counter { +pub mut: + i int +} + +fn (mut c Counter) add(i int) { + c.i = c.i + i +} + +fn run(mut m sync.ManyTimes, mut co Counter, c chan bool) { + m.do(fn [mut co] () { + co.add(5) + }) + c <- true +} + +fn test_many_times_once() { + mut co := &Counter{} + mut m := sync.new_many_times(1) + c := chan bool{} + n := 10 + + // It is executed 10 times, but only once actually. + for i := 0; i < n; i++ { + go run(mut m, mut co, c) + } + for i := 0; i < n; i++ { + <-c + } + assert co.i == 5 +} + +fn test_many_times_fifth() { + mut co := &Counter{} + mut m := sync.new_many_times(5) + c := chan bool{} + n := 10 + + // It is executed 10 times, but only 5 times actually. + for i := 0; i < n; i++ { + go run(mut m, mut co, c) + } + for i := 0; i < n; i++ { + <-c + } + assert co.i == 25 +} -- 2.30.2