Skip to content

Commit 0c713f6

Browse files
authored
sync.once: add Once (#12722)
1 parent 105d7fc commit 0c713f6

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

cmd/tools/vtest-self.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ const (
115115
'vlib/vweb/request_test.v',
116116
'vlib/net/http/request_test.v',
117117
'vlib/vweb/route_test.v',
118+
'vlib/sync/once_test.v',
118119
]
119120
skip_on_non_windows = [
120121
'do_not_remove',

vlib/sync/once.v

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module sync
2+
3+
import sync.atomic2
4+
5+
pub struct Once {
6+
mut:
7+
m RwMutex
8+
pub:
9+
count u64
10+
}
11+
12+
// new_once return a new Once struct.
13+
pub fn new_once() &Once {
14+
mut once := &Once{}
15+
once.m.init()
16+
return once
17+
}
18+
19+
// do execute the function only once.
20+
pub fn (mut o Once) do(f fn ()) {
21+
if atomic2.load_u64(&o.count) < 1 {
22+
o.do_slow(f)
23+
}
24+
}
25+
26+
fn (mut o Once) do_slow(f fn ()) {
27+
o.m.@lock()
28+
if o.count < 1 {
29+
atomic2.store_u64(&o.count, 1)
30+
f()
31+
}
32+
o.m.unlock()
33+
}

vlib/sync/once_test.v

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import sync
2+
3+
struct One {
4+
pub mut:
5+
i int
6+
}
7+
8+
fn (mut o One) add(i int) {
9+
o.i = o.i + i
10+
}
11+
12+
fn run(mut once sync.Once, mut o One, c chan bool) {
13+
once.do(fn [mut o] () {
14+
o.add(5)
15+
})
16+
c <- true
17+
}
18+
19+
fn test_once() {
20+
mut o := &One{}
21+
mut once := sync.new_once()
22+
c := chan bool{}
23+
n := 10
24+
25+
// It is executed 10 times, but only once actually.
26+
for i := 0; i < n; i++ {
27+
go run(mut once, mut o, c)
28+
}
29+
for i := 0; i < n; i++ {
30+
<-c
31+
}
32+
assert o.i == 5
33+
}

0 commit comments

Comments
 (0)