-
Notifications
You must be signed in to change notification settings - Fork 8
/
waitgroup.go
102 lines (82 loc) · 1.82 KB
/
waitgroup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright Suneido Software Corp. All rights reserved.
// Governed by the MIT license found in the LICENSE file.
package builtin
import (
"sync"
"time"
. "github.com/apmckinlay/gsuneido/core"
)
type suWaitGroup struct {
ValueBase[suWaitGroup]
wg sync.WaitGroup
}
var _ = builtin(WaitGroup, "()")
func WaitGroup() Value {
return &suWaitGroup{}
}
var suWaitGroupMethods = methods()
var _ = method(wg_Add, "()")
func wg_Add(this Value) Value {
wg := this.(*suWaitGroup)
wg.wg.Add(1)
return nil
}
var _ = method(wg_Done, "()")
func wg_Done(this Value) Value {
wg := this.(*suWaitGroup)
wg.wg.Done()
return nil
}
var _ = method(wg_Thread, "(block, name = false)")
func wg_Thread(th *Thread, this Value, args []Value) Value {
wg := this.(*suWaitGroup)
wg.wg.Add(1)
fn := args[0]
fn.SetConcurrent()
t2 := NewThread(th)
thread_Name(t2, args[1:])
threads.add(t2)
go func() {
defer func() {
wg.wg.Done()
t2.Close()
threads.remove(t2.Num)
if e := recover(); e != nil {
LogUncaught(t2, "Thread", e)
}
}()
t2.Call(fn)
}()
return nil
}
var _ = method(wg_Wait, "(secs = 5)")
func wg_Wait(th *Thread, this Value, args []Value) Value {
timeout := IfInt(args[0])
if timeout <= 0 {
panic("WaitGroup.Wait: timeout must be > 0")
}
wg := this.(*suWaitGroup)
c := make(chan struct{})
go func() {
defer close(c)
wg.wg.Wait()
}()
select {
case <-c:
return True // completed normally
case <-time.After(time.Duration(timeout) * time.Second):
th.ReturnThrow = true
return SuStr("WaitGroup: timeout")
}
}
// Value implementation
var _ Value = (*suWaitGroup)(nil)
func (wg *suWaitGroup) Equal(other any) bool {
return wg == other
}
func (*suWaitGroup) Lookup(_ *Thread, method string) Callable {
return suWaitGroupMethods[method]
}
func (*suWaitGroup) SetConcurrent() {
// ok for concurrent use
}