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