Skip to content

Instantly share code, notes, and snippets.

@maxsei
Created August 11, 2022 18:29
Show Gist options
  • Select an option

  • Save maxsei/782d06ee690798570d2cb0073c3943a9 to your computer and use it in GitHub Desktop.

Select an option

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
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