github.com/luckypickle/go-ethereum-vet@v1.14.2/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/luckypickle/go-ethereum-vet/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  }