Created
August 8, 2017 16:57
-
-
Save davidkellis/a022bc3a430575d6353b1fa9863b1b80 to your computer and use it in GitHub Desktop.
Fibers in Go (found at https://play.golang.org/p/NSIlZ327sC)
This file contains 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
// I found the following implementation (verbatim) of Fibers in Go at https://play.golang.org/p/NSIlZ327sC | |
// I'm capturing it here for future reference. | |
package main | |
import ( | |
"errors" | |
"fmt" | |
) | |
var errResumeDeadFiber = errors.New("resume dead fiber") | |
type fiberDeadPanic struct{} | |
type Fiber struct { | |
resume chan int | |
close chan int | |
} | |
func NewFiber() *Fiber { | |
f := Fiber{ | |
resume: make(chan int), | |
close: make(chan int), | |
} | |
go f.run() | |
return &f | |
} | |
func (f *Fiber) handleBreak() { | |
if r := recover(); r != nil { | |
if _, ok := r.(fiberDeadPanic); !ok { | |
panic(r) | |
} | |
} | |
fmt.Println("exit goroutine") | |
} | |
func (f *Fiber) run() { | |
defer f.handleBreak() | |
i := 0 | |
for { | |
f.Yield(i) | |
f.Yield(i) | |
i++ | |
} | |
} | |
func (f *Fiber) Yield(i int) { | |
select { | |
case <-f.close: | |
panic(fiberDeadPanic{}) | |
case f.resume <- i: | |
} | |
} | |
func (f *Fiber) Resume() (int, error) { | |
select { | |
case <-f.close: | |
return 0, errResumeDeadFiber | |
default: | |
return <-f.resume, nil | |
} | |
} | |
func (f *Fiber) Close() { | |
select { | |
case <-f.close: | |
default: | |
close(f.close) | |
} | |
} | |
func main() { | |
for i := 0; i < 5; i++ { | |
f := NewFiber() | |
fmt.Println(f.Resume()) | |
fmt.Println(f.Resume()) | |
fmt.Println(f.Resume()) | |
fmt.Println(f.Resume()) | |
f.Close() | |
fmt.Println(f.Resume()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment