-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v0.4.119 refactor AtomicMax closers errorglue.ErrorList perrors.Error…
…List
- Loading branch information
1 parent
4bb102e
commit ae2ee21
Showing
17 changed files
with
316 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
© 2022–present Harald Rudell <[email protected]> (https://haraldrudell.github.io/haraldrudell/) | ||
ISC License | ||
*/ | ||
|
||
package parl | ||
|
||
import ( | ||
"github.com/haraldrudell/parl/perrors" | ||
"github.com/haraldrudell/parl/pruntime" | ||
) | ||
|
||
const ( | ||
CloseChannelDrain = true | ||
) | ||
|
||
// CloseChannel closes a channel | ||
// - CloseChannel is thread-safe, deferrable and panic-free, | ||
// handles closed-channel panic, nil-channel case and | ||
// has channel drain feature | ||
// - isNilChannel returns true if ch is nil. | ||
// closing a nil channel would cause panic. | ||
// - isCloseOfClosedChannel is true if close paniced due to | ||
// the channel already closed. | ||
// A channel transferring data cannot be inspected for being | ||
// closed | ||
// - if errp is non-nil, panic values updates it using errors.AppendError. | ||
// - if doDrain is [parl.CloseChannelDrain], the channel is drained first. | ||
// Note: closing a channel while a thread is blocked in channel send is | ||
// a data race. | ||
// If a thread is continuously sending items and doDrain is true, | ||
// CloseChannel will block indefinitely. | ||
// - n returns the number of drained items. | ||
func CloseChannel[T any](ch chan T, errp *error, drainChannel ...bool) ( | ||
isNilChannel, isCloseOfClosedChannel bool, n int, err error, | ||
) { | ||
|
||
// nil channel case | ||
if isNilChannel = ch == nil; isNilChannel { | ||
return // closing of nil channel return | ||
} | ||
|
||
// channel drain feature | ||
if len(drainChannel) > 0 && drainChannel[0] { | ||
for { | ||
select { | ||
// read non-blocking from the channel | ||
// - ok true: received item, channel is not closed | ||
// - ok false: channel is closed | ||
case _, ok := <-ch: | ||
if ok { | ||
// the channel is not closed | ||
n++ | ||
continue // read next item | ||
} | ||
default: // channel is open but has no items | ||
} | ||
break // closed or no items | ||
} | ||
} | ||
|
||
// close channel | ||
if Closer(ch, &err); err == nil { | ||
return // close successful return | ||
} | ||
|
||
// handle close error | ||
isCloseOfClosedChannel = pruntime.IsCloseOfClosedChannel(err) | ||
if errp != nil { | ||
*errp = perrors.AppendError(*errp, err) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
© 2022–present Harald Rudell <[email protected]> (https://haraldrudell.github.io/haraldrudell/) | ||
ISC License | ||
*/ | ||
|
||
package parl | ||
|
||
import "testing" | ||
|
||
func TestCloseChannel(t *testing.T) { | ||
var value = 3 | ||
var doDrain = true | ||
|
||
var ch chan int | ||
var err, errp error | ||
var n int | ||
var isNilChannel, isCloseOfClosedChannel bool | ||
|
||
// close of nil channel should return isNilChannel true | ||
ch = nil | ||
isNilChannel, isCloseOfClosedChannel, n, err = CloseChannel(ch, &errp) | ||
if !isNilChannel { | ||
t.Error("isNilChannel false") | ||
} | ||
_ = err | ||
_ = n | ||
_ = isCloseOfClosedChannel | ||
|
||
// n should return number of items when draining | ||
ch = make(chan int, 1) | ||
ch <- value | ||
isNilChannel, isCloseOfClosedChannel, n, err = CloseChannel(ch, &errp, doDrain) | ||
if n != 1 { | ||
t.Errorf("n bad %d exp %d", n, 1) | ||
} | ||
_ = isNilChannel | ||
_ = err | ||
_ = isCloseOfClosedChannel | ||
|
||
// close of closed channel should set isCloseOfClosedChannel, err, errp | ||
ch = make(chan int) | ||
close(ch) | ||
isNilChannel, isCloseOfClosedChannel, n, err = CloseChannel(ch, &errp) | ||
if !isCloseOfClosedChannel { | ||
t.Error("isCloseOfClosedChannel false") | ||
} | ||
if err == nil { | ||
t.Error("isCloseOfClosedChannel err nil") | ||
} | ||
if errp == nil { | ||
t.Error("isCloseOfClosedChannel errp nil") | ||
} | ||
_ = isNilChannel | ||
_ = n | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.