Skip to content

Commit 432ae7e

Browse files
authored
Support Go1.18 generics for all interface{} operations
1 parent 6ba0c9c commit 432ae7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+531
-448
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
*.sqlite
2-
*.sqlite-journal
2+
*.sqlite-journal
3+
vendor

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@
3333
},
3434
"github-actions.workflows.pinned.workflows": [
3535
".github/workflows/go.yml"
36-
]
36+
],
37+
"go.alternateTools": {
38+
"go": "/Users/cschleiden/sdk/go1.18rc1/bin/go",
39+
},
40+
"go.testExplorer.showDynamicSubtestsInEditor": true,
3741
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/cschleiden/go-workflows
22

3-
go 1.17
3+
go 1.18
44

55
require (
66
github.com/go-sql-driver/mysql v1.6.0

internal/sync/channel.go

Lines changed: 69 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,76 @@ package sync
22

33
import (
44
"github.com/cschleiden/go-workflows/internal/converter"
5-
"github.com/pkg/errors"
65
)
76

8-
type Channel interface {
9-
Send(ctx Context, v interface{})
7+
type Channel[T any] interface {
8+
Send(ctx Context, v T)
109

11-
SendNonblocking(ctx Context, v interface{}) (ok bool)
10+
SendNonblocking(ctx Context, v T) (ok bool)
1211

13-
Receive(ctx Context, vptr interface{}) (more bool)
12+
Receive(ctx Context) (v T, ok bool)
1413

15-
ReceiveNonblocking(ctx Context, vptr interface{}) (more bool)
14+
ReceiveNonblocking(ctx Context) (v T, ok bool)
1615

1716
Close()
1817
}
1918

20-
type ChannelInternal interface {
19+
type ChannelInternal[T any] interface {
2120
Closed() bool
2221

23-
ReceiveNonBlocking(ctx Context, cb func(v interface{})) (ok bool)
22+
ReceiveNonBlocking(ctx Context) (v T, ok bool)
2423

25-
AddReceiveCallback(cb func(v interface{}))
24+
AddReceiveCallback(cb func(v T, ok bool))
2625
}
2726

28-
func NewChannel() Channel {
29-
return &channel{
30-
c: make([]interface{}, 0),
27+
// Ensure channel implementation support internal interface
28+
var _ ChannelInternal[struct{}] = (*channel[struct{}])(nil)
29+
30+
func NewChannel[T any]() Channel[T] {
31+
return &channel[T]{
32+
c: make([]T, 0),
3133
converter: converter.DefaultConverter,
3234
}
3335
}
3436

35-
func NewBufferedChannel(size int) Channel {
36-
return &channel{
37-
c: make([]interface{}, 0, size),
37+
func NewBufferedChannel[T any](size int) Channel[T] {
38+
return &channel[T]{
39+
c: make([]T, 0, size),
3840
size: size,
3941
converter: converter.DefaultConverter,
4042
}
4143
}
4244

43-
type channel struct {
44-
c []interface{}
45-
receivers []func(interface{})
46-
senders []func() interface{}
45+
type channel[T any] struct {
46+
c []T
47+
receivers []func(value T, ok bool)
48+
senders []func() T
4749
closed bool
4850
size int
4951
converter converter.Converter
5052
}
5153

52-
var _ Channel = (*channel)(nil)
53-
var _ ChannelInternal = (*channel)(nil)
54-
55-
func (c *channel) Close() {
54+
func (c *channel[T]) Close() {
5655
c.closed = true
5756

5857
// If there are still blocked senders, error
5958
if len(c.senders) > 0 {
6059
panic("send on closed channel")
6160
}
6261

62+
// TODO: Drain buffered values
6363
for len(c.receivers) > 0 {
6464
r := c.receivers[0]
6565
c.receivers[0] = nil
6666
c.receivers = c.receivers[1:]
6767

68-
r(nil)
68+
// Send zero value to pending receiver
69+
var v T
70+
r(v, false)
6971
}
7072
}
7173

72-
func (c *channel) Send(ctx Context, v interface{}) {
74+
func (c *channel[T]) Send(ctx Context, v T) {
7375
cr := getCoState(ctx)
7476

7577
addedSender := false
@@ -84,50 +86,48 @@ func (c *channel) Send(ctx Context, v interface{}) {
8486
if !addedSender {
8587
addedSender = true
8688

87-
cb := func() interface{} {
89+
cb := func() T {
8890
sentValue = true
8991
return v
9092
}
9193

9294
c.senders = append(c.senders, cb)
9395
}
9496

97+
// No waiting receiver, yield
9598
cr.Yield()
9699

100+
// Was our sender called while we yielded? If so, we can return
97101
if sentValue {
98102
cr.MadeProgress()
99103
return
100104
}
101105
}
102106
}
103107

104-
func (c *channel) SendNonblocking(ctx Context, v interface{}) bool {
108+
func (c *channel[T]) SendNonblocking(ctx Context, v T) bool {
105109
return c.trySend(v)
106110
}
107111

108-
func (c *channel) Receive(ctx Context, vptr interface{}) (more bool) {
112+
func (c *channel[T]) Receive(ctx Context) (v T, ok bool) {
109113
cr := getCoState(ctx)
110114

111115
addedListener := false
112116
receivedValue := false
113117

114118
for {
115119
// Try to receive from buffered channel or blocked sender
116-
if c.tryReceive(vptr) {
120+
if v, ok, rok := c.tryReceive(); rok {
117121
cr.MadeProgress()
118-
return !c.closed
122+
return v, ok
119123
}
120124

121125
// Register handler to receive value once
122126
if !addedListener {
123-
cb := func(v interface{}) {
127+
cb := func(rv T, rok bool) {
124128
receivedValue = true
125-
126-
if vptr != nil {
127-
if err := converter.AssignValue(c.converter, v, vptr); err != nil {
128-
panic(err)
129-
}
130-
}
129+
v = rv
130+
ok = rok
131131
}
132132

133133
c.receivers = append(c.receivers, cb)
@@ -139,25 +139,30 @@ func (c *channel) Receive(ctx Context, vptr interface{}) (more bool) {
139139
// If we received a value via the callback, return
140140
if receivedValue {
141141
cr.MadeProgress()
142-
return !c.closed
142+
return v, ok
143143
}
144144
}
145145
}
146146

147-
func (c *channel) ReceiveNonblocking(ctx Context, vptr interface{}) (ok bool) {
148-
return c.tryReceive(vptr)
147+
func (c *channel[T]) ReceiveNonblocking(ctx Context) (T, bool) {
148+
if v, ok, rok := c.tryReceive(); rok {
149+
return v, ok
150+
}
151+
152+
var z T
153+
return z, false
149154
}
150155

151-
func (c *channel) hasValue() bool {
156+
func (c *channel[T]) hasValue() bool {
152157
return len(c.c) > 0
153158
}
154159

155-
func (c *channel) canReceive() bool {
160+
func (c *channel[T]) canReceive() bool {
156161
return c.hasValue() || len(c.senders) > 0 || c.closed
157162
}
158163

159-
func (c *channel) trySend(v interface{}) bool {
160-
// If closed, we can't send, exit.
164+
func (c *channel[T]) trySend(v T) bool {
165+
// If closed, we can't send, panic.
161166
if c.closed {
162167
panic("channel closed")
163168
}
@@ -168,7 +173,9 @@ func (c *channel) trySend(v interface{}) bool {
168173
r := c.receivers[0]
169174
c.receivers[0] = nil
170175
c.receivers = c.receivers[1:]
171-
r(v)
176+
177+
r(v, true)
178+
172179
return true
173180
}
174181

@@ -182,72 +189,52 @@ func (c *channel) trySend(v interface{}) bool {
182189
return false
183190
}
184191

185-
func (c *channel) tryReceive(vptr interface{}) bool {
192+
func (c *channel[T]) tryReceive() (v T, ok bool, rok bool) {
186193
// If channel is buffered, return value if available
187194
if c.hasValue() {
188-
v := c.c[0]
195+
v = c.c[0]
189196
c.c = c.c[1:]
190197

191-
if vptr != nil {
192-
if err := converter.AssignValue(c.converter, v, vptr); err != nil {
193-
panic(errors.Wrap(err, "could not assign value when receiving from channel"))
194-
}
195-
}
196-
197-
return true
198+
return v, true, true
198199
}
199200

200201
// If channel has been closed and no values in buffer (if buffered) return zero
201202
// element
202203
if c.closed {
203-
if vptr != nil {
204-
if err := converter.AssignValue(c.converter, nil, vptr); err != nil {
205-
panic(err)
206-
}
207-
}
208-
209-
return true
204+
var z T
205+
return z, false, true
210206
}
211207

208+
// Any blocked senders? If so, receive from the first one
212209
if len(c.senders) > 0 {
213210
s := c.senders[0]
214211
c.senders[0] = nil
215212
c.senders = c.senders[1:]
216213

217-
v := s()
218-
219-
if vptr != nil {
220-
if err := converter.AssignValue(c.converter, v, vptr); err != nil {
221-
panic(err)
222-
}
223-
}
224-
225-
return true
214+
return s(), true, true
226215
}
227216

228-
return false
217+
// Could not receive value
218+
return v, ok, false
229219
}
230220

231-
func (c *channel) hasCapacity() bool {
221+
func (c *channel[T]) hasCapacity() bool {
232222
return len(c.c) < c.size
233223
}
234224

235-
func (c *channel) AddReceiveCallback(cb func(v interface{})) {
225+
func (c *channel[T]) AddReceiveCallback(cb func(v T, ok bool)) {
236226
c.receivers = append(c.receivers, cb)
237227
}
238228

239-
func (c *channel) ReceiveNonBlocking(ctx Context, cb func(v interface{})) (ok bool) {
240-
var vptr interface{}
241-
if c.tryReceive(vptr) {
242-
cb(vptr)
243-
return true
229+
func (c *channel[T]) ReceiveNonBlocking(ctx Context) (T, bool) {
230+
if v, ok, rok := c.tryReceive(); rok {
231+
return v, ok
244232
}
245233

246-
c.AddReceiveCallback(cb)
247-
248-
return false
234+
var z T
235+
return z, false
249236
}
250237

251-
func (c *channel) Closed() bool {
238+
func (c *channel[T]) Closed() bool {
252239
return c.closed
253240
}

0 commit comments

Comments
 (0)