diff options
Diffstat (limited to 'vendor/google.golang.org/appengine/internal/net.go')
-rw-r--r-- | vendor/google.golang.org/appengine/internal/net.go | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/vendor/google.golang.org/appengine/internal/net.go b/vendor/google.golang.org/appengine/internal/net.go new file mode 100644 index 0000000..3b94cf0 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/net.go | |||
@@ -0,0 +1,56 @@ | |||
1 | // Copyright 2014 Google Inc. All rights reserved. | ||
2 | // Use of this source code is governed by the Apache 2.0 | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package internal | ||
6 | |||
7 | // This file implements a network dialer that limits the number of concurrent connections. | ||
8 | // It is only used for API calls. | ||
9 | |||
10 | import ( | ||
11 | "log" | ||
12 | "net" | ||
13 | "runtime" | ||
14 | "sync" | ||
15 | "time" | ||
16 | ) | ||
17 | |||
18 | var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable. | ||
19 | |||
20 | func limitRelease() { | ||
21 | // non-blocking | ||
22 | select { | ||
23 | case <-limitSem: | ||
24 | default: | ||
25 | // This should not normally happen. | ||
26 | log.Print("appengine: unbalanced limitSem release!") | ||
27 | } | ||
28 | } | ||
29 | |||
30 | func limitDial(network, addr string) (net.Conn, error) { | ||
31 | limitSem <- 1 | ||
32 | |||
33 | // Dial with a timeout in case the API host is MIA. | ||
34 | // The connection should normally be very fast. | ||
35 | conn, err := net.DialTimeout(network, addr, 500*time.Millisecond) | ||
36 | if err != nil { | ||
37 | limitRelease() | ||
38 | return nil, err | ||
39 | } | ||
40 | lc := &limitConn{Conn: conn} | ||
41 | runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required | ||
42 | return lc, nil | ||
43 | } | ||
44 | |||
45 | type limitConn struct { | ||
46 | close sync.Once | ||
47 | net.Conn | ||
48 | } | ||
49 | |||
50 | func (lc *limitConn) Close() error { | ||
51 | defer lc.close.Do(func() { | ||
52 | limitRelease() | ||
53 | runtime.SetFinalizer(lc, nil) | ||
54 | }) | ||
55 | return lc.Conn.Close() | ||
56 | } | ||