Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "condition_variable_posix.h"
     12 
     13 #if defined(WEBRTC_LINUX)
     14 #include <ctime>
     15 #else
     16 #include <sys/time.h>
     17 #endif
     18 
     19 #include <errno.h>
     20 
     21 #include "critical_section_posix.h"
     22 
     23 namespace webrtc {
     24 ConditionVariableWrapper* ConditionVariablePosix::Create()
     25 {
     26     ConditionVariablePosix* ptr = new ConditionVariablePosix;
     27     if (!ptr)
     28     {
     29         return NULL;
     30     }
     31 
     32     const int error = ptr->Construct();
     33     if (error)
     34     {
     35         delete ptr;
     36         return NULL;
     37     }
     38 
     39     return ptr;
     40 }
     41 
     42 ConditionVariablePosix::ConditionVariablePosix()
     43 {
     44 }
     45 
     46 int ConditionVariablePosix::Construct()
     47 {
     48     int result = 0;
     49 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
     50     result = pthread_cond_init(&_cond, NULL);
     51 #else
     52     pthread_condattr_t condAttr;
     53     result = pthread_condattr_init(&condAttr);
     54     if (result != 0)
     55     {
     56         return -1;
     57     }
     58     result = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
     59     if (result != 0)
     60     {
     61         return -1;
     62     }
     63     result = pthread_cond_init(&_cond, &condAttr);
     64     if (result != 0)
     65     {
     66         return -1;
     67     }
     68     result = pthread_condattr_destroy(&condAttr);
     69     if (result != 0)
     70     {
     71         return -1;
     72     }
     73 #endif
     74     return 0;
     75 }
     76 
     77 ConditionVariablePosix::~ConditionVariablePosix()
     78 {
     79     pthread_cond_destroy(&_cond);
     80 }
     81 
     82 void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& critSect)
     83 {
     84     CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
     85                                    &critSect);
     86     pthread_cond_wait(&_cond, &cs->_mutex);
     87 }
     88 
     89 
     90 bool
     91 ConditionVariablePosix::SleepCS(
     92     CriticalSectionWrapper& critSect,
     93     unsigned long maxTimeInMS)
     94 {
     95     const unsigned long INFINITE =  0xFFFFFFFF;
     96 
     97     const int MILLISECONDS_PER_SECOND      = 1000;
     98 #ifndef WEBRTC_LINUX
     99     const int MICROSECONDS_PER_MILLISECOND = 1000;
    100 #endif
    101     const int NANOSECONDS_PER_SECOND       = 1000000000;
    102     const int NANOSECONDS_PER_MILLISECOND  = 1000000;
    103 
    104     CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
    105                                    &critSect);
    106 
    107     if (maxTimeInMS != INFINITE)
    108     {
    109         timespec ts;
    110 #ifndef WEBRTC_MAC
    111 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
    112         clock_gettime(CLOCK_REALTIME, &ts);
    113 #else
    114         clock_gettime(CLOCK_MONOTONIC, &ts);
    115 #endif
    116 #else
    117         struct timeval tv;
    118         gettimeofday(&tv, 0);
    119         ts.tv_sec  = tv.tv_sec;
    120         ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
    121 #endif
    122 
    123         ts.tv_sec += maxTimeInMS / MILLISECONDS_PER_SECOND;
    124         ts.tv_nsec += (maxTimeInMS - ((maxTimeInMS / MILLISECONDS_PER_SECOND)*
    125                       MILLISECONDS_PER_SECOND)) * NANOSECONDS_PER_MILLISECOND;
    126 
    127         if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
    128         {
    129             ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
    130             ts.tv_nsec %= NANOSECONDS_PER_SECOND;
    131         }
    132         const int res = pthread_cond_timedwait(&_cond, &cs->_mutex, &ts);
    133         return (res == ETIMEDOUT) ? false : true;
    134     }
    135     else
    136     {
    137         pthread_cond_wait(&_cond, &cs->_mutex);
    138         return true;
    139     }
    140 }
    141 
    142 void ConditionVariablePosix::Wake()
    143 {
    144     pthread_cond_signal(&_cond);
    145 }
    146 
    147 void ConditionVariablePosix::WakeAll()
    148 {
    149     pthread_cond_broadcast(&_cond);
    150 }
    151 } // namespace webrtc
    152