Skip to content

Instantly share code, notes, and snippets.

@reusee
Created October 15, 2017 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reusee/d125f8088fffce07f7f315c51f3498dd to your computer and use it in GitHub Desktop.
Save reusee/d125f8088fffce07f7f315c51f3498dd to your computer and use it in GitHub Desktop.
priority
package main
import (
"fmt"
"sync"
"time"
)
func main() {
pt := fmt.Printf
// scheduler
type G struct {
C chan struct{}
Priority int
}
enters := make(chan G, 65536)
yields := make(chan G, 65536)
quits := make(chan G, 65536)
const MaxPriority = 128
go func() {
var parked [MaxPriority + 1][]G
var numGs [MaxPriority + 1]int
loop:
for {
select {
case g := <-enters:
numGs[g.Priority]++
case g := <-yields:
for i := 0; i < g.Priority; i++ {
if numGs[i] > 0 {
parked[g.Priority] = append(parked[g.Priority], g)
continue loop
}
}
g.C <- struct{}{}
case g := <-quits:
numGs[g.Priority]--
if numGs[g.Priority] > 0 {
continue loop
}
for i := g.Priority + 1; i <= MaxPriority; i++ {
if len(parked[i]) > 0 {
for _, req := range parked[i] {
req.C <- struct{}{}
}
parked[i] = parked[i][0:0]
break
}
}
}
}
}()
spawn := func(priority int, fn func(yield func())) {
c := make(chan struct{})
g := G{
C: c,
Priority: priority,
}
yield := func() {
yields <- g
<-c
}
enters <- g
go func() {
defer func() {
quits <- g
}()
yield()
fn(yield)
}()
}
// demo
// busy goroutines
n := 100000
wg := new(sync.WaitGroup)
wg.Add(n)
for i := 0; i < n; i++ {
spawn(10, func(yield func()) {
wg.Done()
for {
fmt.Printf("")
yield()
}
})
}
wg.Wait()
t0 := time.Now()
done := make(chan struct{})
spawn(1, func(yield func()) {
close(done)
})
<-done
pt("%v\n", time.Now().Sub(t0))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment