-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchannel-send.go
69 lines (56 loc) · 1.8 KB
/
channel-send.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
/*
© 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
ISC License
*/
package parl
import (
"github.com/haraldrudell/parl/perrors"
"github.com/haraldrudell/parl/pruntime"
)
// with nonBlocking set to SendNonBlocking, ChannelSend will never block
const SendNonBlocking = true
// ChannelSend is channel send without panics and possibly non-blocking
// - if nonBlocking is SendNonBlocking or true, channel send will be attempted but not block
// - didSend is true if value was successfully sent on ch
// - err is non-nil if a panic occurred or ch is nil
// - isNilChannel is true if the channel is nil, ie. send would block indefinitely
// - isClosedChannel is true if the panic was caused by ch being closed
// - there should be no panics other than from ch being closed
func ChannelSend[T any](ch chan<- T, value T, nonBlocking ...bool) (didSend, isNilChannel, isClosedChannel bool, err error) {
// check for nil channel
if isNilChannel = ch == nil; isNilChannel {
err = perrors.NewPF("ch channel nil")
return
}
// get non-blocking flag
var sendNb bool
if len(nonBlocking) > 0 {
sendNb = nonBlocking[0]
}
// send, recovering panics
didSend, err = channelSend(ch, value, sendNb)
// set isClosed flag
if err != nil && pruntime.IsSendOnClosedChannel(err) {
isClosedChannel = true
}
return
}
// channelSend sends possibly non-blocking
// - the only way to determine closed channel is to send, which panics
// - a separate function to recover the panic
func channelSend[T any](ch chan<- T, value T, sendNb bool) (didSend bool, err error) {
defer PanicToErr(&err)
// send non-blocking
if sendNb {
select {
case ch <- value:
didSend = true
default:
}
return
}
// send blocking: blocks here
ch <- value
didSend = true
return
}