4949// an implementation of http.RoundTripper for the convenience of callers.
5050type fronted struct {
5151 certPool atomic.Value
52- fronts sortedFronts
52+ fronts * threadSafeFronts
5353 maxAllowedCachedAge time.Duration
5454 maxCacheSize int
5555 cacheFile string
@@ -102,7 +102,7 @@ func NewFronted(options ...Option) Fronted {
102102
103103 f := & fronted {
104104 certPool : atomic.Value {},
105- fronts : make ( sortedFronts , 0 ),
105+ fronts : newThreadSafeFronts ( 0 ),
106106 maxAllowedCachedAge : defaultMaxAllowedCachedAge ,
107107 maxCacheSize : defaultMaxCacheSize ,
108108 cacheSaveInterval : defaultCacheSaveInterval ,
@@ -260,7 +260,7 @@ func (f *fronted) onNewFronts(pool *x509.CertPool, providers map[string]*Provide
260260 }
261261 providersCopy := copyProviders (providers , f .countryCode )
262262 f .addProviders (providersCopy )
263- f .addFronts (loadFronts (providersCopy , f .cacheDirty ))
263+ f .fronts . addFronts (loadFronts (providersCopy , f .cacheDirty )... )
264264 f .certPool .Store (pool )
265265
266266 // The goroutine for finding working fronts runs forever, so only start it once.
@@ -320,8 +320,8 @@ func (f *fronted) tryAllFronts() {
320320 pool := pond .NewPool (40 )
321321
322322 // Submit all fronts to the worker pool.
323- for i := range f .frontSize () {
324- m := f .frontAt (i )
323+ for i := range f .fronts . frontSize () {
324+ m := f .fronts . frontAt (i )
325325 pool .Submit (func () {
326326 if f .isStopped () {
327327 return
@@ -348,18 +348,6 @@ func (f *fronted) hasEnoughWorkingFronts() bool {
348348 return len (f .frontsCh ) >= 4
349349}
350350
351- func (f * fronted ) frontSize () int {
352- f .frontsMu .RLock ()
353- defer f .frontsMu .RUnlock ()
354- return len (f .fronts )
355- }
356-
357- func (f * fronted ) frontAt (i int ) Front {
358- f .frontsMu .RLock ()
359- defer f .frontsMu .RUnlock ()
360- return f .fronts [i ]
361- }
362-
363351func (f * fronted ) vetFront (fr Front ) bool {
364352 conn , err := f .dialFront (fr )
365353 if err != nil {
@@ -571,7 +559,7 @@ func copyProviders(providers map[string]*Provider, countryCode string) map[strin
571559 return providersCopy
572560}
573561
574- func loadFronts (providers map [string ]* Provider , cacheDirty chan interface {}) sortedFronts {
562+ func loadFronts (providers map [string ]* Provider , cacheDirty chan interface {}) [] Front {
575563 log .Debugf ("Loading candidates for %d providers" , len (providers ))
576564 defer log .Debug ("Finished loading candidates" )
577565
@@ -581,7 +569,7 @@ func loadFronts(providers map[string]*Provider, cacheDirty chan interface{}) sor
581569 size += len (p .Masquerades )
582570 }
583571
584- fronts := make (sortedFronts , size )
572+ fronts := make ([] Front , size )
585573
586574 // Note that map iteration order is random, so the order of the providers is automatically randomized.
587575 index := 0
@@ -616,13 +604,6 @@ func (f *fronted) addProviders(providers map[string]*Provider) {
616604 }
617605}
618606
619- func (f * fronted ) addFronts (fronts sortedFronts ) {
620- // Add new masquerades to the existing masquerades slice, but add them at the beginning.
621- f .frontsMu .Lock ()
622- defer f .frontsMu .Unlock ()
623- f .fronts = append (fronts , f .fronts .sortedCopy ()... )
624- }
625-
626607func (f * fronted ) providerFor (m Front ) * Provider {
627608 pid := m .getProviderID ()
628609 if pid == "" {
0 commit comments