diff options
| author | Andrew Gallant (Ocelot) <Andrew.Gallant@tufts.edu> | 2012-05-12 21:55:57 -0400 | 
|---|---|---|
| committer | Andrew Gallant (Ocelot) <Andrew.Gallant@tufts.edu> | 2012-05-12 21:55:57 -0400 | 
| commit | 6bdfd1d1b14071e22d9b09fa5e526f715798c379 (patch) | |
| tree | 5b700755492ffddc295e2d73aaa18911e0a42d9e | |
| parent | 7abc9c6455b8281d5dfd5604ec6ca6fe0d459318 (diff) | |
| download | haven-6bdfd1d1b14071e22d9b09fa5e526f715798c379.tar.gz haven-6bdfd1d1b14071e22d9b09fa5e526f715798c379.tar.xz haven-6bdfd1d1b14071e22d9b09fa5e526f715798c379.zip | |
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
| -rw-r--r-- | nexgb/xgb.go | 8 | 
1 files 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. | 
