github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/wrr/random.go (about) 1 /* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package wrr 19 20 import ( 21 "fmt" 22 "sync" 23 24 "github.com/hxx258456/ccgo/grpc/internal/grpcrand" 25 ) 26 27 // weightedItem is a wrapped weighted item that is used to implement weighted random algorithm. 28 type weightedItem struct { 29 Item interface{} 30 Weight int64 31 } 32 33 func (w *weightedItem) String() string { 34 return fmt.Sprint(*w) 35 } 36 37 // randomWRR is a struct that contains weighted items implement weighted random algorithm. 38 type randomWRR struct { 39 mu sync.RWMutex 40 items []*weightedItem 41 sumOfWeights int64 42 } 43 44 // NewRandom creates a new WRR with random. 45 func NewRandom() WRR { 46 return &randomWRR{} 47 } 48 49 var grpcrandInt63n = grpcrand.Int63n 50 51 func (rw *randomWRR) Next() (item interface{}) { 52 rw.mu.RLock() 53 defer rw.mu.RUnlock() 54 if rw.sumOfWeights == 0 { 55 return nil 56 } 57 // Random number in [0, sum). 58 randomWeight := grpcrandInt63n(rw.sumOfWeights) 59 for _, item := range rw.items { 60 randomWeight = randomWeight - item.Weight 61 if randomWeight < 0 { 62 return item.Item 63 } 64 } 65 66 return rw.items[len(rw.items)-1].Item 67 } 68 69 func (rw *randomWRR) Add(item interface{}, weight int64) { 70 rw.mu.Lock() 71 defer rw.mu.Unlock() 72 rItem := &weightedItem{Item: item, Weight: weight} 73 rw.items = append(rw.items, rItem) 74 rw.sumOfWeights += weight 75 } 76 77 func (rw *randomWRR) String() string { 78 return fmt.Sprint(rw.items) 79 }