listen.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package netutil provides network utility functions, complementing the more
  5. // common ones in the net package.
  6. package netutil // import "golang.org/x/net/netutil"
  7. import (
  8. "net"
  9. "sync"
  10. )
  11. // LimitListener returns a Listener that accepts at most n simultaneous
  12. // connections from the provided Listener.
  13. func LimitListener(l net.Listener, n int) net.Listener {
  14. return &limitListener{
  15. Listener: l,
  16. sem: make(chan struct{}, n),
  17. done: make(chan struct{}),
  18. }
  19. }
  20. type limitListener struct {
  21. net.Listener
  22. sem chan struct{}
  23. closeOnce sync.Once // ensures the done chan is only closed once
  24. done chan struct{} // no values sent; closed when Close is called
  25. }
  26. // acquire acquires the limiting semaphore. Returns true if successfully
  27. // accquired, false if the listener is closed and the semaphore is not
  28. // acquired.
  29. func (l *limitListener) acquire() bool {
  30. select {
  31. case <-l.done:
  32. return false
  33. case l.sem <- struct{}{}:
  34. return true
  35. }
  36. }
  37. func (l *limitListener) release() { <-l.sem }
  38. func (l *limitListener) Accept() (net.Conn, error) {
  39. acquired := l.acquire()
  40. // If the semaphore isn't acquired because the listener was closed, expect
  41. // that this call to accept won't block, but immediately return an error.
  42. c, err := l.Listener.Accept()
  43. if err != nil {
  44. if acquired {
  45. l.release()
  46. }
  47. return nil, err
  48. }
  49. return &limitListenerConn{Conn: c, release: l.release}, nil
  50. }
  51. func (l *limitListener) Close() error {
  52. err := l.Listener.Close()
  53. l.closeOnce.Do(func() { close(l.done) })
  54. return err
  55. }
  56. type limitListenerConn struct {
  57. net.Conn
  58. releaseOnce sync.Once
  59. release func()
  60. }
  61. func (l *limitListenerConn) Close() error {
  62. err := l.Conn.Close()
  63. l.releaseOnce.Do(l.release)
  64. return err
  65. }