-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
oh momma. a lot of modifications and it appears to be working. w00t.
- Loading branch information
Andrew Gallant (Ocelot)
authored and
Andrew Gallant (Ocelot)
committed
May 5, 2012
1 parent
6ed03ad
commit b8d96bc
Showing
3 changed files
with
3,359 additions
and
1,348 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package xgb | ||
|
||
import ( | ||
"errors" | ||
) | ||
|
||
type cookie struct { | ||
Sequence uint16 | ||
replyChan chan []byte | ||
errorChan chan error | ||
pingChan chan bool | ||
} | ||
|
||
func (c *Conn) newCookie(checked, reply bool) cookie { | ||
cookie := cookie{ | ||
Sequence: c.newSequenceId(), | ||
replyChan: nil, | ||
errorChan: nil, | ||
pingChan: nil, | ||
} | ||
|
||
// There are four different kinds of cookies: | ||
// Checked requests with replies get a reply channel and an error channel. | ||
// Unchecked requests with replies get a reply channel and a ping channel. | ||
// Checked requests w/o replies get a ping channel and an error channel. | ||
// Unchecked requests w/o replies get no channels. | ||
// The reply channel is used to send reply data. | ||
// The error channel is used to send error data. | ||
// The ping channel is used when one of the 'reply' or 'error' channels | ||
// is missing but the other is present. The ping channel is way to force | ||
// the blocking to stop and basically say "the error has been received | ||
// in the main event loop" (when the ping channel is coupled with a reply | ||
// channel) or "the request you made that has no reply was successful" | ||
// (when the ping channel is coupled with an error channel). | ||
if checked { | ||
cookie.errorChan = make(chan error, 1) | ||
if !reply { | ||
cookie.pingChan = make(chan bool, 1) | ||
} | ||
} | ||
if reply { | ||
cookie.replyChan = make(chan []byte, 1) | ||
if !checked { | ||
cookie.pingChan = make(chan bool, 1) | ||
} | ||
} | ||
|
||
return cookie | ||
} | ||
|
||
func (c cookie) reply() ([]byte, error) { | ||
// checked | ||
if c.errorChan != nil { | ||
return c.replyChecked() | ||
} | ||
return c.replyUnchecked() | ||
} | ||
|
||
func (c cookie) replyChecked() ([]byte, error) { | ||
if c.replyChan == nil { | ||
return nil, errors.New("Cannot call 'replyChecked' on a cookie that " + | ||
"is not expecting a *reply* or an error.") | ||
} | ||
if c.errorChan == nil { | ||
return nil, errors.New("Cannot call 'replyChecked' on a cookie that " + | ||
"is not expecting a reply or an *error*.") | ||
} | ||
|
||
select { | ||
case reply := <-c.replyChan: | ||
return reply, nil | ||
case err := <-c.errorChan: | ||
return nil, err | ||
} | ||
panic("unreachable") | ||
} | ||
|
||
func (c cookie) replyUnchecked() ([]byte, error) { | ||
if c.replyChan == nil { | ||
return nil, errors.New("Cannot call 'replyUnchecked' on a cookie " + | ||
"that is not expecting a *reply*.") | ||
} | ||
|
||
select { | ||
case reply := <-c.replyChan: | ||
return reply, nil | ||
case <-c.pingChan: | ||
return nil, nil | ||
} | ||
panic("unreachable") | ||
} | ||
|
||
func (c cookie) Check() error { | ||
if c.replyChan != nil { | ||
return errors.New("Cannot call 'Check' on a cookie that is " + | ||
"expecting a *reply*. Use 'Reply' instead.") | ||
} | ||
if c.errorChan == nil { | ||
return errors.New("Cannot call 'Check' on a cookie that is " + | ||
"not expecting a possible *error*.") | ||
} | ||
|
||
select { | ||
case err := <-c.errorChan: | ||
return err | ||
case <-c.pingChan: | ||
return nil | ||
} | ||
panic("unreachable") | ||
} | ||
|
Oops, something went wrong.