Commit c1e06dcb authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: use atomic.Value for Transport's alternate protocol map

Fix an old TODO and use atomic.Value for holding the Transport's
alternate protocol map. It is very frequently accessed and almost
never set or updated.

Change-Id: Ic5a71c504bdac76678114c6390d1fc0673e07aa9
Reviewed-on: https://go-review.googlesource.com/29967
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 8e69d43b
...@@ -25,6 +25,7 @@ import ( ...@@ -25,6 +25,7 @@ import (
"os" "os"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"golang_org/x/net/lex/httplex" "golang_org/x/net/lex/httplex"
...@@ -79,8 +80,8 @@ type Transport struct { ...@@ -79,8 +80,8 @@ type Transport struct {
reqMu sync.Mutex reqMu sync.Mutex
reqCanceler map[*Request]func(error) reqCanceler map[*Request]func(error)
altMu sync.RWMutex altMu sync.Mutex // guards changing altProto only
altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
// Proxy specifies a function to return a proxy for a given // Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the // Request. If the function returns a non-nil error, the
...@@ -331,11 +332,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) { ...@@ -331,11 +332,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
} }
} }
} }
// TODO(bradfitz): switch to atomic.Value for this map instead of RWMutex
t.altMu.RLock() altProto, _ := t.altProto.Load().(map[string]RoundTripper)
altRT := t.altProto[scheme] if altRT := altProto[scheme]; altRT != nil {
t.altMu.RUnlock()
if altRT != nil {
if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol { if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
return resp, err return resp, err
} }
...@@ -460,13 +459,16 @@ var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol") ...@@ -460,13 +459,16 @@ var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) { func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
t.altMu.Lock() t.altMu.Lock()
defer t.altMu.Unlock() defer t.altMu.Unlock()
if t.altProto == nil { oldMap, _ := t.altProto.Load().(map[string]RoundTripper)
t.altProto = make(map[string]RoundTripper) if _, exists := oldMap[scheme]; exists {
}
if _, exists := t.altProto[scheme]; exists {
panic("protocol " + scheme + " already registered") panic("protocol " + scheme + " already registered")
} }
t.altProto[scheme] = rt newMap := make(map[string]RoundTripper)
for k, v := range oldMap {
newMap[k] = v
}
newMap[scheme] = rt
t.altProto.Store(newMap)
} }
// CloseIdleConnections closes any connections which were previously // CloseIdleConnections closes any connections which were previously
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment