github.com/fxsjy/go-ethereum@v1.8.4-0.20180410143526-2e247705cd27/event/example_scope_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package event_test 18 19 import ( 20 "fmt" 21 "sync" 22 23 "github.com/ethereum/go-ethereum/event" 24 ) 25 26 // This example demonstrates how SubscriptionScope can be used to control the lifetime of 27 // subscriptions. 28 // 29 // Our example program consists of two servers, each of which performs a calculation when 30 // requested. The servers also allow subscribing to results of all computations. 31 type divServer struct{ results event.Feed } 32 type mulServer struct{ results event.Feed } 33 34 func (s *divServer) do(a, b int) int { 35 r := a / b 36 s.results.Send(r) 37 return r 38 } 39 40 func (s *mulServer) do(a, b int) int { 41 r := a * b 42 s.results.Send(r) 43 return r 44 } 45 46 // The servers are contained in an App. The app controls the servers and exposes them 47 // through its API. 48 type App struct { 49 divServer 50 mulServer 51 scope event.SubscriptionScope 52 } 53 54 func (s *App) Calc(op byte, a, b int) int { 55 switch op { 56 case '/': 57 return s.divServer.do(a, b) 58 case '*': 59 return s.mulServer.do(a, b) 60 default: 61 panic("invalid op") 62 } 63 } 64 65 // The app's SubscribeResults method starts sending calculation results to the given 66 // channel. Subscriptions created through this method are tied to the lifetime of the App 67 // because they are registered in the scope. 68 func (s *App) SubscribeResults(op byte, ch chan<- int) event.Subscription { 69 switch op { 70 case '/': 71 return s.scope.Track(s.divServer.results.Subscribe(ch)) 72 case '*': 73 return s.scope.Track(s.mulServer.results.Subscribe(ch)) 74 default: 75 panic("invalid op") 76 } 77 } 78 79 // Stop stops the App, closing all subscriptions created through SubscribeResults. 80 func (s *App) Stop() { 81 s.scope.Close() 82 } 83 84 func ExampleSubscriptionScope() { 85 // Create the app. 86 var ( 87 app App 88 wg sync.WaitGroup 89 divs = make(chan int) 90 muls = make(chan int) 91 ) 92 93 // Run a subscriber in the background. 94 divsub := app.SubscribeResults('/', divs) 95 mulsub := app.SubscribeResults('*', muls) 96 wg.Add(1) 97 go func() { 98 defer wg.Done() 99 defer fmt.Println("subscriber exited") 100 defer divsub.Unsubscribe() 101 defer mulsub.Unsubscribe() 102 for { 103 select { 104 case result := <-divs: 105 fmt.Println("division happened:", result) 106 case result := <-muls: 107 fmt.Println("multiplication happened:", result) 108 case <-divsub.Err(): 109 return 110 case <-mulsub.Err(): 111 return 112 } 113 } 114 }() 115 116 // Interact with the app. 117 app.Calc('/', 22, 11) 118 app.Calc('*', 3, 4) 119 120 // Stop the app. This shuts down the subscriptions, causing the subscriber to exit. 121 app.Stop() 122 wg.Wait() 123 124 // Output: 125 // division happened: 2 126 // multiplication happened: 12 127 // subscriber exited 128 }