Исходники и презентации
This commit is contained in:
81
lessons/contexts/context_with_timeout_implementation/main.go
Normal file
81
lessons/contexts/context_with_timeout_implementation/main.go
Normal file
@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
done chan struct{}
|
||||
closed int32
|
||||
}
|
||||
|
||||
func WithTimeout(parent Context, duration time.Duration) (*Context, func()) {
|
||||
if atomic.LoadInt32(&parent.closed) == 1 {
|
||||
return nil, nil // don't use nil
|
||||
}
|
||||
|
||||
ctx := &Context{
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
cancel := func() {
|
||||
if atomic.CompareAndSwapInt32(&ctx.closed, 0, 1) {
|
||||
close(ctx.done)
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
timer := time.NewTimer(duration)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-parent.Done():
|
||||
case <-timer.C:
|
||||
}
|
||||
|
||||
cancel()
|
||||
}()
|
||||
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
func (c *Context) Done() <-chan struct{} {
|
||||
return c.done
|
||||
}
|
||||
|
||||
func (c *Context) Err() error {
|
||||
select {
|
||||
case <-c.done:
|
||||
return errors.New("context deadline exceeded")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) Deadline() (time.Time, bool) {
|
||||
// not implemented
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
func (c *Context) Value(any) any {
|
||||
// not implemented
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx, cancel := WithTimeout(Context{}, time.Second)
|
||||
defer cancel()
|
||||
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-timer.C:
|
||||
fmt.Println("finished")
|
||||
case <-ctx.Done():
|
||||
fmt.Println("canceled")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user