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  }