follow eThread changes: mainly thread_running -> sync, hasStarted()
[enigma2.git] / lib / base / thread.cpp
1 #include <lib/base/thread.h>
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <lib/base/eerror.h>
6
7 void eThread::thread_completed(void *ptr)
8 {
9         eThread *p = (eThread*) ptr;
10         p->m_alive = 0;
11
12                 /* recover state */
13         if (!p->m_state.value())
14         {
15                 p->m_state.up();
16                 assert(p->m_state.value() == 1);
17         }
18 }
19
20 void *eThread::wrapper(void *ptr)
21 {
22         eThread *p = (eThread*)ptr;
23         pthread_cleanup_push(thread_completed, (void*)p);
24         p->thread();
25         pthread_exit(0);
26         pthread_cleanup_pop(1);
27         return 0;
28 }
29
30 eThread::eThread()
31         : the_thread(0), m_alive(0)
32 {
33 }
34
35 int eThread::runAsync(int prio, int policy)
36 {
37         eDebug("before: %d", m_state.value());
38                 /* the thread might already run. */
39         if (sync())
40                 return -1;
41         
42         eDebug("after: %d", m_state.value());
43         assert(m_state.value() == 1); /* sync postconditions */
44         assert(!m_alive);
45         m_state.down();
46         
47         m_alive = 1;
48
49                 /* start thread. */
50         pthread_attr_t attr;
51         pthread_attr_init(&attr);
52         
53         if (prio || policy)
54         {
55                 struct sched_param p;
56                 p.__sched_priority=prio;
57                 pthread_attr_setschedpolicy(&attr, policy);
58                 pthread_attr_setschedparam(&attr, &p);
59         }
60         
61         if (pthread_create(&the_thread, &attr, wrapper, this))
62         {
63                 pthread_attr_destroy(&attr);
64                 m_alive = 0;
65                 eDebug("couldn't create new thread");
66                 return -1;
67         }
68         
69         pthread_attr_destroy(&attr);
70         return 0;
71 }                     
72
73 int eThread::run(int prio, int policy)
74 {
75         if (runAsync(prio, policy))
76                 return -1;
77         sync();
78         return 0;
79 }
80
81 eThread::~eThread()
82 {
83         kill();
84 }
85
86 int eThread::sync(void)
87 {
88         int res;
89         m_state.down(); /* this might block */
90         res = m_alive;
91         assert(m_state.value() == 0);
92         m_state.up();
93         return res; /* 0: thread is guaranteed not to run. 1: state unknown. */
94 }
95
96 void eThread::sendSignal(int sig)
97 {
98         if (m_alive)
99                 pthread_kill(the_thread, sig);
100         else
101                 eDebug("send signal to non running thread");
102 }
103
104 void eThread::kill(bool sendcancel)
105 {
106         if (!the_thread) /* already joined */
107                 return;
108
109         if (sync() && sendcancel)
110         {
111                 eDebug("send cancel to thread");
112                 pthread_cancel(the_thread);
113         }
114         eDebug("thread joined %d", pthread_join(the_thread, 0));
115         the_thread = 0;
116 }
117
118 void eThread::hasStarted()
119 {
120         assert(!m_state.value());
121         m_state.up();
122 }