Skip to content

Instantly share code, notes, and snippets.

@lestrrat
Last active November 20, 2015 01:52
Show Gist options
  • Save lestrrat/f315b701d1087b059658 to your computer and use it in GitHub Desktop.
Save lestrrat/f315b701d1087b059658 to your computer and use it in GitHub Desktop.
package main
import (
"log"
"math/rand"
"time"
)
type Promise struct {
done bool
OnDone func()
}
type Job struct {
Payload int
Done func()
}
type Proxy struct {
C chan (Job)
}
func (p *Promise) SetDone() {
// need locking
p.done = true
}
func (p Promise) IsDone() bool {
// need locking
return p.done
}
func NewProxy() *Proxy {
c := make(chan Job)
go proxy(c)
return &Proxy{C: c}
}
func (p Proxy) Work(j Job) *Promise {
promise := &Promise{done: false}
j.Done = func() {
promise.SetDone()
}
p.C <- j
return promise
}
func proxy(c chan Job) {
for j := range c {
// 適当…
delay := time.Duration(rand.Intn(j.Payload)) * time.Second
log.Printf("Job %d, delay %d seconds", j.Payload, delay/time.Second)
time.AfterFunc(delay, j.Done)
}
}
func main() {
promises := []*Promise{}
p := NewProxy()
for i := 1; i <= 10; i++ {
x := i // make sure changes are reflected in done
done := func() {
log.Printf("Done with %d", x)
}
promise := p.Work(Job{Payload: i})
promise.OnDone = done
promises = append(promises, promise)
}
OUT:
for len(promises) > 0 {
for i, promise := range promises {
if !promise.IsDone() {
continue
}
promise.OnDone()
switch i {
case 0:
promises = promises[1:]
case len(promises) - 1:
promises = promises[:len(promises)-1]
default:
promises = append(promises[:i], promises[i+1:]...)
}
continue OUT
}
time.Sleep(time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment