From 6bdfd1d1b14071e22d9b09fa5e526f715798c379 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Sat, 12 May 2012 21:55:57 -0400 Subject: [PATCH] A more idiomatic way of trying a non-blocking send on a buffered channel and falling back to a blocking send inside a goroutine. This really needs to be fixed. The situation only arises when events are sent and aren't pulled off the channel using {Wait,Poll}ForEvent. Namely, if the event send blocks, the entire program will deadlock. Using a goroutine is not ideal because we lose a guarantee of order: that events are processed in the order of their arrival. However, it seems OK as a temporary band-aide for a situation that probably doesn't arise too often. What I need to do is implement a dynamic queue. Here is a reference implementation: http://play.golang.org/p/AiHBsxTFpj --- nexgb/xgb.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nexgb/xgb.go b/nexgb/xgb.go index b2cf56c..c52f722 100644 --- a/nexgb/xgb.go +++ b/nexgb/xgb.go @@ -379,12 +379,14 @@ func (c *Conn) readResponses() { // FIXME: I'm not sure if using a goroutine here to guarantee // a non-blocking send is the right way to go. I should implement // a proper dynamic queue. - if cap(c.eventChan) == len(c.eventChan) { + // I am pretty sure this also loses a guarantee of events being + // processed in order of being received. + select { + case c.eventChan <- event: + default: go func() { c.eventChan <- event }() - } else { - c.eventChan <- event } // No more processing for events.