github.com/searKing/golang/go@v1.2.117/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  //
    92  //	if ( wait_until(lck,abs_time) == cv_status::timeout)
    93  //	  return pred();
    94  //
    95  // return true;
    96  func (c *TimeoutCond) WaitUntilPred(d time.Time, pred func() bool) bool {
    97  	return c.cond.WaitUntilPred(c.L, d, pred)
    98  }
    99  
   100  // WaitContext wait until notified or time point
   101  // The execution of the current thread (which shall have locked lck's mutex) is blocked either
   102  // until notified or until ctx done, whichever happens first.
   103  func (c *TimeoutCond) WaitContext(ctx context.Context) error {
   104  	return c.cond.WaitContext(ctx, c.L)
   105  }
   106  
   107  // WaitPredContext wait until notified or ctx done
   108  // The execution of the current thread (which shall have locked lck's mutex) is blocked either
   109  // until notified or until ctx, whichever happens first.
   110  // If pred is nil, do as pred returns false always,
   111  // If pred is specified, the function only blocks if pred returns false,
   112  // and notifications can only unblock the thread when it becomes true
   113  // (which is especially useful to check against spurious wake-up calls).
   114  // It behaves as if implemented as:
   115  // while (!pred())
   116  //
   117  //	if ( wait_until(ctx,lck) == cv_status::timeout)
   118  //	  return pred();
   119  //
   120  // return true;
   121  func (c *TimeoutCond) WaitPredContext(ctx context.Context, pred func() bool) bool {
   122  	return c.cond.WaitPredContext(ctx, c.L, pred)
   123  }
   124  
   125  // Signal wakes one goroutine waiting on c, if there is any.
   126  //
   127  // It is allowed but not required for the caller to hold c.L
   128  // during the call.
   129  func (c *TimeoutCond) Signal() {
   130  	c.cond.Signal()
   131  }
   132  
   133  // Broadcast wakes all goroutines waiting on c.
   134  //
   135  // It is allowed but not required for the caller to hold c.L
   136  // during the call.
   137  func (c *TimeoutCond) Broadcast() {
   138  	c.cond.Broadcast()
   139  }