summaryrefslogtreecommitdiff
path: root/tvapi/libtv/tvutils/CThread.cpp (plain)
blob: 628804001408644dec0e78bc47ab4d469797c83e
1/*
2reference android api, just linux pthread
3*/
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <memory.h>
8#include <errno.h>
9#include <assert.h>
10#include <unistd.h>
11
12#include <pthread.h>
13#include <sched.h>
14#include <sys/resource.h>
15
16#include "CThread.h"
17#include <CTvLog.h>
18
19#include <sys/prctl.h>
20
21CThread::CThread()
22 : mThreadId(-1),
23 mLock("Thread::mLock"),
24 mExitPending(false), mRunning(false)
25{
26}
27
28CThread::~CThread()
29{
30}
31
32int CThread::readyToRun()
33{
34 return 0;
35}
36
37
38int CThread::run(const char *name __unused, int priority __unused, int stack)
39{
40 CMutex::Autolock _l(mLock);
41
42 if (mRunning) {
43 // thread already started
44 return -1;
45 }
46
47 mStatus = 0;
48 mExitPending = false;
49 mThreadId = -1;
50 mRunning = true;
51
52
53 pthread_attr_t attr;
54 pthread_attr_init(&attr);
55 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
56
57 if (stack) {
58 pthread_attr_setstacksize(&attr, stack);
59 }
60
61 int result = pthread_create(&mThreadId, &attr,
62 _threadLoop, this);
63 pthread_attr_destroy(&attr);
64 if (result != 0) {
65 LOGE("Thread create fail ret = %d (errno=%d)\n",
66 result, errno);
67
68 mStatus = -1; // something happened!
69 mRunning = false;
70 mThreadId = -1;
71 return -1;
72 }
73 return 0;
74}
75
76void *CThread::_threadLoop(void *user)
77{
78 CThread *const self = static_cast<CThread *>(user);
79
80 bool first = true;
81 do {
82 bool result;
83 if (first) {
84 first = false;
85 self->mStatus = self->readyToRun();
86 result = (self->mStatus == 0);
87
88 if (result && !self->exitPending()) {
89 result = self->threadLoop();
90 }
91 } else {
92 result = self->threadLoop();
93 }
94
95
96 CMutex::Autolock _l(self->mLock);
97 if (result == false || self->mExitPending) {
98 self->mExitPending = true;
99 self->mRunning = false;
100 // clear thread ID so that requestExitAndWait() does not exit if
101 // called by a new thread using the same thread ID as this one.
102 self->mThreadId = -1;
103 // note that interested observers blocked in requestExitAndWait are
104 // awoken by broadcast, but blocked on mLock until break exits scope
105 self->mThreadExitedCondition.broadcast();
106 break;
107 }
108 } while (true);
109
110 return NULL;
111}
112
113void CThread::requestExit()
114{
115 CMutex::Autolock _l(mLock);
116 mExitPending = true;
117}
118
119int CThread::requestExitAndWait()
120{
121 CMutex::Autolock _l(mLock);
122 if (mThreadId == pthread_self()) {
123 ALOGW(
124 "Thread (this=%p): don't call waitForExit() from this "
125 "Thread object's thread. It's a guaranteed deadlock!",
126 this);
127 return -1;
128 }
129
130 mExitPending = true;
131
132 while (mRunning == true) {
133 mThreadExitedCondition.wait(mLock);
134 }
135 // This next line is probably not needed any more, but is being left for
136 // historical reference. Note that each interested party will clear flag.
137 mExitPending = false;
138
139 return mStatus;
140}
141
142int CThread::join()
143{
144 CMutex::Autolock _l(mLock);
145 if (mThreadId == pthread_self()) {
146 ALOGW(
147 "Thread (this=%p): don't call join() from this "
148 "Thread object's thread. It's a guaranteed deadlock!",
149 this);
150
151 return -1;
152 }
153
154 while (mRunning == true) {
155 mThreadExitedCondition.wait(mLock);
156 }
157
158 return mStatus;
159}
160
161bool CThread::exitPending() const
162{
163 CMutex::Autolock _l(mLock);
164 return mExitPending;
165}
166