Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
diamondburned
GitHub Repository: diamondburned/gtkcord4
Path: blob/main/internal/gtkcord/handler.go
365 views
1
package gtkcord
2
3
import (
4
"reflect"
5
"sync"
6
7
"github.com/diamondburned/arikawa/v3/utils/handler"
8
"github.com/diamondburned/gotk4/pkg/core/glib"
9
)
10
11
// MainThreadHandler wraps a [handler.Handler] to run all events on the main
12
// thread.
13
type MainThreadHandler struct {
14
h *handler.Handler
15
}
16
17
// NewMainThreadHandler creates a new MainThreadHandler.
18
func NewMainThreadHandler(h *handler.Handler) *MainThreadHandler {
19
m := &MainThreadHandler{
20
h: handler.New(),
21
}
22
p := &sync.Pool{
23
New: func() any { return make([]handler.Caller, 0, 10) },
24
}
25
h.AddSyncHandler(func(ev any) {
26
callers := p.Get().([]handler.Caller)
27
28
all := m.h.AllCallersForType(reflect.TypeOf(ev))
29
all(func(c handler.Caller) bool {
30
callers = append(callers, c)
31
return true
32
})
33
34
if len(callers) == 0 {
35
p.Put(callers)
36
return
37
}
38
39
v := reflect.ValueOf(ev)
40
glib.IdleAddPriority(glib.PriorityHighIdle, func() {
41
for _, c := range callers {
42
c.Call(v)
43
}
44
45
// Return the callers to the pool.
46
for i := range callers {
47
callers[i] = nil // avoid memory leaks
48
}
49
p.Put(callers[:0])
50
})
51
})
52
return m
53
}
54
55
// AddHandler adds a handler to the handler.Handler.
56
// The given handler will be called on the main thread.
57
// The returned function will remove the handler.
58
func (m *MainThreadHandler) AddHandler(handler any) func() {
59
return m.h.AddSyncHandler(handler)
60
}
61
62
// AddSyncHandler is the same as [AddHandler].
63
// It exists for compatibility.
64
func (m *MainThreadHandler) AddSyncHandler(handler any) func() {
65
return m.AddHandler(handler)
66
}
67
68