tags:

views:

79

answers:

1

So, right now, I just pass a pointer to a Queue object (implementation doesn't really matter) and call queue.add(result) at the end of goroutines that should add things to the queue.

I need that same sort of functionality—and of course doing a loop checking completion with the comma ok syntax is unacceptable in terms of performance versus the simple queue add function call.

Is there a way to do this better, or not?

+1  A: 

There are actually two parts to your question: how does one queue data in Go, and how does one use a channel without blocking.

For the first part, it sounds like what you need to do is instead of using the channel to add things to the queue, use the channel as a queue. For example:

var (
    ch = make(chan int) // You can add an int parameter to this make call to create a buffered channel

    // Do not buffer these channels!
    gFinished = make(chan bool)
    processFinished = make(chan bool)
)
func f() {
    go g()
    for {
        // send values over ch here...
    }
    <-gFinished
    close(ch)
}
func g() {
    // create more expensive objects...
    gFinished <- true
}
func processObjects() {
    for val := range ch {
        // Process each val here
    }
    processFinished <- true
}
func main() {
    go processObjects()
    f()
    <-processFinished
}

As for how you can make this more asynchronous, you can (as cthom06 pointed out) pass a second integer to the make call in the second line which will make send operations asynchronous until the channel's buffer is full.

EDIT: However (as cthom06 also pointed out), because you have two goroutines writing to the channel, one of them has to be responsible for closing the channel. Also, my previous revision would exit before processObjects could complete. The way I chose to synchronize the goroutines is by creating a couple more channels that pass around dummy values to ensure that the cleanup gets finished properly. Those channels are specifically unbuffered so that the sends happen in lock-step.

Quartz
This code will exit immediately after f() is called in main(), processObjects() should run in main(), and probably not use range.
cthom06
I misread, the program won't exit until f() returns, but that still doesn't guarantee that processObjects() is finished (actually, if the channel is buffered it's almost certain it won't finish). In main(), it should be go f(); processObjects(). And the range is still a problem, since the program will hang waiting for more values on ch.
cthom06
You are correct. I'll fix the code.
Quartz