github.com/searKing/golang/go@v1.2.74/sync/cond.go (about) 1 // Copyright 2021 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sync 6 7 import ( 8 "context" 9 "sync" 10 "time" 11 ) 12 13 type TimeoutCond struct { 14 cond ConditionVariable 15 16 // L is held while observing or changing the condition 17 L sync.Locker 18 } 19 20 // NewTimeoutCond returns a new TimeoutCond with Locker l. 21 func NewTimeoutCond(l sync.Locker) *TimeoutCond { 22 return &TimeoutCond{L: l} 23 } 24 25 // Wait atomically unlocks c.L and suspends execution 26 // of the calling goroutine. After later resuming execution, 27 // Wait locks c.L before returning. Unlike in other systems, 28 // Wait cannot return unless awoken by Broadcast or Signal. 29 // 30 // Because c.L is not locked when Wait first resumes, the caller 31 // typically cannot assume that the condition is true when 32 // Wait returns. Instead, the caller should Wait in a loop: 33 // 34 // c.L.Lock() 35 // for !condition() { 36 // c.Wait() 37 // } 38 // ... make use of condition ... 39 // c.L.Unlock() 40 // 41 // Wait wait until notified 42 func (c *TimeoutCond) Wait() { 43 c.cond.Wait(c.L) 44 } 45 46 // WaitPred wait until notified 47 // If pred is specified (2), the function only blocks if pred returns false, 48 // and notifications can only unblock the thread when it becomes true 49 // (which is specially useful to check against spurious wake-up calls). This version (2) behaves as if implemented as: 50 // while (!pred()) wait(lck); 51 func (c *TimeoutCond) WaitPred(pred func() bool) { 52 c.cond.WaitPred(c.L, pred) 53 } 54 55 // WaitFor The execution of the current goroutine (which shall have locked lck's mutex) is blocked during rel_time, 56 // or until notified (if the latter happens first). 57 // WaitFor wait for timeout or until notified 58 // It behaves as if implemented as: 59 // return wait_until (lck, chrono::steady_clock::now() + rel_time); 60 func (c *TimeoutCond) WaitFor(timeout time.Duration) error { 61 return c.cond.WaitFor(c.L, timeout) 62 } 63 64 // WaitForPred wait for timeout or until notified 65 // If pred is nil, do as pred returns false always, 66 // If pred is specified, the function only blocks if pred returns false, 67 // and notifications can only unblock the thread when it becomes true 68 // (which is especially useful to check against spurious wake-up calls). 69 // It behaves as if implemented as: 70 // return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred)); 71 func (c *TimeoutCond) WaitForPred(timeout time.Duration, pred func() bool) bool { 72 return c.cond.WaitForPred(c.L, timeout, pred) 73 } 74 75 // WaitUntil wait until notified or time point 76 // The execution of the current thread (which shall have locked lck's mutex) is blocked either 77 // until notified or until abs_time, whichever happens first. 78 func (c *TimeoutCond) WaitUntil(d time.Time) error { 79 return c.cond.WaitUntil(c.L, d) 80 } 81 82 // WaitUntilPred wait until notified or time point 83 // The execution of the current thread (which shall have locked c.L's mutex) is blocked either 84 // until notified or until abs_time, whichever happens first. 85 // If pred is nil, do as pred returns false always, 86 // If pred is specified, the function only blocks if pred returns false, 87 // and notifications can only unblock the thread when it becomes true 88 // (which is especially useful to check against spurious wake-up calls). 89 // It behaves as if implemented as: 90 // while (!pred()) 91 // if ( wait_until(lck,abs_time) == cv_status::timeout) 92 // return pred(); 93 // return true; 94 func (c *TimeoutCond) WaitUntilPred(d time.Time, pred func() bool) bool { 95 return c.cond.WaitUntilPred(c.L, d, pred) 96 } 97 98 // WaitContext wait until notified or time point 99 // The execution of the current thread (which shall have locked lck's mutex) is blocked either 100 // until notified or until ctx done, whichever happens first. 101 func (c *TimeoutCond) WaitContext(ctx context.Context) error { 102 return c.cond.WaitContext(ctx, c.L) 103 } 104 105 // WaitPredContext wait until notified or ctx done 106 // The execution of the current thread (which shall have locked lck's mutex) is blocked either 107 // until notified or until ctx, whichever happens first. 108 // If pred is nil, do as pred returns false always, 109 // If pred is specified, the function only blocks if pred returns false, 110 // and notifications can only unblock the thread when it becomes true 111 // (which is especially useful to check against spurious wake-up calls). 112 // It behaves as if implemented as: 113 // while (!pred()) 114 // if ( wait_until(ctx,lck) == cv_status::timeout) 115 // return pred(); 116 // return true; 117 func (c *TimeoutCond) WaitPredContext(ctx context.Context, pred func() bool) bool { 118 return c.cond.WaitPredContext(ctx, c.L, pred) 119 } 120 121 // Signal wakes one goroutine waiting on c, if there is any. 122 // 123 // It is allowed but not required for the caller to hold c.L 124 // during the call. 125 func (c *TimeoutCond) Signal() { 126 c.cond.Signal() 127 } 128 129 // Broadcast wakes all goroutines waiting on c. 130 // 131 // It is allowed but not required for the caller to hold c.L 132 // during the call. 133 func (c *TimeoutCond) Broadcast() { 134 c.cond.Broadcast() 135 }