![]() | Programming Guide | WideStudio/MWT Index 目次 |
ロースレッド/セマフォ/ミューテックス
ロースレッドクラスを用いたスレッドの生成
WSDthread クラスを利用するとプログラム上からスレッドを生成することが できます。
btnop() 関数がボタンなどの押下により実行されるイベントプロシージャ本体です。 そのイベントプロシージャ上で WSDthread クラスのインスタンスを生成し、 スレッドとして実行する関数 thread_func() を指定し、 スレッド生成を行ないます。 また、スレッドとして動作する thread_func() 上から、execCallback() メンバ関数を 用いてメインスレッドにイベントを通知することができます。 execCallback() メンバ関数を呼び出すと、メインスレッド上で、 setCallbackFunction() メンバ関数で指定されたコールバック関数が動作し、 スレッドとメインスレッドと同期処理を行なうことができます。#include <WScom.h> #include <WSCfunctionList.h> #include <WSCbase.h> //---------------------------------------------------------- //Function for the event procedure //---------------------------------------------------------- WSDthread* thr = NULL; //サブスレッドとして実行する関数の定義 void* thread_func(WSDthread* obj,void* ptr){ long cnt= (long)ptr; while(1){ cnt++; obj->execCallback((void*)cnt); // メインスレッドへ通知 #ifdef MSW Sleep(1000); #else sleep(1); #endif } return NULL; } //スレッドから通知され、メインスレッドで実行されるコールバック void callback_func(WSDthread*,void* val){ long cnt = (long)val; //カウントアップされた内容を表示します。 newvbtn_000->setProperty(WSNlabelString,cnt); } //イベントプロシージャ。ボタン押下などで実行。 void btnop(WSCbase* object){ if (thr == NULL){ thr = WSDthread::getNewInstance(); thr->setFunction(thread_func); thr->setCallbackFunction(callback_func); thr->createThread((void*)100); }else{ exit(0); } }createThread() メンバ関数によって起動されたスレッド内では、 メインスレッドとは非同期のサブスレッドとして動作するため、 スレッドアンセーフであるWideStudio の GUI インスタンスに対して 排他制御無しに操作してはいけません。 WideStudio の GUI インスタンスに対して スレッド内で処理を行なった結果を表示させたい場合等は、 スレッドインスタンスに対して execCallback() メンバ関数を 用いて、 メインスレッドに通知する手段を用い、メインスレッド上で表示処理を 行ないます。ミューテックス
ミューテックスを用いて、複数のスレッドが動作するコードに対して、 同時に1スレッドしか、動作させないよう、排他することができます。 下記の例は、ロースレッドを用いて生成された複数のスレッドの実行される中、 同時に複数が実行されては困る処理に対して、 ミューテックスを用いて排他をかけている例です。#include <WScom.h> #include <WSCfunctionList.h> #include <WSCbase.h> #include <WSDthread.h> #include <WSDmutex.h> #include <stdlib.h> #include <unistd.h> //---------------------------------------------------------- //Function for the event procedure //---------------------------------------------------------- #include <newwin000.h> WSDmutex* mutex = NULL; static long cnt=0; //複数のサブスレッドとして実行する関数の定義 void* thread_func(WSDthread* obj,void*){ while(1){ mutex->lock(); cnt++; obj->execCallback((void*)cnt); // メインスレッドへ通知 #ifdef MSW Sleep(1000); #else sleep(1); #endif mutex->unlock(); } return NULL; } //スレッドから通知され、メインスレッドで実行されるコールバック void callback_func(WSDthread*,void* val){ long cnt = (long)val; //カウントアップされた内容を表示します。 newvbtn_000->setProperty(WSNlabelString,cnt); } //イベントプロシージャ。ボタン押下などで実行。 void btnop(WSCbase* object){ //do something... if (mutex == NULL){ //排他を行なうためのミューテックスを生成します。 mutex = WSDmutex::getNewInstance(); mutex->initialize(); //同時に10のスレッドを生成し、数値をカウントアップします。 long i; for(i=0; i<10; i++){ WSDthread* thr = WSDthread::getNewInstance(); thr->setFunction(thread_func); thr->setCallbackFunction(callback_func); thr->createThread((void*)0); } }else{ exit(0); } } static WSCfunctionRegister op("btnop",(void*)btnop);セマフォ
セマフォを用いて、 ミューテックスと同様な排他を行なう場合、または、複数のスレッドが 協調動作を行なうために待ち合わせを処理を行なうことが できます。 下記の例は、ロースレッドを用いて生成されたスレッドに対し、 セマフォを用いて待ち合わせを行なう例です。 ボタンを1度押下すると、スレッドを生成し、 セマフォを用いてスレッドを待機させます。 2度目の押下でセマフォを解除し、待機させておいたスレッドを動作を開始させます。#include <WScom.h> #include <WSCfunctionList.h> #include <WSCbase.h> #include <WSDthread.h> #include <WSDsemaphore.h> #include <stdlib.h> #include <unistd.h> //---------------------------------------------------------- //Function for the event procedure //---------------------------------------------------------- #include <newwin000.h> WSDsemaphore* sem = NULL; static long cnt=0; //スレッドとして動作する関数です。 void* thread_func(WSDthread* obj,void* val){ sem->lock(); //セマフォで待ち合わせをします。 while(1){ obj->execCallback((void*)cnt); #ifdef MSW Sleep(1000); #else sleep(1); #endif cnt++; } return NULL; } //スレッドから通知され、メインスレッドで実行されるコールバック void callback_func(WSDthread*,void* val){ long cnt = (long)val; //カウントアップされた内容を表示します。 newvbtn_000->setProperty(WSNlabelString,cnt); } //イベントプロシージャ。ボタン押下などで実行。 void btnop(WSCbase* object){ //do something... if (sem == NULL){ //セマフォを作成します。 sem = WSDsemaphore::getNewInstance(); sem->initialize(); sem->lock(); //スレッドを生成します。 WSDthread* thr = WSDthread::getNewInstance(); thr->setFunction(thread_func); thr->setCallbackFunction(callback_func); thr->createThread((void*)0); object->setProperty(WSNlabelString,"Start Thread"); }else{ //2度目の実行時にセマフォを解除し、待ち合わせていたスレッドを動作させます。 sem->unlock(); //start the waiting thread. } } static WSCfunctionRegister op("btnop",(void*)btnop);
Copyright(C) WideStudio/MWT Development Team, 1999-2005 | Last modified: Jul 31, 2005 |