Armand Grillet
Armand Grillet

Reputation: 3399

Wait for a buffered channel to be full

I must have missed something because I haven't found the answer online for this pretty basic problem. I am using a buffered channel capable of holding three int values.

I am then using three goroutines to fill it up and I want to do an operation once the buffered channel is full.

Here is a snippet explaining the problem:

func main() {
    // Initialization of the slice a and 0 < n < len(a) - 1.
    difs := make(chan int, 3)
    go routine(a[:n], difs)
    go routine(a[n + 1:], difs)
    go routine(a[n - 1:n + 1], difs)

    fmt.Println(<-difs) // Display the first result returned by one of the routine.
}

func routine(a []int, out chan<- int) {
    // Long computation.
    out <- result
}

I would like to update my code so that fmt.Println(<-difs) displays an array of int when all the values have been computed. I could use three times <-difs but I wonder if Go offers something cleaner to do that.

Upvotes: 7

Views: 6458

Answers (2)

user6169399
user6169399

Reputation:

Wait using channel itself, like this working sample code:

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} // Initialization of the slice a and 0 < n < len(a) - 1.
    difs := make(chan int, 3)

    go routine(a[0:4], difs)
    go routine(a[4:8], difs)
    go routine(a[8:12], difs)

    result := []int{<-difs, <-difs, <-difs}

    fmt.Println(result) // Display the first result returned by one of the routine.
}

func routine(a []int, out chan<- int) {
    result := 0 // Long computation.
    for _, v := range a {
        result += v
    }
    out <- result
}

output:

[10 42 26]

Upvotes: 5

Kaedys
Kaedys

Reputation: 10158

The function len() supports channels, returning the number of unread queued elements within the channel. However, you'll have to run a loop to periodically check it.

The traditional method of handling this is using a sync.WaitGroup, as so:

func main() {
    // Initialization of the slice a and 0 < n < len(a) - 1.
    var wg sync.WaitGroup
    wg.Add(3)
    difs := make(chan int, 3)
    go routine(a[:n], difs, &wg)
    go routine(a[n + 1:], difs, &wg)
    go routine(n - 1:n + 1], difs, &wg)

    wg.Wait() // blocks until wg.Done() is called 3 times
    fmt.Println(<-difs) // Display the first result returned by one of the routine.
}

// NOTE: This MUST accept a POINTER to the waitgroup.  They are not copy-safe.
func routine(a []int, out chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    // Long computation.
    out <- result
}

Upvotes: 6

Related Questions