github.com/haraldrudell/parl@v0.4.176/channel-send.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package parl 7 8 import ( 9 "github.com/haraldrudell/parl/perrors" 10 "github.com/haraldrudell/parl/pruntime" 11 ) 12 13 // with nonBlocking set to SendNonBlocking, ChannelSend will never block 14 const SendNonBlocking = true 15 16 // ChannelSend is channel send without panics and possibly non-blocking 17 // - if nonBlocking is SendNonBlocking or true, channel send will be attempted but not block 18 // - didSend is true if value was successfully sent on ch 19 // - err is non-nil if a panic occurred or ch is nil 20 // - isNilChannel is true if the channel is nil, ie. send would block indefinitely 21 // - isClosedChannel is true if the panic was caused by ch being closed 22 // - there should be no panics other than from ch being closed 23 func ChannelSend[T any](ch chan<- T, value T, nonBlocking ...bool) (didSend, isNilChannel, isClosedChannel bool, err error) { 24 25 // check for nil channel 26 if isNilChannel = ch == nil; isNilChannel { 27 err = perrors.NewPF("ch channel nil") 28 return 29 } 30 31 // get non-blocking flag 32 var sendNb bool 33 if len(nonBlocking) > 0 { 34 sendNb = nonBlocking[0] 35 } 36 37 // send, recovering panics 38 didSend, err = channelSend(ch, value, sendNb) 39 40 // set isClosed flag 41 if err != nil && pruntime.IsSendOnClosedChannel(err) { 42 isClosedChannel = true 43 } 44 45 return 46 } 47 48 // channelSend sends possibly non-blocking 49 // - the only way to determine closed channel is to send, which panics 50 // - a separate function to recover the panic 51 func channelSend[T any](ch chan<- T, value T, sendNb bool) (didSend bool, err error) { 52 defer PanicToErr(&err) 53 54 // send non-blocking 55 if sendNb { 56 select { 57 case ch <- value: 58 didSend = true 59 default: 60 } 61 return 62 } 63 64 // send blocking: blocks here 65 ch <- value 66 didSend = true 67 68 return 69 }