History

the only constant is change.

Ge Wang committed 9 years ago

Commit 009ac191 parent b1e2669181 files · +0 −3911Browse files

Showing the changes to src/core/util_thread.cpp (1 of 181 files). Show all

Unified · Split

src/core/util_thread.cpp+523−0
@@ -0,0 +1,523 @@
1/*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
4
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.stanford.edu/
7 http://chuck.cs.princeton.edu/
8
9 This program is free software; 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
22 U.S.A.
23-----------------------------------------------------------------------------*/
24
25//-----------------------------------------------------------------------------
26// name: util_thread.cpp
27// desc: thread utilities
28//
29// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30// based on STK's Thread
31// Perry R. Cook + Gary Scavone
32// date: autumn 2004
33//-----------------------------------------------------------------------------
34#include "util_thread.h"
35#include "util_buffers.h"
36#include "chuck_errmsg.h"
37#ifndef __PLATFORM_WIN32__
38#include <unistd.h> // usleep
39#endif
40
41
42
43
44// static instantiation
45const size_t XWriteThread::PRODUCER_BUFFER_SIZE = 1024;
46XWriteThread * XWriteThread::o_defaultWriteThread = NULL;
47
48
49
50
51
52//-----------------------------------------------------------------------------
53// name: XThread()
54// desc: ...
55//-----------------------------------------------------------------------------
56XThread::XThread( )
57{
58 thread = 0;
59}
60
61
62
63
64//-----------------------------------------------------------------------------
65// name: ~XThread()
66// desc: ...
67//-----------------------------------------------------------------------------
68XThread::~XThread( )
69{
70 if( thread != 0 )
71 {
72#if defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__)
73 pthread_cancel(thread);
74 pthread_join(thread, NULL);
75#elif defined(__PLATFORM_WIN32__)
76 TerminateThread((HANDLE)thread, 0);
77#endif
78 }
79}
80
81
82
83
84//-----------------------------------------------------------------------------
85// name: start()
86// desc: ...
87//-----------------------------------------------------------------------------
88bool XThread::start( THREAD_FUNCTION routine, void * ptr )
89{
90 bool result = false;
91
92#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
93 if( pthread_create( &thread, NULL, *routine, ptr ) == 0 )
94 result = true;
95#elif defined(__PLATFORM_WIN32__)
96 unsigned thread_id;
97 thread = _beginthreadex( NULL, 0, routine, ptr, 0, &thread_id );
98 if( thread ) result = true;
99#endif
100 return result;
101}
102
103
104
105
106//-----------------------------------------------------------------------------
107// name: wait()
108// desc: ...
109//-----------------------------------------------------------------------------
110bool XThread::wait( long milliseconds, bool cancel )
111{
112 bool result = false;
113
114#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
115 if(cancel) pthread_cancel(thread);
116 pthread_join(thread, NULL);
117#elif defined(__PLATFORM_WIN32__)
118 DWORD timeout, retval;
119 if( milliseconds < 0 ) timeout = INFINITE;
120 else timeout = milliseconds;
121 retval = WaitForSingleObject( (HANDLE)thread, timeout );
122 if( retval == WAIT_OBJECT_0 ) {
123 CloseHandle( (HANDLE)thread );
124 thread = 0;
125 result = true;
126 }
127#endif
128
129 return result;
130}
131
132
133
134
135//-----------------------------------------------------------------------------
136// name: test()
137// desc: ...
138//-----------------------------------------------------------------------------
139void XThread :: test( )
140{
141#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
142 pthread_testcancel();
143#endif
144}
145
146
147
148
149//-----------------------------------------------------------------------------
150// name: XMutex()
151// desc: ...
152//-----------------------------------------------------------------------------
153XMutex::XMutex( )
154{
155#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
156 pthread_mutex_init(&mutex, NULL);
157#elif defined(__PLATFORM_WIN32__)
158 InitializeCriticalSection(&mutex);
159#endif
160}
161
162
163
164
165//-----------------------------------------------------------------------------
166// name: XMutex()
167// desc: ...
168//-----------------------------------------------------------------------------
169XMutex::~XMutex( )
170{
171#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
172 pthread_mutex_destroy( &mutex );
173#elif defined(__PLATFORM_WIN32__)
174 DeleteCriticalSection(&mutex);
175#endif
176}
177
178
179
180
181//-----------------------------------------------------------------------------
182// name: acquire()
183// desc: ...
184//-----------------------------------------------------------------------------
185void XMutex::acquire( )
186{
187#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
188 pthread_mutex_lock(&mutex);
189#elif defined(__PLATFORM_WIN32__)
190 EnterCriticalSection(&mutex);
191#endif
192}
193
194
195
196
197//-----------------------------------------------------------------------------
198// name: unlock()
199// desc: ...
200//-----------------------------------------------------------------------------
201void XMutex::release( )
202{
203#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
204 pthread_mutex_unlock(&mutex);
205#elif defined(__PLATFORM_WIN32__)
206 LeaveCriticalSection(&mutex);
207#endif
208}
209
210
211
212
213//-----------------------------------------------------------------------------
214// name: shared()
215// desc: get XWriteThread shared instance
216//-----------------------------------------------------------------------------
217XWriteThread * XWriteThread::shared()
218{
219 // static XWriteThread s_defaultWriteThread;
220
221 // check
222 if( o_defaultWriteThread == NULL )
223 o_defaultWriteThread = new XWriteThread();
224
225 return o_defaultWriteThread;
226}
227
228
229
230
231//-----------------------------------------------------------------------------
232// name: XWriteThread()
233// desc: constructor
234//-----------------------------------------------------------------------------
235XWriteThread::XWriteThread(size_t data_buffer_size, size_t msg_buffer_size)
236 :
237 m_msg_buffer(new CircularBuffer<Message>(msg_buffer_size)),
238 m_data_buffer(new FastCircularBuffer),
239 m_thread_buffer(new t_CKBYTE[data_buffer_size])
240{
241 m_data_buffer->initialize( data_buffer_size, sizeof(char) );
242 m_thread_exit = FALSE;
243 m_thread.start( write_cb, this );
244 m_stream = NULL;
245 m_bytes_in_buffer = 0;
246}
247
248
249
250
251//-----------------------------------------------------------------------------
252// name: ~XWriteThread()
253// desc: destructor
254//-----------------------------------------------------------------------------
255XWriteThread::~XWriteThread()
256{
257 SAFE_DELETE( m_msg_buffer );
258 SAFE_DELETE( m_data_buffer );
259 SAFE_DELETE_ARRAY( m_thread_buffer );
260}
261
262
263
264
265//-----------------------------------------------------------------------------
266// name: shutdown()
267// desc: close down writer thread and delete in background
268//-----------------------------------------------------------------------------
269void XWriteThread::shutdown()
270{
271 Message msg;
272 msg.operation = Message::SHUTDOWN;
273 m_msg_buffer->put( msg );
274
275 m_thread.wait( -1, false );
276}
277
278
279
280
281//-----------------------------------------------------------------------------
282// name: fwrite()
283// desc: ...
284//-----------------------------------------------------------------------------
285size_t XWriteThread::fwrite(const void * ptr, size_t size, size_t nitems, FILE * stream)
286{
287 if(stream != m_stream)
288 flush_data_buffer();
289
290 // TODO: overflow detection
291 if(m_data_buffer->put((char*)ptr, size*nitems) == 0)
292 {
293 EM_log(CK_LOG_SEVERE, "XWriteThread::fwrite: data buffer overflow");
294 }
295
296 m_bytes_in_buffer += size*nitems;
297 m_stream = stream;
298
299 if(m_bytes_in_buffer >= PRODUCER_BUFFER_SIZE)
300 flush_data_buffer();
301
302 return nitems;
303}
304
305
306
307
308//-----------------------------------------------------------------------------
309// name: fseek()
310// desc: ...
311//-----------------------------------------------------------------------------
312int XWriteThread::fseek(FILE *stream, long offset, int whence)
313{
314 flush_data_buffer();
315
316 Message msg;
317 msg.file = stream;
318 msg.operation = Message::SEEK;
319 msg.seek.offset = offset;
320 msg.seek.whence = whence;
321 m_msg_buffer->put(msg);
322
323 return 0;
324}
325
326
327
328
329//-----------------------------------------------------------------------------
330// name: fflush()
331// desc: ...
332//-----------------------------------------------------------------------------
333int XWriteThread::fflush(FILE *stream)
334{
335 flush_data_buffer();
336
337 Message msg;
338 msg.file = stream;
339 msg.operation = Message::FLUSH;
340 m_msg_buffer->put(msg);
341
342 return 0;
343}
344
345
346
347
348//-----------------------------------------------------------------------------
349// name: fclose()
350// desc: ...
351//-----------------------------------------------------------------------------
352int XWriteThread::fclose(FILE *stream)
353{
354 flush_data_buffer();
355
356 Message msg;
357 msg.file = stream;
358 msg.operation = Message::CLOSE;
359 m_msg_buffer->put(msg);
360
361 return 0;
362}
363
364
365
366
367//-----------------------------------------------------------------------------
368// name: flush_data_buffer()
369// desc: ...
370//-----------------------------------------------------------------------------
371void XWriteThread::flush_data_buffer()
372{
373 if(m_bytes_in_buffer > 0)
374 {
375 Message msg;
376 msg.file = m_stream;
377 msg.operation = Message::WRITE;
378 msg.write.data_size = m_bytes_in_buffer;
379 m_msg_buffer->put(msg);
380
381 m_bytes_in_buffer = 0;
382 }
383}
384
385
386
387
388//-----------------------------------------------------------------------------
389// name: write_cb()
390// desc: thread function
391//-----------------------------------------------------------------------------
392#if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) )
393void * XWriteThread::write_cb(void * _thiss)
394#elif defined(__PLATFORM_WIN32__)
395unsigned XWriteThread::write_cb(void * _thiss)
396#endif
397{
398 XWriteThread * _this = (XWriteThread *) _thiss;
399 Message msg;
400
401 while(!_this->m_thread_exit)
402 {
403 while(_this->m_msg_buffer->get(msg))
404 {
405 if(msg.operation == Message::WRITE)
406 {
407 size_t actual_size = _this->m_data_buffer->get(_this->m_thread_buffer,
408 msg.write.data_size);
409 if(actual_size != msg.write.data_size)
410 {
411 EM_log(CK_LOG_SEVERE, "XWriteThread: buffered data size mismatch (%li : %li)",
412 msg.write.data_size, actual_size);
413 }
414
415 ::fwrite(_this->m_thread_buffer, 1, actual_size, msg.file);
416 }
417 else if(msg.operation == Message::SEEK)
418 {
419 ::fseek(msg.file, msg.seek.offset, msg.seek.whence);
420 }
421 else if(msg.operation == Message::FLUSH)
422 {
423 ::fflush(msg.file);
424 }
425 else if(msg.operation == Message::CLOSE)
426 {
427 ::fclose(msg.file);
428 }
429 else if(msg.operation == Message::SHUTDOWN)
430 {
431 _this->m_thread_exit = TRUE;
432 break;
433 }
434 }
435
436 usleep(1000);
437 }
438
439 delete _this;
440 _thiss = _this = NULL;
441
442 return 0;
443}
444
445
446
447
448#ifdef __MACOSX_CORE__
449t_CKINT XThreadUtil::our_priority = 85;
450#else
451t_CKINT XThreadUtil::our_priority = 0x7fffffff;
452#endif
453
454
455
456
457#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
458//-----------------------------------------------------------------------------
459// name: set_priority()
460// desc: set thread priority
461//-----------------------------------------------------------------------------
462t_CKBOOL XThreadUtil::set_priority( CHUCK_THREAD tid, t_CKINT priority )
463{
464 struct sched_param param;
465 int policy;
466
467 // log
468 EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority );
469
470 // get for thread
471 if( pthread_getschedparam( tid, &policy, &param) )
472 return FALSE;
473
474 // priority
475 param.sched_priority = priority;
476 // policy
477 policy = SCHED_RR;
478 // set for thread, pthread style
479 if( pthread_setschedparam( tid, policy, &param ) )
480 return FALSE;
481
482 return TRUE;
483}
484//-----------------------------------------------------------------------------
485// name: set_priority()
486// desc: set thread priority for self
487//-----------------------------------------------------------------------------
488t_CKBOOL XThreadUtil::set_priority( t_CKINT priority )
489{
490 // pass it along with self thread
491 set_priority( pthread_self(), priority );
492 return TRUE;
493}
494#else
495//-----------------------------------------------------------------------------
496// name: set_priority()
497// desc: set thread priority
498//-----------------------------------------------------------------------------
499t_CKBOOL XThreadUtil::set_priority( CHUCK_THREAD tid, t_CKINT priority )
500{
501 // if priority is 0 then done
502 if( !priority ) return TRUE;
503
504 // log
505 EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority );
506
507 // set the priority the thread, windows style
508 if( !SetThreadPriority( tid, priority ) )
509 return FALSE;
510
511 return TRUE;
512}
513//-----------------------------------------------------------------------------
514// name: set_priority()
515// desc: set thread priority for self
516//-----------------------------------------------------------------------------
517t_CKBOOL XThreadUtil::set_priority( t_CKINT priority )
518{
519 // pass it along with self thread
520 set_priority( GetCurrentThread(), priority );
521 return TRUE;
522}
523#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t