1package main 2 3import ( 4 "fmt" 5 6 "github.com/Arceliar/phony" 7) 8 9// Structs can embed the Inbox type to fulfill the Actor interface. 10type printer struct { 11 phony.Inbox 12} 13 14// Functions can be defined to send messages to an Actor from another Actor. 15func (p *printer) Println(from phony.Actor, msg ...interface{}) { 16 p.Act(from, func() { fmt.Println(msg...) }) 17} 18 19// It's useful to embed an Actor in a struct whose fields the Actor is responsible for. 20type counter struct { 21 phony.Inbox 22 count int 23 printer *printer 24} 25 26// Act with a nil sender is useful for asking an Actor to do something from non-Actor code. 27func (c *counter) Increment() { 28 c.Act(nil, func() { c.count++ }) 29} 30 31// Block waits until after a message has been processed before returning. 32// This can be used to interrogate an Actor from an outside goroutine. 33// Note that Actors shouldn't use this on eachother, since it blocks, it's just meant for convenience when interfacing with outside code. 34func (c *counter) Get() int { 35 var n int 36 phony.Block(c, func() { n = c.count }) 37 return n 38} 39 40// Print sends a message to the counter, telling to to call c.printer.Println 41// Calling Println sends a message to the printer, telling it to print 42// So message sends become function calls. 43func (c *counter) Print() { 44 c.Act(nil, func() { 45 c.printer.Println(c, "The count is:", c.count) 46 }) 47} 48 49func main() { 50 c := &counter{printer: new(printer)} // Create an actor 51 for idx := 0; idx < 10; idx++ { 52 c.Increment() // Ask the Actor to do some work 53 c.Print() // And ask it to send a message to another Actor, which handles them asynchronously 54 } 55 n := c.Get() // Inspect the Actor's internal state 56 fmt.Println("Value from Get:", n) // This likely prints before the Print() lines above have finished -- Actors work asynchronously. 57 phony.Block(c.printer, func() {}) // Wait for an Actor to handle a message, in this case just to finish printing 58 fmt.Println("Exiting") 59} 60