summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/braintree/manners/listener.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/braintree/manners/listener.go')
-rw-r--r--Godeps/_workspace/src/github.com/braintree/manners/listener.go49
1 files changed, 49 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/braintree/manners/listener.go b/Godeps/_workspace/src/github.com/braintree/manners/listener.go
new file mode 100644
index 000000000..dd84e4a2e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/braintree/manners/listener.go
@@ -0,0 +1,49 @@
+package manners
+
+import (
+ "net"
+ "sync"
+)
+
+func NewListener(l net.Listener, s *GracefulServer) *GracefulListener {
+ return &GracefulListener{l, true, s, sync.RWMutex{}}
+}
+
+// A GracefulListener differs from a standard net.Listener in one way: if
+// Accept() is called after it is gracefully closed, it returns a
+// listenerAlreadyClosed error. The GracefulServer will ignore this
+// error.
+type GracefulListener struct {
+ net.Listener
+ open bool
+ server *GracefulServer
+ rw sync.RWMutex
+}
+
+func (l *GracefulListener) Accept() (net.Conn, error) {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ l.rw.RLock()
+ defer l.rw.RUnlock()
+ if !l.open {
+ err = listenerAlreadyClosed{err}
+ }
+ return nil, err
+ }
+ return conn, nil
+}
+
+func (l *GracefulListener) Close() error {
+ l.rw.Lock()
+ defer l.rw.Unlock()
+ if !l.open {
+ return nil
+ }
+ l.open = false
+ err := l.Listener.Close()
+ return err
+}
+
+type listenerAlreadyClosed struct {
+ error
+}