LCOV - code coverage report
Current view: directory - src/shared/platform/win - condition_variable.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 3 3 100.0 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : 
       8                 : // ConditionVariable is a reasonable attempt at simulating
       9                 : // the newer Posix and Vista-only construct for condition variable
      10                 : // synchronization.  This functionality is very helpful for having several
      11                 : // threads wait for an event, as is common with a thread pool
      12                 : // managed by a master.  The meaning of such an event in the
      13                 : // (worker) thread pool scenario is that additional tasks are
      14                 : // now available for processing.  It is used in Chrome in the
      15                 : // DNS prefetching system to notify worker threads that a queue
      16                 : // now has items (tasks) which need to be tended to.
      17                 : // A related use would have a pool manager waiting on a
      18                 : // ConditionVariable, waiting for a thread in the pool to announce
      19                 : // (signal) that there is now more room in a (bounded size) communications
      20                 : // queue for the manager to deposit tasks, or, as a second example, that
      21                 : // the queue of tasks is completely empty and all workers are waiting.
      22                 : 
      23                 : // USAGE NOTE 1: spurious signal events are possible with this and
      24                 : // most implementations of condition variables.  As a result, be
      25                 : // *sure* to retest your condition before proceeding.  The following
      26                 : // is a good example of doing this correctly:
      27                 : 
      28                 : // while (!work_to_be_done()) Wait(...);
      29                 : 
      30                 : // In contrast do NOT do the following:
      31                 : 
      32                 : // if (!work_to_be_done()) Wait(...);  // Don't do this.
      33                 : 
      34                 : // Especially avoid the above if you are relying on some other thread only
      35                 : // issuing a signal up *if* there is work-to-do.  There can/will
      36                 : // be spurious signals.  Recheck state on waiting thread before
      37                 : // assuming the signal was intentional. Caveat caller ;-).
      38                 : 
      39                 : // USAGE NOTE 2: Broadcast() frees up all waiting threads at once,
      40                 : // which leads to contention for the locks they all held when they
      41                 : // called Wait().  This results in POOR performance.  A much better
      42                 : // approach to getting a lot of threads out of Wait() is to have each
      43                 : // thread (upon exiting Wait()) call Signal() to free up another
      44                 : // Wait'ing thread.  Look at condition_variable_unittest.cc for
      45                 : // both examples.
      46                 : 
      47                 : // Broadcast() can be used nicely during teardown, as it gets the job
      48                 : // done, and leaves no sleeping threads... and performance is less
      49                 : // critical at that point.
      50                 : 
      51                 : // The semantics of Broadcast() are carefully crafted so that *all*
      52                 : // threads that were waiting when the request was made will indeed
      53                 : // get signaled.  Some implementations mess up, and don't signal them
      54                 : // all, while others allow the wait to be effectively turned off (for
      55                 : // for a while while waiting threads come around).  This implementation
      56                 : // appears correct, as it will not "lose" any signals, and will guarantee
      57                 : // that all threads get signaled by Broadcast().
      58                 : 
      59                 : // This implementation offers support for "performance" in its selection of
      60                 : // which thread to revive.  Performance, in direct contrast with "fairness,"
      61                 : // assures that the thread that most recently began to Wait() is selected by
      62                 : // Signal to revive.  Fairness would (if publicly supported) assure that the
      63                 : // thread that has Wait()ed the longest is selected. The default policy
      64                 : // may improve performance, as the selected thread may have a greater chance of
      65                 : // having some of its stack data in various CPU caches.  Although not publicly
      66                 : // available, internal support for "fairness" is used by the UnitTest harness
      67                 : // only on Windows to more thoroughly test the implementation.
      68                 : 
      69                 : // For many very subtle implementation details, see the condition_variable.cc.
      70                 : 
      71                 : // NOTE(gregoryd): changed the interface to allow providing the Lock reference
      72                 : // in Wait functions instead of the constructor.
      73                 : 
      74                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_CONDITION_VARIABLE_H_
      75                 : #define NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_CONDITION_VARIABLE_H_
      76                 : 
      77                 : 
      78                 : #include "native_client/src/shared/platform/win/time.h"
      79                 : #include "native_client/src/shared/platform/win/condition_variable_events.h"
      80                 : #include "native_client/src/shared/platform/win/lock.h"
      81                 : 
      82                 : namespace NaCl {
      83                 : 
      84                 : class Lock;
      85                 : 
      86                 : class ConditionVariable {
      87                 :  public:
      88                 :   // Construct a cv (our version allows to use the cv with different locks).
      89                 :   ConditionVariable();
      90                 : 
      91                 :   ~ConditionVariable();
      92                 : 
      93                 :   // Wait() releases the caller's critical section atomically as it starts to
      94                 :   // sleep, and the re-acquires it when it is signaled.
      95                 :   // We provide two variants of TimedWait:
      96                 :   // the first one takes relative time as an argument.
      97                 :   int TimedWaitRel(Lock& user_lock, TimeDelta max_time);
      98                 :   // The second TimedWait takes absolute time
      99                 :   int TimedWaitAbs(Lock& user_lock, TimeTicks abs_time);
     100               2 :   void Wait(Lock& user_lock) {
     101                 :     // Default to "wait forever" timing, which means have to get a Signal()
     102                 :     // or Broadcast() to come out of this wait state.
     103               2 :     TimedWaitRel(user_lock, TimeDelta::FromMilliseconds(INFINITE));
     104               2 :   }
     105                 : 
     106                 :   // Broadcast() revives all waiting threads.
     107                 :   void Broadcast();
     108                 :   // Signal() revives one waiting thread.
     109                 :   void Signal();
     110                 : 
     111                 :  private:
     112                 :   enum RunState { RUNNING = 64213, SHUTDOWN = 0 };
     113                 : 
     114                 :   // Internal implementation methods supporting Wait().
     115                 :   ConditionVariableEvent* GetEventForWaiting();
     116                 :   void RecycleEvent(ConditionVariableEvent* used_event);
     117                 : 
     118                 :   // Note that RUNNING is an unlikely number to have in RAM by accident.
     119                 :   // This helps with defensive destructor coding in the face of user error.
     120                 :   RunState run_state_;
     121                 : 
     122                 :   // Private critical section for access to member data.
     123                 :   Lock internal_lock_;
     124                 :   // Lock that is acquired before calling Wait().
     125                 :   // NOTE(gregoryd): Lock& user_lock_;-removed, see the note at top of file
     126                 : 
     127                 :   // Events that threads are blocked on.
     128                 :   ConditionVariableEvent waiting_list_;
     129                 : 
     130                 :   // Free list for old events.
     131                 :   ConditionVariableEvent recycling_list_;
     132                 :   int recycling_list_size_;
     133                 : 
     134                 :   // The number of allocated, but not yet deleted events.
     135                 :   int allocation_counter_;
     136                 : 
     137                 :   NACL_DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
     138                 : };
     139                 : 
     140                 : }  // namespace NaCl
     141                 : 
     142                 : #endif  // NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_CONDITION_VARIABLE_H_

Generated by: LCOV version 1.7