-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathproceedevent.go
168 lines (136 loc) · 4.81 KB
/
proceedevent.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright 2023 Tailscale Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
// +build windows
package walk
type proceedEventHandlerInfo struct {
handler ProceedEventHandler
once bool
}
// ProceedEventHandler is a func that should return true to proceed past the
// event, or false to abort.
type ProceedEventHandler func() bool
// ProceedEvent is an event where, if any of its handlers return false, its
// publisher should not proceed further past the event. Note that once a given
// handler returns false, the event is immediately aborted; no additional
// handlers are run.
type ProceedEvent struct {
handlers []proceedEventHandlerInfo
}
// Attach adds handler to e and will be invoked when the event associated with
// e is triggered. It returns an integral handle to the event that may be used
// with Detach.
func (e *ProceedEvent) Attach(handler ProceedEventHandler) int {
handlerInfo := proceedEventHandlerInfo{handler, false}
for i, h := range e.handlers {
if h.handler == nil {
e.handlers[i] = handlerInfo
return i
}
}
e.handlers = append(e.handlers, handlerInfo)
return len(e.handlers) - 1
}
// Detach removes the handler specified by handle, which was obtained as the
// result of a call to Attach.
func (e *ProceedEvent) Detach(handle int) {
e.handlers[handle].handler = nil
}
// Once is similar to Attach, except that handler is attached as a "one-shot"
// occurrence; handler will automatically be detached after its first invocation.
func (e *ProceedEvent) Once(handler ProceedEventHandler) {
i := e.Attach(handler)
e.handlers[i].once = true
}
// ProceedEventPublisher is the event publisher used by any code that supports
// ProceedEvent.
type ProceedEventPublisher struct {
event ProceedEvent
}
// Event obtains a pointer to the ProceedEvent associated with p.
func (p *ProceedEventPublisher) Event() *ProceedEvent {
return &p.event
}
// Publish dispatches the event to all registered handlers. The first handler
// to return false will abort event dispatch and Publish will return false.
// Otherwise, Publish returns true.
func (p *ProceedEventPublisher) Publish() bool {
for i, h := range p.event.handlers {
if h.handler != nil {
proceed := h.handler()
if h.once {
p.event.Detach(i)
}
if !proceed {
return false
}
}
}
return true
}
type proceedWithArgEventHandlerInfo[T any] struct {
handler ProceedWithArgEventHandler[T]
once bool
}
// ProceedWithArgEventHandler is a func that accepts param of type T and should
// return true to proceed past the event, or false to abort.
type ProceedWithArgEventHandler[T any] func(param T) bool
// ProceedWithArgEvent is an event where, if any of its handlers return false, its
// publisher should not proceed further past the event. Note that once a given
// handler returns false, the event is immediately aborted; no additional
// handlers are run.
type ProceedWithArgEvent[T any] struct {
handlers []proceedWithArgEventHandlerInfo[T]
}
// Attach adds handler to e and will be invoked when the event associated with
// e is triggered. It returns an integral handle to the event that may be used
// with Detach.
func (e *ProceedWithArgEvent[T]) Attach(handler ProceedWithArgEventHandler[T]) int {
handlerInfo := proceedWithArgEventHandlerInfo[T]{handler, false}
for i, h := range e.handlers {
if h.handler == nil {
e.handlers[i] = handlerInfo
return i
}
}
e.handlers = append(e.handlers, handlerInfo)
return len(e.handlers) - 1
}
// Detach removes the handler specified by handle, which was obtained as the
// result of a call to Attach.
func (e *ProceedWithArgEvent[T]) Detach(handle int) {
e.handlers[handle].handler = nil
}
// Once is similar to Attach, except that handler is attached as a "one-shot"
// occurrence; handler will automatically be detached after its first invocation.
func (e *ProceedWithArgEvent[T]) Once(handler ProceedWithArgEventHandler[T]) {
i := e.Attach(handler)
e.handlers[i].once = true
}
// ProceedWithArgEventPublisher is the event publisher used by any code that supports
// ProceedWithArgEvent.
type ProceedWithArgEventPublisher[T any] struct {
event ProceedWithArgEvent[T]
}
// Event obtains a pointer to the ProceedWithArgEvent associated with p.
func (p *ProceedWithArgEventPublisher[T]) Event() *ProceedWithArgEvent[T] {
return &p.event
}
// Publish dispatches the event with param of type T to all registered handlers.
// The first handler to return false will abort event dispatch and Publish will
// return false. Otherwise, Publish returns true.
func (p *ProceedWithArgEventPublisher[T]) Publish(param T) bool {
for i, h := range p.event.handlers {
if h.handler != nil {
proceed := h.handler(param)
if h.once {
p.event.Detach(i)
}
if !proceed {
return false
}
}
}
return true
}