WideStudio/MWT Logo
WideStudio/MWT
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);


Document Release 3.90 for WideStudio/MWT ver 3.90, Jul 2005


WideStudio/MWT documents index | 目次

Copyright(C) WideStudio/MWT Development Team, 1999-2005 Last modified: Jul 31, 2005