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