- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

thread.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28
33 #ifndef __INCLUDE_MIST_THREAD__
34 #define __INCLUDE_MIST_THREAD__
35
36
37 #ifndef __INCLUDE_MIST_CONF_H__
38 #include "config/mist_conf.h"
39 #endif
40
41 #ifndef __INCLUDE_MIST_SINGLETON__
42 #include "singleton.h"
43 #endif
44
45
46 // スレッド用ライブラリのインクルード
47 // UNIX系とWindows用を使い分ける
48 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
49 // スレッドサポートはしないので特に必要なインクルードファイルは無し
50 #define __THREAD_POOL_SUPPORT__ 0
51 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
52 #if !defined( _WIN32_WINNT )
53 #define __THREAD_POOL_SUPPORT__ 0
54 #pragma message( "To use mist thread pool functionality, you must define _WIN32_WINNT (>=0x0400) in the project setting page." )
55 #elif _WIN32_WINNT < 0x0400
56 #define __THREAD_POOL_SUPPORT__ 0
57 #pragma message( "To use mist thread pool functionality, _WIN32_WINNT must be greater than 0x0400." )
58 #else
59 #define __THREAD_POOL_SUPPORT__ 1
60 #endif
61
62 #include <windows.h>
63 #include <process.h>
64 #include <mmsystem.h>
65 #pragma comment ( lib, "winmm.lib" )
66 #else
67 #include <pthread.h>
68 #include <unistd.h>
69 #include <time.h>
70 #include <errno.h>
71 #include <sys/time.h>
72 #define __THREAD_POOL_SUPPORT__ 1
73 #endif
74
75 #ifndef INFINITE
76 #define INFINITE ( ( unsigned long ) -1 )
77 #endif
78
79 #include <map>
80 #include <vector>
81 #include <list>
82 #include <string>
83
84
85 // mist名前空間の始まり
86 _MIST_BEGIN
87
88
89
90 // スレッド用関数
91 typedef unsigned long ThreadExitCode;
92 typedef ThreadExitCode ( LPTHREADFUNC ) ( void *thread_param );
93
94
95 // スレッドを操作する，識別する変数
96 struct thread_dmy_class{ };
97
98 // スレッドを操作する一番ベースとなるクラス
99 struct thread_object
100 {
101 virtual bool create( ) = 0;
102 virtual bool wait( unsigned long dwMilliseconds = INFINITE ) = 0;
103 virtual bool close( ) = 0;
104 virtual ~thread_object( ){ }
105 };
106
107
115
116
124 inline size_t get_cpu_num( )
125 {
126 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
127 // スレッドサポートはしないのでCPU数は常に1
128 return( 1 );
129 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
130 SYSTEM_INFO sysInfo;
131 GetSystemInfo( &sysInfo );
132 return( static_cast< size_t >( sysInfo.dwNumberOfProcessors ) );
133 #else
134 return( static_cast< size_t >( sysconf( _SC_NPROCESSORS_ONLN ) ) );
135 #endif
136 }
137
138
140 inline void sleep( size_t dwMilliseconds )
141 {
142 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
143 SleepEx( static_cast< DWORD >( dwMilliseconds ), false );
144 #else
145 timespec treq, trem;
146 treq.tv_sec = static_cast< time_t >( dwMilliseconds / 1000 );
147 treq.tv_nsec = static_cast< long >( ( dwMilliseconds % 1000 ) * 1000000 );
148
149 while( nanosleep( &treq, &trem ) != 0 )
150 {
151 treq = trem;
152 }
153 #endif
154 }
155
156
189 struct simple_lock_object
190 {
191 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
192 typedef char lock_object_type; // スレッドサポートはしないのでダミー変数用意
193 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
194 typedef CRITICAL_SECTION lock_object_type; // Windows用のロックオブジェクト(CRITIFCALSECTIONを利用)
195 #else
196 typedef pthread_mutex_t lock_object_type; // pthreadライブラリでのロックオブジェクト
197 #endif
198
199 lock_object_type __lock__;
200
201 public:
203 simple_lock_object( )
204 {
205 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
206 // スレッドサポートはしないので特に必何もしない
207 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
208 //InitializeCriticalSectionAndSpinCount( &__lock__, 4000 ); // クリティカルセクションオブジェクトを初期化
209 InitializeCriticalSection( &__lock__ ); // クリティカルセクションオブジェクトを初期化
210 #else
211 pthread_mutex_init( &__lock__, NULL ); // pthread用のMutexオブジェクトを初期化
212 #endif
213 }
214
216 ~simple_lock_object( )
217 {
218 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
219 // スレッドサポートはしないので特に必何もしない
220 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
221 DeleteCriticalSection( &__lock__ ); // クリティカルセクションオブジェクトを削除
222 #else
223 pthread_mutex_destroy( &__lock__ ); // pthread用のMutexオブジェクトを初期化
224 #endif
225 }
226
227 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
228
229 // スレッドサポートはしないので特に必何もしない
230 bool lock( ){ return( true ); }
231 bool unlock( ){ return( true ); }
232 bool try_lock( ){ return( true ); }
233
234 #else
235
241 bool lock( )
242 {
243 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
244 EnterCriticalSection( &__lock__ ); // クリティカルセクションオブジェクトをロック
245 #else
246 pthread_mutex_lock( &__lock__ ); // pthread用のMutexオブジェクトをロック
247 #endif
248
249 return( true );
250 }
251
252 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
253
254
255
256
257
258
259
260 bool try_lock( )
261 {
262 // クリティカルセクションオブジェクトのロックが可能かを調べる
263 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
264 return( TryEnterCriticalSection( &__lock__ ) != FALSE );
265 #else
266 return( pthread_mutex_trylock( &__lock__ ) == 0 );
267 #endif
268 }
269 #endif
270
272 bool unlock( )
273 {
274 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
275 LeaveCriticalSection( &__lock__ ); // クリティカルセクションオブジェクトをアンロック
276 #else
277 pthread_mutex_unlock( &__lock__ ); // pthread用のMutexオブジェクトをアンロック
278 #endif
279
280 return( true );
281 }
282
283 #endif
284 };
285
287 // スレッドグループの終わり
288
289 template < class MUTEX >
290 class lock_object_table : public ::std::map< ::std::string, MUTEX >
291 {
292 private:
293 typedef ::std::map< ::std::string, MUTEX > base;
294 typedef MUTEX lock_object_type;
295
296 public:
297 lock_object_table( )
298 {
299 }
300
301 ~lock_object_table( )
302 {
303 typename base::iterator ite = base::begin( );
304 for( ; ite != base::end( ) ; ++ite )
305 {
306 destroy( ite->second );
307 }
308 base::clear( );
309 }
310
311 protected:
312 static void destroy( lock_object_type &l )
313 {
314 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
315 // スレッドサポートはしないので特に必何もしない
316 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
317 DeleteCriticalSection( &l ); // クリティカルセクションオブジェクトを削除
318 #else
319 pthread_mutex_destroy( &l ); // pthread用のMutexオブジェクトを初期化
320 #endif
321 }
322 };
323
327
328
362 struct lock_object
363 {
364 protected:
365 ::std::string lock_name_;
366
367 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
368 typedef char lock_object_type; // スレッドサポートはしないのでダミー変数用意
369 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
370 typedef CRITICAL_SECTION lock_object_type; // Windows用のロックオブジェクト(CRITIFCALSECTIONを利用)
371 #else
372 typedef pthread_mutex_t lock_object_type; // pthreadライブラリでのロックオブジェクト
373 #endif
374
375 typedef lock_object_table< lock_object_type > lock_table;
376
377 public:
378 lock_object( ) : lock_name_( "mist default lock object!!" ){ }
379 lock_object( const std::string &name ) : lock_name_( name ){ }
380
381 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
382
383 // スレッドサポートはしないので特に必何もしない
384 bool lock( ){ return( true ); }
385 bool unlock( ){ return( true ); }
386
387 #else
388
394 bool lock( )
395 {
396 static lock_object_type &__double_lock__ = double_lock_object( );
397
398 // テーブルの検索でスレッドが衝突しないようにロックする
399 lock( __double_lock__ );
400
401 lock_table &table = singleton< lock_table >::get_instance( );
402 lock_table::iterator ite = table.find( lock_name_ );
403 if( ite == table.end( ) )
404 {
405 // まだロックオブジェクトを初期化していないので初期化する
406 ::std::pair< lock_table::iterator, bool > p = table.insert( lock_table::value_type( lock_name_, lock_object_type( ) ) );
407 if( p.second )
408 {
409 lock_object_type &obj = p.first->second;
410 initialize( obj );
411
412 // テーブル検索用のロックを開放する
413 unlock( __double_lock__ );
414
415 lock( obj );
416 }
417 else
418 {
419 // テーブル検索用のロックを開放する
420 unlock( __double_lock__ );
421
422 // ロックオブジェクトをテーブルに追加することができませんでした・・・
423 return( false );
424 }
425 }
426 else
427 {
428 // テーブル検索用のロックを開放する
429 unlock( __double_lock__ );
430
431 // すでに同名のロックオブジェクトが存在するのでそちらをロックする
432 lock( ite->second );
433 }
434
435 return( true );
436 }
437
438 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
439
440
441
442
443
444
445
446 bool try_lock( )
447 {
448 static lock_object_type &__double_lock__ = double_lock_object( );
449
450 // テーブルの検索でスレッドが衝突しないようにロックする
451 lock( __double_lock__ );
452
453 lock_table &table = singleton< lock_table >::get_instance( );
454 lock_table::iterator ite = table.find( lock_name_ );
455 if( ite == table.end( ) )
456 {
457 // まだロックオブジェクトを初期化していないので初期化する
458 ::std::pair< lock_table::iterator, bool > p = table.insert( lock_table::value_type( lock_name_, lock_object_type( ) ) );
459 if( p.second )
460 {
461 lock_object_type &obj = p.first->second;
462 initialize( obj );
463
464 // テーブル検索用のロックを開放する
465 unlock( __double_lock__ );
466
467 return( try_lock( obj ) );
468 }
469 else
470 {
471 // テーブル検索用のロックを開放する
472 unlock( __double_lock__ );
473
474 // ロックオブジェクトをテーブルに追加することができませんでした・・・
475 return( false );
476 }
477 }
478 else
479 {
480 // テーブル検索用のロックを開放する
481 unlock( __double_lock__ );
482
483 // すでに同名のロックオブジェクトが存在するのでそちらをロックする
484 return( try_lock( ite->second ) );
485 }
486 }
487 #endif
488
490 bool unlock( )
491 {
492 lock_table &table = singleton< lock_table >::get_instance( );
493 lock_table::iterator ite = table.find( lock_name_ );
494 if( ite == table.end( ) )
495 {
496 // 指定されたロックオブジェクトが見つからなかったので何もしない
497 return( false );
498 }
499 else
500 {
501 unlock( ite->second );
502 }
503 return( true );
504 }
505
506 #endif
507
508
509 protected:
511 static lock_object_type &double_lock_object( )
512 {
513 static bool isFirst = true;
514 static lock_object_type __double_lock__;
515 if( isFirst )
516 {
517 isFirst = false;
518 initialize( __double_lock__ );
519 }
520 return( __double_lock__ );
521 }
522
527 static void initialize( lock_object_type &l )
528 {
529 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
530 // スレッドサポートはしないので特に必何もしない
531 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
532 InitializeCriticalSection( &l ); // クリティカルセクションオブジェクトを初期化
533 #else
534 pthread_mutex_init( &l, NULL ); // pthread用のMutexオブジェクトを初期化
535 #endif
536 }
537
538
543 static void lock( lock_object_type &l )
544 {
545 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
546 // スレッドサポートはしないので特に必何もしない
547 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
548 EnterCriticalSection( &l ); // クリティカルセクションオブジェクトをロック
549 #else
550 pthread_mutex_lock( &l ); // pthread用のMutexオブジェクトをロック
551 #endif
552 }
553
554 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
555
556
557
558
559
560
561
562
563
564 static bool try_lock( lock_object_type &l )
565 {
566 // クリティカルセクションオブジェクトのロックが可能かを調べる
567 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
568 // スレッドサポートはしないので特に必何もしない
569 return( true );
570 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
571 return( TryEnterCriticalSection( &l ) != FALSE );
572 #else
573 return( pthread_mutex_trylock( &l ) == 0 );
574 #endif
575 }
576 #endif
577
582 static void unlock( lock_object_type &l )
583 {
584 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
585 // スレッドサポートはしないので特に必何もしない
586 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
587 LeaveCriticalSection( &l ); // クリティカルセクションオブジェクトをアンロック
588 #else
589 pthread_mutex_unlock( &l ); // pthread用のMutexオブジェクトをアンロック
590 #endif
591 }
592 };
593
594
595
596
611 class lock
612 {
613 protected:
614 lock_object lock_object_;
615
616 public:
618 lock( ) : lock_object_( )
619 {
620 lock_object_.lock( );
621 }
622
623
625 lock( const std::string &name ) : lock_object_( name )
626 {
627 lock_object_.lock( );
628 }
629
630
632 ~lock( )
633 {
634 lock_object_.unlock( );
635 }
636 };
637
638
639 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
640
641 class signal
642 {
643 protected:
644 HANDLE handle_;
645
646 public:
648 signal( ) : handle_( CreateEvent( NULL, FALSE, FALSE, NULL ) )
649 {
650 }
651
653 ~signal( )
654 {
655 CloseHandle( handle_ );
656 }
657
659 bool wait( unsigned long dwMilliseconds = INFINITE )
660 {
661 DWORD ret = WaitForSingleObject( handle_, dwMilliseconds );
662 if( SUCCEEDED( ret ) )
663 {
664 ResetEvent( handle_ );
665 return ( true );
666 }
667 else
668 {
669 return( false );
670 }
671 }
672
674 void send( )
675 {
676 SetEvent( handle_ );
677 }
678
680 void reset( )
681 {
682 ResetEvent( handle_ );
683 }
684 };
685 #else
686 class signal
687 {
688 protected:
689 pthread_cond_t cond_;
690 pthread_mutex_t mutex_;
691 volatile bool flag_;
692
693 public:
695 signal( ) : flag_( false )
696 {
697 pthread_mutex_init( &mutex_, NULL );
698 pthread_cond_init( &cond_, NULL );
699 pthread_mutex_lock ( &mutex_ );
700 }
701
703 ~signal( )
704 {
705 pthread_cond_destroy( &cond_ );
706 pthread_mutex_destroy( &mutex_ );
707 }
708
710 bool wait( unsigned long dwMilliseconds = INFINITE )
711 {
712 if( dwMilliseconds == INFINITE )
713 {
714 while( !flag_ )
715 {
716 if( pthread_cond_wait( &cond_, &mutex_ ) == 0 )
717 {
718 break;
719 }
720 }
721 flag_ = false;
722 return( true );
723 }
724 else
725 {
726 timeval now;
727 gettimeofday( &now, NULL );
728
729 timespec tm;
730 tm.tv_sec = now.tv_sec + static_cast< time_t >( dwMilliseconds / 1000 );
731 tm.tv_nsec = now.tv_usec * 1000 + static_cast< long >( ( dwMilliseconds % 1000 ) * 1000000 );
732
733 tm.tv_sec += tm.tv_nsec / 1000000000;
734 tm.tv_nsec = tm.tv_nsec % 1000000000;
735
736 while( !flag_ )
737 {
738 if( pthread_cond_timedwait( &cond_, &mutex_, &tm ) == 0 )
739 {
740 break;
741 }
742 else
743 {
744 return( false );
745 }
746 }
747
748 flag_ = false;
749 return( true );
750 }
751 }
752
754 void send( )
755 {
756 flag_ = true;
757 pthread_cond_broadcast( &cond_ );
758 }
759
761 void reset( )
762 {
763 flag_ = false;
764 }
765 };
766 #endif
767
768
777 template < class thread_parameter = thread_dmy_class >
778 class thread : public thread_object
779 {
780 public:
781 typedef unsigned long thread_exit_type;
782
783 private:
784
785 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
786 // スレッドサポートはしないので特に必要な変数は無し
787 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
788 HANDLE thread_handle_; // Windows用のスレッドを識別するハンドル
789 unsigned int thread_id_; // Windows用のスレッドを識別するID
790 #else
791 pthread_t thread_id_; // pthreadライブラリでスレッドを識別するID
792 signal finish_; // スレッドの終了待ちを行うシグナル
793 bool joined_; // スレッドに対する pthread_join 処理が終了しているかどうか
794 #endif
795
796 simple_lock_object exit_; // 終了待ちシグナル
797 thread_exit_type thread_exit_code_; // スレッドの戻り値
798
799 public:
800
802 thread_exit_type exit_code( ) const { return( thread_exit_code_ ); }
803
804
813 const thread &operator =( const thread &t )
814 {
815 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
816 // スレッドサポートはしない
817 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
818 thread_handle_ = t.thread_handle_;
819 thread_id_ = t.thread_id_;
820 #else
821 thread_id_ = t.thread_id_;
822 joined_ = t.joined_;
823 #endif
824 thread_exit_code_ = t.thread_exit_code_;
825 return( *this );
826 }
827
828
838 bool operator ==( const thread &t ) const
839 {
840 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
841 // スレッドサポートはしない
842 return( this == &t );
843 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
844 return( thread_id_ == t.thread_id_ );
845 #else
846 return( pthread_equal( thread_id_, t.thread_id_ ) != 0 );
847 #endif
848 }
849
850 bool operator !=( const thread &t ) const
851 {
852 return( !( *this == t ) );
853 }
854
855
856 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
857 // スレッドサポートはしない
858 thread( const thread &t ) : thread_exit_code_( t.thread_exit_code_ ){ }
859 thread( ) : thread_exit_code_( 0 ){ }
860 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
861 thread( const thread &t ) : thread_handle_( t.thread_handle_ ), thread_id_( t.thread_id_ ), thread_exit_code_( t.thread_exit_code_ ){ }
862 thread( ) : thread_handle_( NULL ), thread_id_( ( unsigned int )-1 ), thread_exit_code_( 0 ){ }
863 #else
864 thread( const thread &t ) : thread_id_( t.thread_id ), joined_( false ), thread_exit_code_( t.thread_exit_code ){ }
865 thread( ) : thread_id_( ( pthread_t ) ( -1 ) ), joined_( false ), thread_exit_code_( 0 ){ }
866 #endif
867
868 virtual ~thread( )
869 {
870 this->close( );
871 }
872
873
879 virtual bool create( )
880 {
881 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
882 // スレッドサポートはしないので直接関数を呼び出す
883 bool ret = true;
884 thread_exit_code_ = thread_function( );
885 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
886 if( thread_handle_ != NULL ) return( false );
887 thread_handle_ = ( HANDLE )_beginthreadex( NULL, 0, map_thread_function, ( void * )this, 0, &thread_id_ );
888 bool ret = thread_handle_ != NULL ? true : false;
889 #else
890 if( thread_id_ != ( pthread_t ) ( -1 ) ) return( false );
891 bool ret = pthread_create( &( thread_id_ ), NULL, map_thread_function, ( void * )this ) == 0 ? true : false;
892 joined_ = false;
893 #endif
894
895 return ( ret );
896 }
897
898
904 virtual bool create_without_thread( )
905 {
906 thread_exit_code_ = thread_function( );
907 return ( true );
908 }
909
910
920 virtual bool wait( unsigned long dwMilliseconds = INFINITE )
921 {
922 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
923 // スレッドサポートはしないので何もしない
924 // スレッドかされないため，dwMilliseconds は常に INFINITE 扱いとなる
925 return( true );
926 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
927 DWORD ret = WaitForSingleObject( thread_handle_, dwMilliseconds );
928 return ( ret == WAIT_OBJECT_0 );
929 #else
930 if( dwMilliseconds == INFINITE )
931 {
932 if( pthread_join( thread_id_, NULL ) == 0 )
933 {
934 joined_ = true;
935 return( true );
936 }
937 else
938 {
939 return( false );
940 }
941 }
942 else
943 {
944 if( finish_.wait( dwMilliseconds ) )
945 {
946 if( pthread_join( thread_id_, NULL ) == 0 )
947 {
948 joined_ = true;
949 return( true );
950 }
951 else
952 {
953 return( false );
954 }
955 }
956 else
957 {
958 return( false );
959 }
960 }
961 #endif
962 }
963
964
972 virtual bool close( )
973 {
974 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
975 // スレッドサポートはしないので常に true を返す
976 return( true );
977 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
978 if( thread_handle_ != NULL )
979 {
980 // スレッドの完全終了を待機する
981 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
982 while( !exit_.try_lock( ) ){}
983 exit_.unlock( );
984 #endif
985
986 BOOL ret = CloseHandle( thread_handle_ );
987 thread_handle_ = NULL;
988 return ( ret != 0 );
989 }
990 else
991 {
992 return( true );
993 }
994 #else
995 if( thread_id_ != ( pthread_t ) ( -1 ) )
996 {
997 // スレッドの完全終了を待機する
998 while( !exit_.try_lock( ) ){}
999 exit_.unlock( );
1000
1001 if( !joined_ )
1002 {
1003 pthread_join( thread_id_, NULL );
1004 }
1005
1006 thread_id_ = ( pthread_t ) ( -1 );
1007 return( true );
1008 }
1009 else
1010 {
1011 return( true );
1012 }
1013 #endif
1014 }
1015
1016
1017 protected:
1025 virtual thread_exit_type thread_function( ) = 0;
1026
1027
1028 #if !defined( _MIST_THREAD_SUPPORT_ ) || _MIST_THREAD_SUPPORT_ == 0
1029 // スレッドサポートはしないので何もしない
1030 #elif defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
1031 static unsigned int __stdcall map_thread_function( void *p )
1032 {
1033 thread *obj = static_cast< thread * >( p );
1034 obj->exit_.lock( );
1035 obj->thread_exit_code_ = obj->thread_function( );
1036 obj->exit_.unlock( );
1037 return( 0 );
1038 }
1039 #else
1040 static void *map_thread_function( void *p )
1041 {
1042 thread *obj = static_cast< thread * >( p );
1043 obj->exit_.lock( );
1044 obj->thread_exit_code_ = obj->thread_function( );
1045 obj->exit_.unlock( );
1046 obj->finish_.send( );
1047 return ( NULL );
1048 }
1049 #endif
1050 };
1051
1052
1062 template < class Thread >
1063 inline bool do_threads_( Thread *threads, size_t num_threads, unsigned long dwMilliseconds = INFINITE )
1064 {
1065 bool ret = true;
1066 size_t i = 0;
1067
1068 // スレッドの生成
1069 for( i = 1 ; i < num_threads ; i++ )
1070 {
1071 if( !threads[ i ].create( ) )
1072 {
1073 ret = false;
1074 }
1075 }
1076 if( num_threads > 0 )
1077 {
1078 // 先頭のパラメータのみ実行スレッドで行う
1079 threads[ 0 ].create_without_thread( );
1080 }
1081
1082 // スレッドの終了待ち
1083 for( i = 1 ; i < num_threads ; i++ )
1084 {
1085 if( !threads[ i ].wait( dwMilliseconds ) )
1086 {
1087 ret = false;
1088 }
1089 }
1090
1091 // リソースの開放
1092 for( i = 1 ; i < num_threads ; i++ )
1093 {
1094 if( !threads[ i ].close( ) )
1095 {
1096 ret = false;
1097 }
1098 }
1099
1100 return( ret );
1101 }
1102
1112 template < class Thread >
1113 inline bool do_threads_( Thread **threads, size_t num_threads, unsigned long dwMilliseconds = INFINITE )
1114 {
1115 bool ret = true;
1116 size_t i = 0;
1117
1118 // スレッドの生成
1119 for( i = 1 ; i < num_threads ; i++ )
1120 {
1121 if( !threads[ i ]->create( ) )
1122 {
1123 ret = false;
1124 }
1125 }
1126 if( num_threads > 0 )
1127 {
1128 // 先頭のパラメータのみ実行スレッドで行う
1129 threads[ 0 ]->create_without_thread( );
1130 }
1131
1132 // スレッドの終了待ち
1133 for( i = 1 ; i < num_threads ; i++ )
1134 {
1135 if( !threads[ i ]->wait( dwMilliseconds ) )
1136 {
1137 ret = false;
1138 }
1139 }
1140
1141 // リソースの開放
1142 for( i = 1 ; i < num_threads ; i++ )
1143 {
1144 if( !threads[ i ]->close( ) )
1145 {
1146 ret = false;
1147 }
1148 }
1149
1150 return( ret );
1151 }
1152
1153
1154
1164 template < class Thread >
1165 inline bool do_threads( Thread *threads, size_t num_threads, unsigned long dwMilliseconds = INFINITE )
1166 {
1167 bool ret = true;
1168 size_t i = 0;
1169
1170 // スレッドの生成
1171 for( i = 0 ; i < num_threads ; i++ )
1172 {
1173 if( !threads[ i ].create( ) )
1174 {
1175 ret = false;
1176 }
1177 }
1178
1179 // スレッドの終了待ち
1180 for( i = 0 ; i < num_threads ; i++ )
1181 {
1182 if( !threads[ i ].wait( dwMilliseconds ) )
1183 {
1184 ret = false;
1185 }
1186 }
1187
1188 // リソースの開放
1189 for( i = 0 ; i < num_threads ; i++ )
1190 {
1191 if( !threads[ i ].close( ) )
1192 {
1193 ret = false;
1194 }
1195 }
1196
1197 return( ret );
1198 }
1199
1200
1202 // スレッドグループの終わり
1203
1204 // スレッドを普通の関数形式の呼び出しで簡便に利用するための関数群
1205 namespace __thread_controller__
1206 {
1207 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
1208 inline unsigned long _timeGetTime_( )
1209 {
1210 return( timeGetTime( ) );
1211 }
1212 #else
1213 inline unsigned long _timeGetTime_( )
1214 {
1215 timeval dmy;
1216 gettimeofday( &dmy, NULL );
1217 return( dmy.tv_sec );
1218 }
1219 #endif
1220
1221 template < class Param, class Functor >
1222 class thread_object_functor : public thread< thread_object_functor< Param, Functor > >
1223 {
1224 public:
1225 typedef thread< thread_object_functor< Param, Functor > > base;
1226 typedef typename base::thread_exit_type thread_exit_type;
1227
1228 private:
1229 Param &param_;
1230 Functor func_;
1231
1232 public:
1233 thread_object_functor( Param &p, Functor f ) : param_( p ), func_( f ){ }
1234 virtual ~thread_object_functor( ){ }
1235
1236 protected:
1237 // 継承した先で必ず実装されるスレッド関数
1238 virtual thread_exit_type thread_function( )
1239 {
1240 func_( param_ );
1241 return( 0 );
1242 }
1243 };
1244
1245 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
1246 struct __thread_pool_functor__
1247 {
1248 typedef size_t size_type;
1249 typedef ptrdiff_t difference_type;
1250
1251 virtual void run( size_type id, size_type nthreads ) = 0;
1252
1253 virtual ~__thread_pool_functor__( ){}
1254 };
1255
1256 template < class Param, class Functor >
1257 class thread_pool_functor_base : public __thread_pool_functor__
1258 {
1259 private:
1260 Param param_;
1261 Functor func_;
1262
1263 public:
1264 thread_pool_functor_base( Param p, Functor f ) : param_( p ), func_( f ){ }
1265 virtual ~thread_pool_functor_base( ){}
1266
1267 protected:
1268 // 継承した先で必ず実装されるスレッド関数
1269 virtual void run( size_type /* id */, size_type /* nthreads */ )
1270 {
1271 func_( param_ );
1272 }
1273 };
1274
1275 template < class Param1, class Param2, class Functor >
1276 class thread_pool_functor_base2 : public __thread_pool_functor__
1277 {
1278 private:
1279 Param1 param1_;
1280 Param2 param2_;
1281 Functor func_;
1282
1283 public:
1284 thread_pool_functor_base2( Param1 p1, Param2 p2, Functor f ) : param1_( p1 ), param2_( p2 ), func_( f ){ }
1285 virtual ~thread_pool_functor_base2( ){ }
1286
1287 protected:
1288 // 継承した先で必ず実装されるスレッド関数
1289 virtual void run( size_type /* id */, size_type /* nthreads */ )
1290 {
1291 func_( param1_, param2_ );
1292 }
1293 };
1294
1295 template < class Param1, class Param2, class Param3, class Functor >
1296 class thread_pool_functor_base3 : public __thread_pool_functor__
1297 {
1298 private:
1299 Param1 param1_;
1300 Param2 param2_;
1301 Param3 param3_;
1302 Functor func_;
1303
1304 public:
1305 thread_pool_functor_base3( Param1 p1, Param2 p2, Param3 p3, Functor f ) : param1_( p1 ), param2_( p2 ), param3_( p3 ), func_( f ){ }
1306 virtual ~thread_pool_functor_base3( ){ }
1307
1308 protected:
1309 // 継承した先で必ず実装されるスレッド関数
1310 virtual void run( size_type /* id */, size_type /* nthreads */ )
1311 {
1312 func_( param1_, param2_, param3_ );
1313 }
1314 };
1315
1316 template < class Param1, class Param2, class Param3, class Param4, class Functor >
1317 class thread_pool_functor_base4 : public __thread_pool_functor__
1318 {
1319 private:
1320 Param1 param1_;
1321 Param2 param2_;
1322 Param3 param3_;
1323 Param4 param4_;
1324 Functor func_;
1325
1326 public:
1327 thread_pool_functor_base4( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Functor f ) : param1_( p1 ), param2_( p2 ), param3_( p3 ), param4_( p4 ), func_( f ){ }
1328 virtual ~thread_pool_functor_base4( ){ }
1329
1330 protected:
1331 // 継承した先で必ず実装されるスレッド関数
1332 virtual void run( size_type /* id */, size_type /* nthreads */ )
1333 {
1334 func_( param1_, param2_, param3_, param4_ );
1335 }
1336 };
1337
1338
1339 template < class Functor >
1340 class thread_pool_void_functor_base : public __thread_pool_functor__
1341 {
1342 private:
1343 Functor func_;
1344
1345 public:
1346 thread_pool_void_functor_base( Functor f ) : func_( f ){ }
1347 virtual ~thread_pool_void_functor_base( ){ }
1348
1349 protected:
1350 // 継承した先で必ず実装されるスレッド関数
1351 virtual void run( size_type /* id */, size_type /* nthreads */ )
1352 {
1353 func_( );
1354 }
1355 };
1356
1357 class thread_pool_functor : public thread< thread_pool_functor >
1358 {
1359 public:
1360 typedef thread< thread_pool_functor > base;
1361 typedef base::thread_exit_type thread_exit_type;
1362 typedef size_t size_type;
1363 typedef ptrdiff_t difference_type;
1364
1365 private:
1366 std::list< __thread_pool_functor__ * > &functors_;
1367 simple_lock_object &lock_;
1368 simple_lock_object suspend_lock_;
1369 simple_lock_object wait_lock_;
1370 bool is_running_;
1371 bool is_end_;
1372 size_type id_;
1373 size_type nthreads_;
1374 signal signal_;
1375
1376 public:
1377 thread_pool_functor( std::list< __thread_pool_functor__ * > &functors, simple_lock_object &l, size_type id, size_type nthreads )
1378 : functors_( functors ), lock_( l ), is_running_( false ), is_end_( false ), id_( id ), nthreads_( nthreads )
1379 {
1380 // ロックした状態でスタートする
1381 suspend_lock_.lock( );
1382 }
1383
1384 virtual ~thread_pool_functor( ){ }
1385
1386 size_type num_jobs( ) const { return( functors_.size( ) ); }
1387 bool is_end( ) const { return( is_end_ ); }
1388
1389 bool is_suspended( )
1390 {
1391 if( wait_lock_.try_lock( ) )
1392 {
1393 wait_lock_.unlock( );
1394 return( true );
1395 }
1396 else
1397 {
1398 return( false );
1399 }
1400 }
1401
1402 virtual bool create( )
1403 {
1404 if( base::create( ) )
1405 {
1406 // スレッドの開始まで待機する
1407 while( true )
1408 {
1409 lock_.lock( );
1410 if( is_running_ )
1411 {
1412 lock_.unlock( );
1413 break;
1414 }
1415 else
1416 {
1417 lock_.unlock( );
1418 }
1419 }
1420
1421 return( true );
1422 }
1423 else
1424 {
1425 return( false );
1426 }
1427 }
1428
1429 virtual bool close( )
1430 {
1431 lock_.lock( );
1432 // 終了フラグを立ててスレッドを再起動する
1433 is_end_ = true;
1434 this->resume( );
1435 lock_.unlock( );
1436
1437 // スレッドが正常終了するまで待つ
1438 while( !wait_lock_.try_lock( ) ){}
1439 wait_lock_.unlock( );
1440
1441 return( base::close( ) );
1442 }
1443
1444 void resume( )
1445 {
1446 if( is_suspended( ) )
1447 {
1448 suspend_lock_.unlock( );
1449 while( wait_lock_.try_lock( ) )
1450 {
1451 wait_lock_.unlock( );
1452 }
1453 suspend_lock_.lock( );
1454 }
1455 }
1456
1457 bool wait( unsigned long dwMilliseconds = INFINITE )
1458 {
1459 lock_.lock( );
1460 if( !wait_lock_.try_lock( ) )
1461 {
1462 lock_.unlock( );
1463 return( signal_.wait( dwMilliseconds ) );
1464 }
1465 else
1466 {
1467 wait_lock_.unlock( );
1468 lock_.unlock( );
1469 return( true );
1470 }
1471 }
1472
1473 protected:
1474 // 継承した先で必ず実装されるスレッド関数
1475 virtual thread_exit_type thread_function( )
1476 {
1477 wait_lock_.lock( );
1478
1479 lock_.lock( );
1480 is_running_ = true;
1481 lock_.unlock( );
1482
1483 while( true )
1484 {
1485 lock_.lock( );
1486 if( is_end_ )
1487 {
1488 lock_.unlock( );
1489 break;
1490 }
1491 else if( functors_.empty( ) )
1492 {
1493 // 処理待ちをする
1494 wait_lock_.unlock( );
1495 lock_.unlock( );
1496 signal_.send( );
1497 suspend_lock_.lock( );
1498 signal_.reset( );
1499 wait_lock_.lock( );
1500 suspend_lock_.unlock( );
1501 }
1502 else
1503 {
1504 // キューの先頭からデータを取り出す
1505 __thread_pool_functor__ *f = functors_.front( );
1506 functors_.pop_front( );
1507 lock_.unlock( );
1508
1509 if( f != NULL )
1510 {
1511 f->run( id_, nthreads_ );
1512 delete f;
1513 }
1514 }
1515 }
1516
1517 wait_lock_.unlock( );
1518 signal_.send( );
1519
1520 return( 0 );
1521 }
1522 };
1523 #endif
1524 }
1525
1526
1530
1531 #if defined( __THREAD_POOL_SUPPORT__ ) && __THREAD_POOL_SUPPORT__ != 0
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563 class thread_pool
1564 {
1565 public:
1566 typedef size_t size_type;
1567 typedef ptrdiff_t difference_type;
1568
1569 private:
1570 typedef __thread_controller__::thread_pool_functor thread_pool_functor;
1571 typedef __thread_controller__::__thread_pool_functor__ __thread_pool_functor__;
1572
1573 std::vector< thread_pool_functor * > threads_;
1574 std::list< __thread_pool_functor__ * > functors_;
1575 simple_lock_object lock_;
1576 bool initialized_;
1577
1578 public:
1580 thread_pool( ) : initialized_( false )
1581 {
1582 }
1583
1585 thread_pool( size_type number_of_max_threads ) : initialized_( false )
1586 {
1587 initialize( number_of_max_threads );
1588 }
1589
1591 virtual ~thread_pool( )
1592 {
1593 uninitialize( );
1594 }
1595
1602 bool initialize( size_type number_of_max_threads )
1603 {
1604 // 現在実行中のスレッドを全て終了させる
1605 uninitialize( );
1606
1607 if( number_of_max_threads == 0 )
1608 {
1609 // 1以上を指定する必要あり
1610 return( false );
1611 }
1612
1613 threads_.resize( number_of_max_threads );
1614
1615 // スレッドを実行してアイドル状態にする
1616 for( size_type i = 0 ; i < threads_.size( ) ; i++ )
1617 {
1618 threads_[ i ] = new thread_pool_functor( functors_, lock_, i, threads_.size( ) );
1619 threads_[ i ]->create( );
1620 //threads_[ i ]->wait( );
1621 }
1622
1623 initialized_ = true;
1624
1625 return( true );
1626 }
1627
1632 bool uninitialize( )
1633 {
1634 if( initialized_ )
1635 {
1636 for( size_type i = 0 ; i < threads_.size( ) ; i++ )
1637 {
1638 // スレッドのハンドルを閉じる
1639 threads_[ i ]->close( );
1640
1641 // 使用していたメモリ領域を開放する
1642 delete threads_[ i ];
1643 }
1644
1645 threads_.clear( );
1646
1647 // キューに残っているデータを削除する
1648 lock_.lock( );
1649 while( !functors_.empty( ) )
1650 {
1651 __thread_pool_functor__ *f = functors_.front( );
1652 functors_.pop_front( );
1653 delete f;
1654 }
1655 lock_.unlock( );
1656 }
1657
1658 initialized_ = false;
1659
1660 return( true );
1661 }
1662
1671 template < class Functor, class Param >
1672 bool execute( Functor f, Param p )
1673 {
1674 if( threads_.empty( ) || !initialized_ )
1675 {
1676 return( false );
1677 }
1678
1679 return( exec( new __thread_controller__::thread_pool_functor_base< Param, Functor >( p, f ) ) );
1680 }
1681
1691 template < class Functor, class Param1, class Param2 >
1692 bool execute( Functor f, Param1 p1, Param2 p2 )
1693 {
1694 if( threads_.empty( ) || !initialized_ )
1695 {
1696 return( false );
1697 }
1698
1699 return( exec( new __thread_controller__::thread_pool_functor_base2< Param1, Param2, Functor >( p1, p2, f ) ) );
1700 }
1701
1712 template < class Functor, class Param1, class Param2, class Param3 >
1713 bool execute( Functor f, Param1 p1, Param2 p2, Param3 p3 )
1714 {
1715 if( threads_.empty( ) || !initialized_ )
1716 {
1717 return( false );
1718 }
1719
1720 return( exec( new __thread_controller__::thread_pool_functor_base3< Param1, Param2, Param3, Functor >( p1, p2, p3, f ) ) );
1721 }
1722
1734 template < class Functor, class Param1, class Param2, class Param3, class Param4 >
1735 bool execute( Functor f, Param1 p1, Param2 p2, Param3 p3, Param4 p4 )
1736 {
1737 if( threads_.empty( ) || !initialized_ )
1738 {
1739 return( false );
1740 }
1741
1742 return( exec( new __thread_controller__::thread_pool_functor_base4< Param1, Param2, Param3, Param4, Functor >( p1, p2, p3, p4, f ) ) );
1743 }
1744
1751 template < class Functor >
1752 bool execute( Functor f )
1753 {
1754 if( threads_.empty( ) || !initialized_ )
1755 {
1756 return( false );
1757 }
1758
1759 return( exec( new __thread_controller__::thread_pool_void_functor_base< Functor >( f ) ) );
1760 }
1761
1771 template < class Functor, class Param >
1772 bool executes( Functor f, Param *param, size_t num_threads )
1773 {
1774 if( threads_.empty( ) || !initialized_ )
1775 {
1776 return( false );
1777 }
1778
1779 // キューに追加する
1780 lock_.lock( );
1781 for( size_type i = 0 ; i < num_threads ; i++ )
1782 {
1783 functors_.push_back( new __thread_controller__::thread_pool_functor_base< Param, Functor >( param[ i ], f ) );
1784 }
1785 lock_.unlock( );
1786
1787 resume_thread_from_queue( num_threads );
1788
1789 return( true );
1790 }
1791
1802 template < class Functor, class Param1, class Param2 >
1803 bool executes( Functor f, Param1 *param1, Param2 *param2, size_t num_threads )
1804 {
1805 if( threads_.empty( ) || !initialized_ )
1806 {
1807 return( false );
1808 }
1809
1810 // キューに追加する
1811 lock_.lock( );
1812 for( size_type i = 0 ; i < num_threads ; i++ )
1813 {
1814 functors_.push_back( new __thread_controller__::thread_pool_functor_base2< Param1, Param2, Functor >( param1[ i ], param2[ i ], f ) );
1815 }
1816 lock_.unlock( );
1817
1818 resume_thread_from_queue( num_threads );
1819
1820 return( true );
1821 }
1822
1834 template < class Functor, class Param1, class Param2, class Param3 >
1835 bool executes( Functor f, Param1 *param1, Param2 *param2, Param3 *param3, size_t num_threads )
1836 {
1837 if( threads_.empty( ) || !initialized_ )
1838 {
1839 return( false );
1840 }
1841
1842 // キューに追加する
1843 lock_.lock( );
1844 for( size_type i = 0 ; i < num_threads ; i++ )
1845 {
1846 functors_.push_back( new __thread_controller__::thread_pool_functor_base3< Param1, Param2, Param3, Functor >( param1[ i ], param2[ i ], param3[ i ], f ) );
1847 }
1848 lock_.unlock( );
1849
1850 resume_thread_from_queue( num_threads );
1851
1852 return( true );
1853 }
1854
1867 template < class Functor, class Param1, class Param2, class Param3, class Param4 >
1868 bool executes( Functor f, Param1 *param1, Param2 *param2, Param3 *param3, Param4 *param4, size_t num_threads )
1869 {
1870 if( threads_.empty( ) || !initialized_ )
1871 {
1872 return( false );
1873 }
1874
1875 // キューに追加する
1876 lock_.lock( );
1877 for( size_type i = 0 ; i < num_threads ; i++ )
1878 {
1879 functors_.push_back( new __thread_controller__::thread_pool_functor_base4< Param1, Param2, Param3, Param4, Functor >( param1[ i ], param2[ i ], param3[ i ], param4[ i ], f ) );
1880 }
1881 lock_.unlock( );
1882
1883 resume_thread_from_queue( num_threads );
1884
1885 return( true );
1886 }
1887
1898 virtual bool wait( unsigned long dwMilliseconds = INFINITE )
1899 {
1900 if( !initialized_ )
1901 {
1902 return( false );
1903 }
1904 else if( threads_.empty( ) )
1905 {
1906 return( false );
1907 }
1908
1909 unsigned long st = __thread_controller__::_timeGetTime_( );
1910 size_type i = 0;
1911 for( ; i < threads_.size( ) ; i++ )
1912 {
1913 if( !threads_[ i ]->wait( dwMilliseconds ) )
1914 {
1915 break;
1916 }
1917 else if( dwMilliseconds != INFINITE )
1918 {
1919 unsigned long ct = __thread_controller__::_timeGetTime_( );
1920 if( dwMilliseconds <= ct - st )
1921 {
1922 break;
1923 }
1924 else
1925 {
1926 dwMilliseconds -= ct - st;
1927 st = ct;
1928 }
1929 }
1930 }
1931
1932 return( i == threads_.size( ) );
1933 }
1934
1935 protected:
1940 bool exec( __thread_controller__::__thread_pool_functor__ *func )
1941 {
1942 // キューに追加する
1943 {
1944 // 排他制御する
1945 lock_.lock( );
1946 functors_.push_back( func );
1947 lock_.unlock( );
1948 }
1949
1950 resume_thread_from_queue( 1 );
1951
1952 return( true );
1953 }
1954
1959 void resume_thread_from_queue( size_type num_threads )
1960 {
1961 size_type count = 0;
1962 for( size_type i = 0 ; i < threads_.size( ) ; i++ )
1963 {
1964 thread_pool_functor &t = *threads_[ i ];
1965
1966 if( t.is_suspended( ) )
1967 {
1968 // アイドル状態のスレッドがあれば再開する
1969 t.resume( );
1970
1971 count++;
1972 }
1973
1974 if( count >= num_threads )
1975 {
1976 break;
1977 }
1978 }
1979 }
1980 };
1981
1982
1983
2009 class worker_thread
2010 {
2011 public:
2012 typedef size_t size_type;
2013 typedef ptrdiff_t difference_type;
2014
2015 private:
2016 __thread_controller__::thread_pool_functor *thread_;
2017 std::list< __thread_controller__::__thread_pool_functor__ * > functors_;
2018 simple_lock_object lock_;
2019
2020 public:
2022 worker_thread( ) : thread_( NULL )
2023 {
2024 thread_ = new __thread_controller__::thread_pool_functor( functors_, lock_, 0, 1 );
2025 thread_->create( );
2026 //thread_->wait( );
2027 }
2028
2030 virtual ~worker_thread( )
2031 {
2032 close( );
2033 }
2034
2036 bool is_suspended( )
2037 {
2038 if( thread_ == NULL )
2039 {
2040 return( true );
2041 }
2042
2043 return( thread_->is_suspended( ) );
2044 }
2045
2050 bool close( )
2051 {
2052 if( thread_ == NULL )
2053 {
2054 return( false );
2055 }
2056
2057 // スレッドのハンドルを閉じる
2058 thread_->close( );
2059
2060 // 使用していたメモリ領域を開放する
2061 delete thread_;
2062 thread_ = NULL;
2063
2064 // キューに残っているデータを削除する
2065 lock_.lock( );
2066 while( !functors_.empty( ) )
2067 {
2068 __thread_controller__::__thread_pool_functor__ *f = functors_.front( );
2069 functors_.pop_front( );
2070 delete f;
2071 }
2072 lock_.unlock( );
2073
2074 return( true );
2075 }
2076
2085 template < class Functor, class Param >
2086 bool execute( Functor f, Param p )
2087 {
2088 if( thread_ == NULL )
2089 {
2090 return( false );
2091 }
2092
2093 return( exec( new __thread_controller__::thread_pool_functor_base< Param, Functor >( p, f ) ) );
2094 }
2095
2096
2106 template < class Functor, class Param1, class Param2 >
2107 bool execute( Functor f, Param1 p1, Param2 p2 )
2108 {
2109 if( thread_ == NULL )
2110 {
2111 return( false );
2112 }
2113
2114 return( exec( new __thread_controller__::thread_pool_functor_base2< Param1, Param2, Functor >( p1, p2, f ) ) );
2115 }
2116
2127 template < class Functor, class Param1, class Param2, class Param3 >
2128 bool execute( Functor f, Param1 p1, Param2 p2, Param3 p3 )
2129 {
2130 if( thread_ == NULL )
2131 {
2132 return( false );
2133 }
2134
2135 return( exec( new __thread_controller__::thread_pool_functor_base3< Param1, Param2, Param3, Functor >( p1, p2, p3, f ) ) );
2136 }
2137
2149 template < class Functor, class Param1, class Param2, class Param3, class Param4 >
2150 bool execute( Functor f, Param1 p1, Param2 p2, Param3 p3, Param4 p4 )
2151 {
2152 if( thread_ == NULL )
2153 {
2154 return( false );
2155 }
2156
2157 return( exec( new __thread_controller__::thread_pool_functor_base4< Param1, Param2, Param3, Param4, Functor >( p1, p2, p3, p4, f ) ) );
2158 }
2159
2166 template < class Functor >
2167 bool execute( Functor f )
2168 {
2169 if( thread_ == NULL )
2170 {
2171 return( false );
2172 }
2173
2174 return( exec( new __thread_controller__::thread_pool_void_functor_base< Functor >( f ) ) );
2175 }
2176
2187 virtual bool wait( unsigned long dwMilliseconds = INFINITE )
2188 {
2189 if( thread_ == NULL )
2190 {
2191 return( true );
2192 }
2193 else
2194 {
2195 return( thread_->wait( dwMilliseconds ) );
2196 }
2197 }
2198
2199 protected:
2204 bool exec( __thread_controller__::__thread_pool_functor__ *func )
2205 {
2206 // キューに追加する
2207 {
2208 // 排他制御する
2209 lock_.lock( );
2210 functors_.push_back( func );
2211 lock_.unlock( );
2212 }
2213
2214 // スレッドを再開する
2215 thread_->resume( );
2216
2217
2218 return( true );
2219 }
2220 };
2221 #endif
2222
2224 class thread_handle
2225 {
2226 private:
2227 thread_object *thread_;
2228
2229 public:
2230
2232 bool create( ){ return( thread_ == NULL ? false : thread_->create( ) ); }
2233
2234
2239 bool wait( unsigned long dwMilliseconds = INFINITE ){ return( thread_ == NULL ? false : thread_->wait( dwMilliseconds ) ); }
2240
2241
2243 bool close( )
2244 {
2245 if( thread_ == NULL )
2246 {
2247 return( false );
2248 }
2249 bool b = thread_->close( );
2250 delete thread_;
2251 thread_ = NULL;
2252 return( b );
2253 }
2254
2255 public:
2256 thread_handle( ) : thread_( NULL ){ }
2257 thread_handle( thread_object *t ) : thread_( t ){ }
2258
2259 const thread_handle &operator =( const thread_handle &t )
2260 {
2261 if( &t != this )
2262 {
2263 thread_ = t.thread_;
2264 }
2265 return( *this );
2266 }
2267 };
2268
2309 template < class Param, class Functor >
2310 inline thread_handle create_thread( Param &param, Functor f )
2311 {
2312 thread_handle thread_( new __thread_controller__::thread_object_functor< Param, Functor >( param, f ) );
2313 thread_.create( );
2314 return( thread_ );
2315 }
2316
2324 template < class Param, class Functor >
2325 inline void create_threads( thread_handle *handles, Param *param, size_t num_threads, Functor f )
2326 {
2327 for( size_t i = 0 ; i < num_threads ; i++ )
2328 {
2329 handles[ i ] = thread_handle( new __thread_controller__::thread_object_functor< Param, Functor >( param[ i ], f ) );
2330 handles[ i ].create( );
2331 }
2332 }
2333
2334
2344 inline bool close_thread( thread_handle &thread_ ){ return( thread_.close( ) ); }
2345
2354 inline bool close_threads( thread_handle *handles, size_t num_threads )
2355 {
2356 bool ret = true;
2357 for( size_t i = 0 ; i < num_threads ; i++ )
2358 {
2359 if( !handles[ i ].close( ) )
2360 {
2361 ret = false;
2362 }
2363 }
2364 return( ret );
2365 }
2366
2367
2378 inline bool wait_thread( thread_handle &thread_, unsigned long dwMilliseconds = INFINITE ){ return( thread_.wait( dwMilliseconds ) ); }
2379
2389 inline bool wait_threads( thread_handle *handles, size_t num_threads, unsigned long dwMilliseconds = INFINITE )
2390 {
2391 if( dwMilliseconds == INFINITE )
2392 {
2393 bool ret = true;
2394 for( size_t i = 0 ; i < num_threads ; i++ )
2395 {
2396 if( !handles[ i ].wait( INFINITE ) )
2397 {
2398 ret = false;
2399 }
2400 }
2401 return( ret );
2402 }
2403 else
2404 {
2405 bool ret = true;
2406 for( size_t i = 0 ; i < num_threads ; i++ )
2407 {
2408 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
2409 DWORD st = timeGetTime( );
2410 #else
2411 timeval dmy;
2412 gettimeofday( &dmy, NULL );
2413 unsigned long st = dmy.tv_sec * 1000 + dmy.tv_usec / 1000;
2414 #endif
2415 if( !handles[ i ].wait( dwMilliseconds ) )
2416 {
2417 ret = false;
2418 }
2419
2420 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
2421 DWORD et = timeGetTime( );
2422 #else
2423 gettimeofday( &dmy, NULL );
2424 unsigned long et = dmy.tv_sec * 1000 + dmy.tv_usec / 1000;
2425 #endif
2426
2427 if( st + dwMilliseconds <= et )
2428 {
2429 break;
2430 }
2431 else
2432 {
2433 dwMilliseconds -= et - st;
2434 }
2435 }
2436 return( ret );
2437 }
2438 }
2439
2440
2450 template < class Param, class Functor >
2451 inline bool do_thread( Param &param, Functor f, unsigned long dwMilliseconds = INFINITE )
2452 {
2453 bool ret = true;
2454
2455 // スレッドの生成
2456 thread_handle thread_ = create_thread( param, f );
2457
2458 // スレッドの終了待ち
2459 if( !wait_thread( thread_, dwMilliseconds ) )
2460 {
2461 ret = false;
2462 }
2463
2464 // リソースの開放
2465 if( !close_thread( thread_ ) )
2466 {
2467 ret = false;
2468 }
2469 return( ret );
2470 }
2471
2472
2483 template < class Param, class Functor >
2484 inline bool do_threads( Param *params, size_t num_threads, Functor f, unsigned long dwMilliseconds = INFINITE )
2485 {
2486 bool ret = true;
2487 thread_handle *threads_ = new thread_handle[ num_threads ];
2488
2489 // スレッドの生成
2490 create_threads( threads_, params, num_threads, f );
2491
2492 // スレッドの終了待ち
2493 if( !wait_threads( threads_, num_threads, dwMilliseconds ) )
2494 {
2495 ret = false;
2496 }
2497
2498 // リソースの開放
2499 if( !close_threads( threads_, num_threads ) )
2500 {
2501 ret = false;
2502 }
2503
2504 delete [] threads_;
2505
2506 return( ret );
2507 }
2508
2509
2511 // スレッドグループの終わり
2512
2513
2514 // mist名前空間の終わり
2515 _MIST_END
2516
2517
2518 #endif // __INCLUDE_MIST_THREAD__
2519