github.com/searKing/golang/go@v1.2.117/time/rate/example_test.go (about) 1 package rate_test 2 3 import ( 4 "context" 5 "fmt" 6 "math/rand" 7 "runtime" 8 "sync" 9 "time" 10 11 "github.com/searKing/golang/go/time/rate" 12 ) 13 14 func ExampleNewReorderBuffer() { 15 const n = 10 16 // See https://web.archive.org/web/20040724215416/http://lgjohn.okstate.edu/6253/lectures/reorder.pdf for more about Reorder buffer. 17 limiter := rate.NewReorderBuffer() 18 ctx, cancel := context.WithTimeout(context.Background(), time.Hour) 19 defer cancel() 20 21 var wg sync.WaitGroup 22 23 for i := 0; i < n; i++ { 24 i := i 25 26 // Allocate: The dispatch stage reserves space in the reorder buffer for instructions in program order. 27 r := limiter.Reserve(ctx) 28 29 wg.Add(1) 30 go func() { 31 defer wg.Done() 32 // Execute out of order 33 runtime.Gosched() // Increase probability of a race for out-of-order mock 34 //fmt.Printf("%03d Execute out of order\n", i) 35 36 defer r.PutToken() 37 //fmt.Printf("%03d Wait until in order\n", i) 38 // Wait: The complete stage must wait for instructions to finish execution. 39 err := r.Wait(ctx) // Commit in order 40 if err != nil { 41 fmt.Printf("err: %s\n", err.Error()) 42 return 43 } 44 // Complete: Finished instructions are allowed to write results in order into the architected registers. 45 fmt.Printf("%03d Complete in order\n", i) 46 }() 47 } 48 wg.Wait() 49 // Output: 50 // 000 Complete in order 51 // 001 Complete in order 52 // 002 Complete in order 53 // 003 Complete in order 54 // 004 Complete in order 55 // 005 Complete in order 56 // 006 Complete in order 57 // 007 Complete in order 58 // 008 Complete in order 59 // 009 Complete in order 60 61 } 62 63 func ExampleNewFullBurstLimiter() { 64 const ( 65 burst = 3 66 ) 67 limiter := rate.NewFullBurstLimiter(burst) 68 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 69 defer cancel() 70 71 // expect dropped, as limiter is initialized with full tokens(3) 72 limiter.PutToken() 73 74 for i := 0; ; i++ { 75 // fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339)) 76 fmt.Printf("Wait %03d, tokens left: %d\n", i, limiter.Tokens()) 77 err := limiter.Wait(ctx) 78 if err != nil { 79 fmt.Printf("err: %s\n", err.Error()) 80 return 81 } 82 fmt.Printf("Got %03d, tokens left: %d\n", i, limiter.Tokens()) 83 84 // actor mocked by gc 85 runtime.GC() 86 87 if i == 0 { 88 // refill one token 89 limiter.PutToken() 90 } 91 } 92 // Output: 93 // Wait 000, tokens left: 3 94 // Got 000, tokens left: 2 95 // Wait 001, tokens left: 3 96 // Got 001, tokens left: 2 97 // Wait 002, tokens left: 2 98 // Got 002, tokens left: 1 99 // Wait 003, tokens left: 1 100 // Got 003, tokens left: 0 101 // Wait 004, tokens left: 0 102 // err: context deadline exceeded 103 } 104 105 func ExampleNewEmptyBurstLimiter() { 106 const ( 107 burst = 3 108 concurrency = 2 109 ) 110 limiter := rate.NewEmptyBurstLimiter(burst) 111 ctx, cancel := context.WithTimeout(context.Background(), time.Hour) 112 defer cancel() 113 114 fmt.Printf("tokens left: %d\n", limiter.Tokens()) 115 116 // expect not allowed, as limiter is initialized with empty tokens(0) 117 if limiter.Allow() { 118 fmt.Printf("allow passed\n") 119 } else { 120 fmt.Printf("allow refused\n") 121 } 122 // fill one token 123 limiter.PutToken() 124 fmt.Printf("tokens left: %d\n", limiter.Tokens()) 125 126 // expect allowed, as limiter is filled with one token(1) 127 if limiter.Allow() { 128 fmt.Printf("allow passed\n") 129 } else { 130 fmt.Printf("allow refused\n") 131 } 132 fmt.Printf("tokens left: %d\n", limiter.Tokens()) 133 134 var mu sync.Mutex 135 var wg sync.WaitGroup 136 for i := 0; i < concurrency; i++ { 137 wg.Add(1) 138 go func() { 139 defer wg.Done() 140 // fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339)) 141 mu.Lock() 142 fmt.Printf("Wait 1 Token, tokens left: %d\n", limiter.Tokens()) 143 mu.Unlock() 144 err := limiter.Wait(ctx) 145 if err != nil { 146 mu.Lock() 147 fmt.Printf("err: %s\n", err.Error()) 148 mu.Unlock() 149 return 150 } 151 152 mu.Lock() 153 fmt.Printf("Got 1 Token, tokens left: %d\n", limiter.Tokens()) 154 mu.Unlock() 155 }() 156 } 157 158 time.Sleep(10 * time.Millisecond) 159 for i := 0; i < concurrency; i++ { 160 time.Sleep(10 * time.Millisecond) 161 mu.Lock() 162 fmt.Printf("PutToken #%d: before tokens left: %d\n", i, limiter.Tokens()) 163 // fill one token 164 limiter.PutToken() 165 fmt.Printf("PutToken #%d: after tokens left: %d\n", i, limiter.Tokens()) 166 mu.Unlock() 167 } 168 wg.Wait() 169 fmt.Printf("tokens left: %d\n", limiter.Tokens()) 170 171 // expect allowed, as limiter is filled with one token(1) 172 if limiter.Allow() { 173 fmt.Printf("allow passed\n") 174 } else { 175 fmt.Printf("allow refused\n") 176 } 177 fmt.Printf("tokens left: %d\n", limiter.Tokens()) 178 179 // expect not allowed, as limiter is initialized with empty tokens(0) 180 if limiter.Allow() { 181 fmt.Printf("allow passed\n") 182 } else { 183 fmt.Printf("allow refused\n") 184 } 185 // Output: 186 // tokens left: 0 187 // allow refused 188 // tokens left: 1 189 // allow passed 190 // tokens left: 0 191 // Wait 1 Token, tokens left: 0 192 // Wait 1 Token, tokens left: 0 193 // PutToken #0: before tokens left: 0 194 // PutToken #0: after tokens left: 0 195 // Got 1 Token, tokens left: 0 196 // PutToken #1: before tokens left: 0 197 // PutToken #1: after tokens left: 0 198 // Got 1 Token, tokens left: 0 199 // tokens left: 0 200 // allow refused 201 // tokens left: 0 202 // allow refused 203 } 204 205 func ExampleBurstLimiter_Reserve() { 206 const ( 207 burst = 1 208 n = 10 209 ) 210 limiter := rate.NewFullBurstLimiter(burst) 211 ctx, cancel := context.WithTimeout(context.Background(), time.Hour) 212 defer cancel() 213 214 // expect dropped, as limiter is initialized with full tokens(1) 215 limiter.PutToken() 216 217 type Reservation struct { 218 index int 219 r *rate.Reservation 220 } 221 222 var mu sync.Mutex 223 var wg sync.WaitGroup 224 var rs []*Reservation 225 226 for i := 0; i < n; i++ { 227 // fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339)) 228 // fmt.Printf("Reserve %03d\n", i) 229 r := &Reservation{ 230 index: i, 231 r: limiter.Reserve(ctx), 232 } 233 if i%2 == rand.Intn(2)%2 { 234 rs = append(rs, r) 235 continue 236 } 237 wg.Add(1) 238 go func() { 239 defer wg.Done() 240 // fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339)) 241 // fmt.Printf("Wait %03d\n", r.index) 242 err := r.r.Wait(ctx) 243 if err != nil { 244 mu.Lock() 245 fmt.Printf("err: %s\n", err.Error()) 246 mu.Unlock() 247 } 248 249 mu.Lock() 250 fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens()) 251 mu.Unlock() 252 r.r.PutToken() 253 }() 254 } 255 256 for i := 0; i < len(rs); i++ { 257 r := rs[i] 258 wg.Add(1) 259 go func() { 260 defer wg.Done() 261 // fmt.Printf("%03d %s\n", r.index, time.Now().Format(time.RFC3339)) 262 // fmt.Printf("Wait %03d\n", r.index) 263 err := r.r.Wait(ctx) 264 if err != nil { 265 mu.Lock() 266 fmt.Printf("err: %s\n", err.Error()) 267 mu.Unlock() 268 } 269 270 mu.Lock() 271 fmt.Printf("%03d Got 1 Token, tokens left: %d\n", r.index, limiter.Tokens()) 272 mu.Unlock() 273 r.r.PutToken() 274 }() 275 } 276 wg.Wait() 277 // Output: 278 // 000 Got 1 Token, tokens left: 0 279 // 001 Got 1 Token, tokens left: 0 280 // 002 Got 1 Token, tokens left: 0 281 // 003 Got 1 Token, tokens left: 0 282 // 004 Got 1 Token, tokens left: 0 283 // 005 Got 1 Token, tokens left: 0 284 // 006 Got 1 Token, tokens left: 0 285 // 007 Got 1 Token, tokens left: 0 286 // 008 Got 1 Token, tokens left: 0 287 // 009 Got 1 Token, tokens left: 0 288 289 }