Skip to content

Instantly share code, notes, and snippets.

@gatlin
Created August 13, 2012 22:23
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 gatlin/3344489 to your computer and use it in GitHub Desktop.
Save gatlin/3344489 to your computer and use it in GitHub Desktop.
Concepts from Orc applied in Go
package main
import (
"fmt"
"github.com/gatlin/go-orc"
"net/http"
"time"
)
/*
* a nifty example
*/
func main() {
// a site is a function which publishes a value asynchronously
load_page := orc.Site{
func(url orc.Void, publish orc.Voidchan) {
resp, _ := http.Get(url.(string))
defer resp.Body.Close()
publish <- url
},
}
// the built-in Cut function calls multiple sites concurrently and yields
// the first return value
loaded_first := orc.Cut([]orc.Voidchan{
load_page.Call("http://archlinux.fr"),
load_page.Call("http://google.com"),
load_page.Call("http://amazon.com"),
})
// for now, it's your job to assert types.
// Void is interface{} and Voidchan is chan interface{}
fmt.Println(loaded_first.(string))
// rtimer publishes `t` after `t` seconds
rtimer := orc.Site{
func(t orc.Void, publish orc.Voidchan) {
<-time.After(time.Duration(t.(int)) * time.Second)
publish <- t
},
}
// this site wraps fmt.Println
site_print := orc.Site{
func(msg orc.Void, publish orc.Voidchan) {
fmt.Println(msg)
publish <- nil
},
}
// sites can be recursive if pre-declared
// metronome also shows a nifty heart-beat pattern in Orc which could be
// useful for fault-tolerance in distributed computations
var metronome orc.Site
metronome = orc.Site{
func(t orc.Void, publish orc.Voidchan) {
orc.Merge([]orc.Voidchan{
site_print.Call("tick"),
rtimer.Call(t).ForEachDo(metronome),
})
},
}
<-metronome.Call(1)
}
package orc
/*
* end run around the type system
*/
type Void interface{}
type Voidchan chan Void
/*
* Sites, functions which remote / asynchronous services
*/
type Site struct {
Fn func(arg Void, out Voidchan)
}
func (s Site) Call(arg Void) Voidchan {
out := make(Voidchan, 1)
go s.Fn(arg, out)
return out
}
/*
* Orc inspired functions
*/
func Merge(cs []Voidchan) Voidchan {
combined := make(Voidchan, cap(cs))
for _, c := range cs {
go func(ch Voidchan) {
for v := range ch {
combined <- v
}
return
}(c)
}
return combined
}
func (self Voidchan) ForEachDo(site Site) Voidchan {
for i := 0; i < cap(self); i++ {
s := <-self
<-site.Call(s)
}
return make(Voidchan, 1)
}
func (self Voidchan) WithFirstDo(fn Site) {
v := <-self
<-fn.Call(v)
}
func Cut(cs []Voidchan) Void {
c := make(Voidchan, 1)
Merge(cs).WithFirstDo(Site{
func(arg Void, out Voidchan) {
c <- arg
out <- nil
},
})
return <-c
}
@gatlin
Copy link
Author

gatlin commented Aug 13, 2012

Causes a deadlock but this is the basic idea, even if it's faulty for now.

@gatlin
Copy link
Author

gatlin commented Aug 14, 2012

Above comment is now obsolete :)

@gatlin
Copy link
Author

gatlin commented Aug 16, 2012

If anyone does view this, Sites are objects because I'd like to abstract how computations are orchestrated from where they are happening; Site might become an interface adhered to by a LocalSite or RemoteSite object. Stay tuned?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment