cec: stick some interfaces before the pthread stuff, so we can add other implementati...
[deb_libcec.git] / src / lib / platform / posix / pthreads.cpp
1 /*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
6 *
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
8 *
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 *
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
26 *
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
31 */
32
33 #include "../threads.h"
34 #include "../timeutils.h"
35
36 using namespace CEC;
37
38 CMutex::CMutex(bool bRecursive /* = true */) :
39 IMutex(bRecursive)
40 {
41 pthread_mutex_init(&m_mutex, bRecursive ? GetMutexAttribute() : NULL);
42 }
43
44 CMutex::~CMutex(void)
45 {
46 pthread_mutex_destroy(&m_mutex);
47 }
48
49 bool CMutex::TryLock(void)
50 {
51 return (pthread_mutex_trylock(&m_mutex) == 0);
52 }
53
54 bool CMutex::Lock(void)
55 {
56 return (pthread_mutex_lock(&m_mutex) == 0);
57 }
58
59 void CMutex::Unlock(void)
60 {
61 pthread_mutex_unlock(&m_mutex);
62 }
63
64 static pthread_mutexattr_t g_mutexAttr;
65 pthread_mutexattr_t *CMutex::GetMutexAttribute()
66 {
67 static bool bAttributeInitialised = false;
68 if (!bAttributeInitialised)
69 {
70 pthread_mutexattr_init(&g_mutexAttr);
71 pthread_mutexattr_settype(&g_mutexAttr, PTHREAD_MUTEX_RECURSIVE);
72 bAttributeInitialised = true;
73 }
74 return &g_mutexAttr;
75 }
76
77 CCondition::CCondition(void)
78 {
79 pthread_cond_init(&m_cond, NULL);
80 }
81
82 CCondition::~CCondition(void)
83 {
84 pthread_cond_broadcast(&m_cond);
85 pthread_cond_destroy(&m_cond);
86 }
87
88 void CCondition::Broadcast(void)
89 {
90 pthread_cond_broadcast(&m_cond);
91 }
92
93 void CCondition::Signal(void)
94 {
95 pthread_cond_signal(&m_cond);
96 }
97
98 bool CCondition::Wait(IMutex *mutex, uint32_t iTimeout /* = 0 */)
99 {
100 bool bReturn(false);
101 sched_yield();
102 CMutex *pmutex = static_cast<CMutex *>(mutex);
103 if (pmutex)
104 {
105 if (iTimeout > 0)
106 {
107 struct timespec abstime;
108 struct timeval now;
109 gettimeofday(&now, NULL);
110 iTimeout += now.tv_usec / 1000;
111 abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000);
112 abstime.tv_nsec = (int32_t)((iTimeout % (uint32_t)1000) * (uint32_t)1000000);
113 bReturn = (pthread_cond_timedwait(&m_cond, &pmutex->m_mutex, &abstime) == 0);
114 }
115 else
116 {
117 bReturn = (pthread_cond_wait(&m_cond, &pmutex->m_mutex) == 0);
118 }
119 }
120 return bReturn;
121 }
122
123 bool CThread::CreateThread(bool bWait /* = true */)
124 {
125 bool bReturn(false);
126 CLockObject lock(m_threadMutex);
127 m_bStop = false;
128 if (!m_bRunning && pthread_create(&m_thread, NULL, (void *(*) (void *))&CThread::ThreadHandler, (void *)this) == 0)
129 {
130 if (bWait)
131 m_threadCondition->Wait(m_threadMutex);
132 bReturn = true;
133 }
134 return bReturn;
135 }
136
137 bool CThread::StopThread(bool bWaitForExit /* = true */)
138 {
139 bool bReturn = IThread::StopThread(bWaitForExit);
140
141 void *retVal;
142 if (bWaitForExit && m_bRunning)
143 bReturn = (pthread_join(m_thread, &retVal) == 0);
144
145 return bReturn;
146 }
147
148 void *CThread::ThreadHandler(CThread *thread)
149 {
150 void *retVal = NULL;
151
152 if (thread)
153 {
154 CLockObject lock(thread->m_threadMutex);
155 thread->m_bRunning = true;
156 lock.Leave();
157 thread->m_threadCondition->Broadcast();
158
159 retVal = thread->Process();
160
161 lock.Lock();
162 thread->m_bRunning = false;
163 lock.Leave();
164 thread->m_threadCondition->Broadcast();
165 }
166
167 return retVal;
168 }