...
1
2
3
4
5
6
7 package netutil
8
9 import (
10 "net"
11 "sync"
12 )
13
14
15
16 func LimitListener(l net.Listener, n int) net.Listener {
17 return &limitListener{
18 Listener: l,
19 sem: make(chan struct{}, n),
20 done: make(chan struct{}),
21 }
22 }
23
24 type limitListener struct {
25 net.Listener
26 sem chan struct{}
27 closeOnce sync.Once
28 done chan struct{}
29 }
30
31
32
33
34 func (l *limitListener) acquire() bool {
35 select {
36 case <-l.done:
37 return false
38 case l.sem <- struct{}{}:
39 return true
40 }
41 }
42 func (l *limitListener) release() { <-l.sem }
43
44 func (l *limitListener) Accept() (net.Conn, error) {
45 if !l.acquire() {
46
47
48
49
50
51
52
53
54 for {
55 c, err := l.Listener.Accept()
56 if err != nil {
57 return nil, err
58 }
59 c.Close()
60 }
61 }
62
63 c, err := l.Listener.Accept()
64 if err != nil {
65 l.release()
66 return nil, err
67 }
68 return &limitListenerConn{Conn: c, release: l.release}, nil
69 }
70
71 func (l *limitListener) Close() error {
72 err := l.Listener.Close()
73 l.closeOnce.Do(func() { close(l.done) })
74 return err
75 }
76
77 type limitListenerConn struct {
78 net.Conn
79 releaseOnce sync.Once
80 release func()
81 }
82
83 func (l *limitListenerConn) Close() error {
84 err := l.Conn.Close()
85 l.releaseOnce.Do(l.release)
86 return err
87 }
88
View as plain text