...

Source file src/golang.org/x/sync/semaphore/semaphore_example_test.go

Documentation: golang.org/x/sync/semaphore

     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  
     5  package semaphore_test
     6  
     7  import (
     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.
    21  func 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.)
    61  func 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  

View as plain text