-
Notifications
You must be signed in to change notification settings - Fork 39
/
handler.go
66 lines (56 loc) · 1.51 KB
/
handler.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
package gtkcord
import (
"reflect"
"sync"
"github.com/diamondburned/arikawa/v3/utils/handler"
"github.com/diamondburned/gotk4/pkg/core/glib"
)
// MainThreadHandler wraps a [handler.Handler] to run all events on the main
// thread.
type MainThreadHandler struct {
h *handler.Handler
}
// NewMainThreadHandler creates a new MainThreadHandler.
func NewMainThreadHandler(h *handler.Handler) *MainThreadHandler {
m := &MainThreadHandler{
h: handler.New(),
}
p := &sync.Pool{
New: func() any { return make([]handler.Caller, 0, 10) },
}
h.AddSyncHandler(func(ev any) {
callers := p.Get().([]handler.Caller)
all := m.h.AllCallersForType(reflect.TypeOf(ev))
all(func(c handler.Caller) bool {
callers = append(callers, c)
return true
})
if len(callers) == 0 {
p.Put(callers)
return
}
v := reflect.ValueOf(ev)
glib.IdleAddPriority(glib.PriorityHighIdle, func() {
for _, c := range callers {
c.Call(v)
}
// Return the callers to the pool.
for i := range callers {
callers[i] = nil // avoid memory leaks
}
p.Put(callers[:0])
})
})
return m
}
// AddHandler adds a handler to the handler.Handler.
// The given handler will be called on the main thread.
// The returned function will remove the handler.
func (m *MainThreadHandler) AddHandler(handler any) func() {
return m.h.AddSyncHandler(handler)
}
// AddSyncHandler is the same as [AddHandler].
// It exists for compatibility.
func (m *MainThreadHandler) AddSyncHandler(handler any) func() {
return m.AddHandler(handler)
}