Created
August 11, 2022 18:29
-
-
Save maxsei/782d06ee690798570d2cb0073c3943a9 to your computer and use it in GitHub Desktop.
This is an attempt at making something that kills go routines in a stack of go routines in a LIFO order
This file contains hidden or 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
| package main | |
| import ( | |
| "sync/atomic" | |
| "log" | |
| "time" | |
| ) | |
| func main() { | |
| msgs := make(chan struct{}) | |
| // Client making 10 req/s. | |
| go func() { | |
| for i := 0; i < 20; i++{ | |
| time.Sleep(time.Second / 10) | |
| go func(){msgs <- struct{}{}}() | |
| } | |
| }() | |
| // Server than can handle 5 req/s. | |
| server := NewServer(5, time.Second) | |
| server.Serve(msgs) | |
| } | |
| func NewServer(limit int, freq time.Duration) *Server { | |
| ret := Server{ | |
| limit : int64(limit), | |
| counter : 0, | |
| freq :freq, | |
| updates : make(chan Update), | |
| } | |
| return &ret | |
| } | |
| type Server struct { | |
| limit int64 | |
| counter int64 | |
| freq time.Duration | |
| updates chan Update | |
| } | |
| func (s *Server) Serve(msgs chan struct{}) { | |
| for { | |
| <-msgs | |
| go s.Handle() | |
| } | |
| } | |
| func (s *Server) Handle() { | |
| stackPos, _ := AddInt64(&s.counter, 1) // cur, acc := AddInt64(v, 1) | |
| start := time.Now() | |
| defer func(){ | |
| if r := recover(); r == nil { | |
| log.Printf("aborting handler started at %v", start) | |
| } | |
| AddInt64(&s.counter, -1) | |
| }() | |
| go func(){ | |
| s.updates<- Update{UpdateStart, time.Now(), stackPos} | |
| Work(start) | |
| log.Println("sending update that we're done from handler started at %v", start) | |
| s.updates<- Update{UpdateStop, time.Now(), stackPos} | |
| }() | |
| for { | |
| update := <-s.updates | |
| switch update.status{ | |
| case UpdateStart: | |
| pastLimit := stackPos > s.limit | |
| pastRate := update.at.Sub(start) < s.freq | |
| if pastLimit && pastRate { | |
| panic(nil) | |
| } | |
| case UpdateStop: | |
| if update.pos < stackPos { | |
| stackPos-- | |
| } | |
| if stackPos == 0 { | |
| return | |
| } | |
| } | |
| } | |
| } | |
| func Work(id time.Time) { | |
| const n int = 20 | |
| dur := time.Second | |
| for i := 0; i < n; i++ { | |
| // prog := (i+1)/n | |
| // log.Printf("%v %.03f", id, prog) | |
| time.Sleep(dur / time.Duration(n)) | |
| } | |
| } | |
| func AddInt64(v *int64, amount int64) (int64, int64) { | |
| cur := atomic.LoadInt64(v) | |
| acc := atomic.AddInt64(v, amount) | |
| // log.Printf("%d-> %d", cur, acc) | |
| return cur, acc | |
| } | |
| const ( | |
| UpdateStart = iota | |
| UpdateStop | |
| ) | |
| type Update struct { | |
| status int | |
| at time.Time | |
| pos int64 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment