Guest User

Untitled

a guest
Dec 13th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.13 KB | None | 0 0
  1. package gopool
  2.  
  3. import "sync"
  4.  
  5. // GoPool is a pool of goroutines with error reporting.
  6. type GoPool struct {
  7. waitGroup sync.WaitGroup
  8. errors chan error
  9. }
  10.  
  11. // New initializes a new GoPool.
  12. func New() *GoPool {
  13. return &GoPool{
  14. waitGroup: sync.WaitGroup{},
  15. errors: make(chan error),
  16. }
  17. }
  18.  
  19. // Run runs the specified function in a goroutine, collecting any errors that might occur.
  20. func (p *GoPool) Run(goFuncs ...func() error) {
  21. p.waitGroup.Add(len(goFuncs))
  22. for _, goFunc := range goFuncs {
  23. goFunc := goFunc
  24. go func() {
  25. defer p.waitGroup.Done()
  26. err := goFunc()
  27. if err != nil {
  28. p.errors <- err
  29. }
  30. }()
  31. }
  32. }
  33.  
  34. // Wait waits for all specified tasks in the GoPoo to complete, and returns any collected errors that occurred.
  35. func (p *GoPool) Wait() (errors []error) {
  36. go func() {
  37. p.waitGroup.Wait()
  38. close(p.errors)
  39. }()
  40. for err := range p.errors {
  41. errors = append(errors, err)
  42. }
  43. return errors
  44. }
  45.  
  46. func DoThings() {
  47. var thingA int
  48. var thingB string
  49. var thingC *Thing
  50.  
  51. pool := gopool.New()
  52. pool.Run(func() (err error) {
  53. thingA, err = FetchThingA()
  54. return err
  55. })
  56. pool.Run(func() (err error) {
  57. thingB = FetchThingB()
  58. return nil
  59. })
  60. pool.Run(func() (err error) {
  61. thingC, err = FetchThingC()
  62. return err
  63. })
  64. errs := pool.Wait()
  65. if len(errs) > 0 {
  66. // Handle errs
  67. }
  68. // Use each of the fetched things
  69. }
  70.  
  71. toRun := []func() error{}
  72. toRun = append(toRun, func() error{fmt.Println("one"); return nil});
  73. ....
  74. errors := pool.Run(toRun...)
  75.  
  76. // Run will run all the supplied functions in separate Go-routines, and return any errors in the resulting slice,
  77. // and also return a boolen ok indicator which will be true if all goroutines succeeded.
  78. func Run(toRun ...func() error) ([]error, bool) {
  79.  
  80. count := len(toRun)
  81. var wg sync.WaitGroup
  82. wg.Add(count)
  83. errors := make([]error, count, count)
  84. ok := true
  85. for i, fn := range toRun {
  86. // create a closure for the error index and the function
  87. go func(index int, fn func() error) {
  88. defer wg.Done()
  89. errors[index] = fn()
  90. }(i, fn)
  91. }
  92. wg.Wait()
  93. for _, e := range errors {
  94. if e != nil {
  95. ok = false
  96. }
  97. }
  98. return errors, ok
  99. }
  100.  
  101. func main() {
  102.  
  103. runs := []func() error{}
  104.  
  105. runs = append(runs, func() error {
  106. fmt.Println("one")
  107. return nil
  108. })
  109. runs = append(runs, func() error {
  110. fmt.Println("two")
  111. return nil
  112. })
  113. runs = append(runs, func() error {
  114. fmt.Println("three")
  115. return nil
  116. })
  117.  
  118. fmt.Println("Run one")
  119. if errs, ok := Run(runs...); !ok {
  120. fmt.Printf("Some errors: %vn", errs)
  121. } else {
  122. fmt.Println("OK")
  123. }
  124.  
  125. runs = append(runs, func() error {
  126. fmt.Println("fail")
  127. return errors.New("Failed")
  128. })
  129.  
  130. fmt.Println("Run Two")
  131. if errs, ok := Run(runs...); !ok {
  132. fmt.Printf("Some errors: %vn", errs)
  133. } else {
  134. fmt.Println("OK")
  135. }
  136.  
  137. }
Add Comment
Please, Sign In to add comment