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 "webrtc/system_wrappers/source/condition_variable_posix.h"
     12 
     13 #include <errno.h>
     14 #if defined(WEBRTC_LINUX)
     15 #include <time.h>
     16 #else
     17 #include <sys/time.h>
     18 #endif
     19 
     20 #include "webrtc/system_wrappers/source/critical_section_posix.h"
     21 
     22 namespace webrtc {
     23 
     24 ConditionVariableWrapper* ConditionVariablePosix::Create() {
     25   ConditionVariablePosix* ptr = new ConditionVariablePosix;
     26   if (!ptr) {
     27     return NULL;
     28   }
     29 
     30   const int error = ptr->Construct();
     31   if (error) {
     32     delete ptr;
     33     return NULL;
     34   }
     35 
     36   return ptr;
     37 }
     38 
     39 ConditionVariablePosix::ConditionVariablePosix() {
     40 }
     41 
     42 int ConditionVariablePosix::Construct() {
     43 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
     44   pthread_cond_init(&cond_, NULL);
     45 #else
     46   int result = 0;
     47   pthread_condattr_t cond_attr;
     48   result = pthread_condattr_init(&cond_attr);
     49   if (result != 0) {
     50     return -1;
     51   }
     52   result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
     53   if (result != 0) {
     54     return -1;
     55   }
     56   result = pthread_cond_init(&cond_, &cond_attr);
     57   if (result != 0) {
     58     return -1;
     59   }
     60   result = pthread_condattr_destroy(&cond_attr);
     61   if (result != 0) {
     62     return -1;
     63   }
     64 #endif
     65   return 0;
     66 }
     67 
     68 ConditionVariablePosix::~ConditionVariablePosix() {
     69   pthread_cond_destroy(&cond_);
     70 }
     71 
     72 void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect) {
     73   CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
     74       &crit_sect);
     75   pthread_cond_wait(&cond_, &cs->mutex_);
     76 }
     77 
     78 bool ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect,
     79                                      unsigned long max_time_inMS) {
     80   const unsigned long INFINITE =  0xFFFFFFFF;
     81   const int MILLISECONDS_PER_SECOND = 1000;
     82 #ifndef WEBRTC_LINUX
     83   const int MICROSECONDS_PER_MILLISECOND = 1000;
     84 #endif
     85   const int NANOSECONDS_PER_SECOND = 1000000000;
     86   const int NANOSECONDS_PER_MILLISECOND  = 1000000;
     87 
     88   CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
     89       &crit_sect);
     90 
     91   if (max_time_inMS != INFINITE) {
     92     timespec ts;
     93 #ifndef WEBRTC_MAC
     94 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
     95     clock_gettime(CLOCK_REALTIME, &ts);
     96 #else
     97     clock_gettime(CLOCK_MONOTONIC, &ts);
     98 #endif
     99 #else  // WEBRTC_MAC
    100     struct timeval tv;
    101     gettimeofday(&tv, 0);
    102     ts.tv_sec  = tv.tv_sec;
    103     ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
    104 #endif
    105 
    106     ts.tv_sec += max_time_inMS / MILLISECONDS_PER_SECOND;
    107     ts.tv_nsec +=
    108         (max_time_inMS
    109         - ((max_time_inMS / MILLISECONDS_PER_SECOND) * MILLISECONDS_PER_SECOND))
    110         * NANOSECONDS_PER_MILLISECOND;
    111 
    112     if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) {
    113       ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
    114       ts.tv_nsec %= NANOSECONDS_PER_SECOND;
    115     }
    116     const int res = pthread_cond_timedwait(&cond_, &cs->mutex_, &ts);
    117     return (res == ETIMEDOUT) ? false : true;
    118   } else {
    119     pthread_cond_wait(&cond_, &cs->mutex_);
    120     return true;
    121   }
    122 }
    123 
    124 void ConditionVariablePosix::Wake() {
    125   pthread_cond_signal(&cond_);
    126 }
    127 
    128 void ConditionVariablePosix::WakeAll() {
    129   pthread_cond_broadcast(&cond_);
    130 }
    131 
    132 }  // namespace webrtc
    133