/[svn]/linuxsampler/trunk/src/common/Thread.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/Thread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 497 - (show annotations) (download)
Sun Apr 10 11:55:44 2005 UTC (18 years, 11 months ago) by persson
File size: 7589 byte(s)
* removed some build warnings
* fixed a bug with hanging notes when using sustain pedal
* release samples are not triggered anymore when sustain pedal is down

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "Thread.h"
24
25 Thread::Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta) {
26 this->bLockedMemory = LockMemory;
27 this->isRealTime = RealTime;
28 this->Running = false;
29 this->PriorityDelta = PriorityDelta;
30 this->PriorityMax = PriorityMax;
31 __thread_destructor_key = 0;
32 pthread_mutex_init(&__thread_state_mutex, NULL);
33 pthread_cond_init(&__thread_start_condition, NULL);
34 pthread_cond_init(&__thread_exit_condition, NULL);
35 }
36
37 Thread::~Thread() {
38 StopThread();
39 pthread_cond_destroy(&__thread_start_condition);
40 pthread_cond_destroy(&__thread_exit_condition);
41 pthread_mutex_destroy(&__thread_state_mutex);
42 }
43
44 /**
45 * Starts the thread. This method will wait until the thread actually
46 * started it's execution before it will return. The abstract method
47 * Main() is the entry point for the new thread. You have to implement the
48 * Main() method in your subclass.
49 */
50 int Thread::StartThread() {
51 pthread_mutex_lock(&__thread_state_mutex);
52 if (!Running) {
53 SignalStartThread();
54 pthread_cond_wait(&__thread_start_condition, &__thread_state_mutex);
55 }
56 pthread_mutex_unlock(&__thread_state_mutex);
57 return 0;
58 }
59
60 /**
61 * Starts the thread. This method will signal to start the thread and
62 * return immediately. Note that the thread might not yet run when this
63 * method returns! The abstract method Main() is the entry point for the
64 * new thread. You have to implement the Main() method in your subclass.
65 *
66 * @see StartThread()
67 */
68 int Thread::SignalStartThread() {
69 // Create and run the thread
70 int res = pthread_create(&this->__thread_id, NULL, __pthread_launcher, this);
71 switch (res) {
72 case 0: // Success
73 break;
74 case EAGAIN:
75 std::cerr << "Thread creation failed: System doesn't allow to create another thread."
76 << std::endl << std::flush;
77 this->Running = false;
78 break;
79 case EPERM:
80 std::cerr << "Thread creation failed: You're lacking permisssions to set required scheduling policy and parameters."
81 << std::endl << std::flush;
82 this->Running = false;
83 break;
84 default:
85 std::cerr << "Thread creation failed: Unknown cause."
86 << std::endl << std::flush;
87 this->Running = false;
88 break;
89 }
90 return res;
91 }
92
93 /**
94 * Stops the thread. This method will wait until the thread actually stopped
95 * it's execution before it will return.
96 */
97 int Thread::StopThread() {
98 pthread_mutex_lock(&__thread_state_mutex);
99 if (Running) {
100 SignalStopThread();
101 pthread_cond_wait(&__thread_exit_condition, &__thread_state_mutex);
102 pthread_detach(__thread_id);
103 }
104 pthread_mutex_unlock(&__thread_state_mutex);
105 return 0;
106 }
107
108 /**
109 * Stops the thread. This method will signal to stop the thread and return
110 * immediately. Note that the thread might still run when this method
111 * returns!
112 *
113 * @see StopThread()
114 */
115 int Thread::SignalStopThread() {
116 pthread_cancel(__thread_id);
117 return 0;
118 }
119
120 /**
121 * Sets the process SCHED_FIFO policy, if max=1 then set at max priority,
122 * else use min priority. delta is added to the priority so that we can
123 * for example set 3 SCHED_FIFO tasks to different priorities by specifying
124 * delta 0 , -1 , -2 ( 0 = highest priority because -1 is subtracted to the
125 * current priority).
126 */
127 int Thread::SetSchedulingPriority() {
128 #if !defined(__APPLE__)
129 struct sched_param schp;
130
131 if (!isRealTime) return 0;
132
133 /*
134 * set the process to realtime privs
135 */
136 memset(&schp, 0, sizeof(schp));
137 if (this->PriorityMax == 1) {
138 schp.sched_priority = sched_get_priority_max(SCHED_FIFO) + this->PriorityDelta;
139 }
140 if (this->PriorityMax == -1) {
141 schp.sched_priority = sched_get_priority_min(SCHED_FIFO) + this->PriorityDelta;
142 }
143
144 if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0) {
145 perror("Thread: WARNING, can't assign realtime scheduling to thread!");
146 return -1;
147 }
148 #endif
149 return 0;
150 }
151
152 /**
153 * Locks the memory so it will not be swapped out by the operating system.
154 */
155 int Thread::LockMemory() {
156 #if !defined(__APPLE__)
157 if (!bLockedMemory) return 0;
158 if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {
159 perror("Thread: WARNING, can't mlockall() memory!");
160 return -1;
161 }
162 #endif
163 return 0;
164 }
165
166 /**
167 * Registers thread destructor callback function which will be executed when
168 * the thread stops it's execution and sets the 'Running' flag to true. This
169 * method will be called by the __pthread_launcher callback function, DO NOT
170 * CALL THIS METHOD YOURSELF!
171 */
172 void Thread::EnableDestructor() {
173 pthread_mutex_lock(&__thread_state_mutex);
174 pthread_key_create(&__thread_destructor_key, __pthread_destructor);
175 pthread_setspecific(__thread_destructor_key, this);
176 Running = true;
177 pthread_mutex_unlock(&__thread_state_mutex);
178 pthread_cond_broadcast(&__thread_start_condition);
179 }
180
181 /**
182 * Will be called by the kernel when the thread stops it's execution.
183 */
184 int Thread::Destructor() {
185 pthread_key_delete(__thread_destructor_key);
186 pthread_mutex_lock(&__thread_state_mutex);
187 Running = false;
188 pthread_mutex_unlock(&__thread_state_mutex);
189 pthread_cond_broadcast(&__thread_exit_condition);
190 return 0;
191 }
192
193 /// Callback function for the POSIX thread API
194 void* __pthread_launcher(void* thread) {
195 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); // let the thread be killable under any circumstances
196 Thread* t;
197 t = (Thread*) thread;
198 t->SetSchedulingPriority();
199 t->LockMemory();
200 t->EnableDestructor();
201 t->Main();
202 return NULL;
203 }
204
205 /// Callback function for the POSIX thread API
206 void __pthread_destructor(void* thread) {
207 Thread* t;
208 t = (Thread*) thread;
209 t->Destructor();
210 }

  ViewVC Help
Powered by ViewVC