1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package semaphore_test 6 7import ( 8 "context" 9 "fmt" 10 "log" 11 "runtime" 12 13 "golang.org/x/sync/semaphore" 14) 15 16// Example_workerPool demonstrates how to use a semaphore to limit the number of 17// goroutines working on parallel tasks. 18// 19// This use of a semaphore mimics a typical “worker pool” pattern, but without 20// the need to explicitly shut down idle workers when the work is done. 21func Example_workerPool() { 22 ctx := context.TODO() 23 24 var ( 25 maxWorkers = runtime.GOMAXPROCS(0) 26 sem = semaphore.NewWeighted(int64(maxWorkers)) 27 out = make([]int, 32) 28 ) 29 30 // Compute the output using up to maxWorkers goroutines at a time. 31 for i := range out { 32 // When maxWorkers goroutines are in flight, Acquire blocks until one of the 33 // workers finishes. 34 if err := sem.Acquire(ctx, 1); err != nil { 35 log.Printf("Failed to acquire semaphore: %v", err) 36 break 37 } 38 39 go func(i int) { 40 defer sem.Release(1) 41 out[i] = collatzSteps(i + 1) 42 }(i) 43 } 44 45 // Acquire all of the tokens to wait for any remaining workers to finish. 46 // 47 // If you are already waiting for the workers by some other means (such as an 48 // errgroup.Group), you can omit this final Acquire call. 49 if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil { 50 log.Printf("Failed to acquire semaphore: %v", err) 51 } 52 53 fmt.Println(out) 54 55 // Output: 56 // [0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5] 57} 58 59// collatzSteps computes the number of steps to reach 1 under the Collatz 60// conjecture. (See https://en.wikipedia.org/wiki/Collatz_conjecture.) 61func collatzSteps(n int) (steps int) { 62 if n <= 0 { 63 panic("nonpositive input") 64 } 65 66 for ; n > 1; steps++ { 67 if steps < 0 { 68 panic("too many steps") 69 } 70 71 if n%2 == 0 { 72 n /= 2 73 continue 74 } 75 76 const maxInt = int(^uint(0) >> 1) 77 if n > (maxInt-1)/3 { 78 panic("overflow") 79 } 80 n = 3*n + 1 81 } 82 83 return steps 84} 85