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 (
"os"
"strings"
"sync"
"sync/atomic"
"time"
"golang_org/x/net/lex/httplex"
......@@ -79,8 +80,8 @@ type Transport struct {
reqMu sync.Mutex
reqCanceler map[*Request]func(error)
altMu sync.RWMutex
altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
altMu sync.Mutex // guards changing altProto only
altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
// Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the
......@@ -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()
altRT := t.altProto[scheme]
t.altMu.RUnlock()
if altRT != nil {
altProto, _ := t.altProto.Load().(map[string]RoundTripper)
if altRT := altProto[scheme]; altRT != nil {
if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
return resp, err
}
......@@ -460,13 +459,16 @@ var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
t.altMu.Lock()
defer t.altMu.Unlock()
if t.altProto == nil {
t.altProto = make(map[string]RoundTripper)
}
if _, exists := t.altProto[scheme]; exists {
oldMap, _ := t.altProto.Load().(map[string]RoundTripper)
if _, exists := oldMap[scheme]; exists {
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
......
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