fc2ブログ

Win32並行処理プログラミング入門22

 この記事は、Win32並行処理プログラミング入門21の続きです。今回は、イベントカーネルオブジェクトについての解説を進めます。
 イベントカーネルオブジェクトとは、前回のサンプルで示したように、何かを知らせるためのカーネルオブジェクトです。何かとは、開発者が自由に決められます。例えば、前回のサンプルのように、データの準備が出来た事を表す事が出来ます。他にも、「待ち行列が空になった」などといった状態を知らせる使い方もあります。
 イベントカーネルオブジェクトを使用するには、先ずはCreateEvent関数、もしくはCreateEventEx関数を実行し、イベントカーネルのハンドルを入手しなくてはなりません。
 CreateEvent関数は以下の様に使います。

//前回のサンプルより抜粋
hEvent = CreateEvent ( 
        __nullptr, //セキュリティ属性 
        TRUE, //手動or自動
        FALSE, //初期時のシグナル状態
        _T("piyo") //イベントカーネルオブジェクトの名前
    );

第一パラメータのセキュリティ属性は、話しが長くなるので今回は解説しません。第二パラメータは、リセットイベントをどのように扱うかを示しています。
 第二パラメータへTRUEをセットすると、リセットイベントを手動で行う事になります。リセットイベントとは、イベントカーネルオブジェクトを非シグナル状態にする事です。FALSEを指定した場合は、待機スレッドが終了した時点で、イベントカーネルオブジェクトは自動的に非シグナル状態へ変わります。
 第三パラメータは、イベントカーネルオブジェクトの初期状態です。TRUEを指定すると、直ぐにシグナル状態となります。
 第四パラメータは、イベントカーネルオブジェクトの名前です。名前を付けると、イベントカーネルオブジェクトが識別できるようになります。

テーマ : プログラミング
ジャンル : コンピュータ

スレッド数決定問題14

 この記事は、スレッド数決定問題13の続きです。引き続き、最適なスレッド数を決定する方法について語ります。
 設計をする際には、従来のスレッドモデルの並行処理ではなく、インテルTBBの様な並列処理特有の考え方をする方が、設計の負担が少なくなります。インテルTBBの様な並列処理を扱う時は、この処理は並列化するというふうに抽象化して考えます。ただし、全てを並列化するなどというふうに、無目的な抽象化をしてはなりません。今まで述べてきたように、CPUという貴重なリソースを有効に使用するべきです。システムを設計する際には、局所的に常に並列化するのではなく、全体的にCPUの利用率が最適になる様に考えなくてはなりません。
 それを実現するには、実装を知らなくてはなりません。昨今はフレームワークなどがあるから詳細を知る必要がないと誤解している人々がいますが、それではプロとして通用しません。その技術がどのように実現されているのかを知って、初めてプロフェッショナルと言えるでしょう。
 それを考えると、昔よりも今の方が要求される情報量が増加しています。それに加えて、抽象化により思わぬ不利益を被ることもあります。例えば、個々のアプリケーションが無目的にCPUの全てのコアを使用する場合、2つのアプリケーションを立ち上げるだけで、PCに過負荷がかかってしまうかもしれません。
 どんな技術でもそうなのですが、過剰な使用は毒となります。特に並列化の場合、バグの発生率が高くなり、CPUへの負担が一気に高くなります。それを防ぐために、並列化の技術は高度に抽象化され、物理的なスレッドに直接対応していません。しかしながら、そうした論理スレッドを使用すると、今度は設計が難しくなります。
 今までと同じ考え方では、高度に抽象化されている並列処理の技術は使いこなせません。従来のスレッドモデルを使用した並行処理とは違う考え方が必要となります。続く...

テーマ : プログラミング
ジャンル : コンピュータ

実践的オブジェクト指向分析入門17

 この記事は、実践的オブジェクト指向分析入門16の続きです。前回は、オブジェクト指向分析と、セキュリティの関係を解説しました。今回は、オブジェクト指向分析と、データベースの関係について解説します。
 データベースエンジニアが、オブジェクト指向分析時にするべき事は、概念データモデルの作成です。業務分析によって導き出されたオブジェクトの中で、データベース化するべき対象を見極めます。データベースエンジニアは、企業にとって価値ある情報を見極める役割があるという事です。
 ここで注意しなくてはならないのは、データベースエンジニアの多くが、データ中心アプローチで考えている点です。データベースの主流は、リレーショナルデータベースです。ですからデータベースエンジニアは、自然とデータ中心アプローチで考える事に慣れています。このギャップに注意しなくてはなりません。
 オブジェクト指向とデータ中心アプローチのギャップを埋めるには、オブジェクトのデータに注意を払います。前に述べた通りで、オブジェクト指向だからと言って、データ中心アプローチの考え方が無駄というわけではありません。オブジェクトにもデータは存在し、そのデータを正規化する事は非常に大事です。データに注目すると、無駄なオブジェクトを発見したり、オブジェクトの対象が見極められたりする効果があります。
 実はオブジェクトとデータに共通する考えがあります。それは、集合理論です。オブジェクトもデータも集合として考えると、何の違和感もなくオブジェクト指向とデータ中心なプロ―チを同居させる事が出来ます。ただし、集合理論といっても厳密に考え過ぎると余計に分析できなくなります。
 数学的な考えは非常に役立ちます。しかしだからと言って、情報処理=数学でもないのです。情報処理と数学の共通部分はありますが、情報処理は情報処理なのです。集合理論を使用する事もその一環です。あくまでも思考の道具として扱わなくてはなりません。数学的発想に縛られては情報処理が出来ません。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

実践的オブジェクト指向分析入門16

 この記事は、実践的オブジェクト指向分析入門15の続きです。前回は、ネットワークとオブジェクト指向分析の関係を説明しました。今回は、セキュリティとオブジェクト指向分析の関係を説明します。
 今時のシステムは、セキュリティを避けては通れません。誤解される事が多いのですが、セキュリティは設計段階や実装段階ですればいいというものではありません。それでは遅すぎます。オブジェクト指向分析の段階で考え始めなくてはなりません。
 分析段階でセキュリティで考えねばならない事は、エンドユーザーが持つ情報の分析です。セキュリティは何でも拒否すればいいという単純なものではありません。100%のセキュリティとは何もしない状態です。何もしなければ安全ですが、企業の存在意義がなくなります。セキュリティは、情報の価値に基づいて実施せねばなりません。それには、早期の分析が必要なのです。
 既存システムがない会社でも情報が存在する事に注意して下さい。企業の情報は紙媒体に多く存在します。情報=電子とは限りません。情報は様々な媒体で存在します。エンドユーザーがその情報をどのように扱っているのか、その情報が漏れた場合のリスクは何か、その情報の価値はどのようなものなのかと言った事を分析します。
 エンドユーザーが既にセキュリティポリシーを持っている場合は、その分析を行い、持っていない場合はセキュリティポリシーを作るのに当たって必要な情報を収集します。セキュリティは、エンドユーザーの業務に直結する上に、そのありがたみが見えにくいものなので、エンドユーザーのセキュリティに関する理解度を把握する必要もあります。
 セキュリティの重要さは、昨今認識され始めています。しかしながら、エンドユーザーは余りセキュリティを知らないので、セキュリティを知ってもらうためになるべく早くから手を打ちましょう。そして、セキュリティは、人とコンピューターの双方の連携によって成り立ちます。技術者は機械の方ばかり目が行く傾向がありますが、人がセキュリティホールになるケースが多いです。機会にも人の心にもセキュリティ対策をするべく、広範囲かつ素早い分析活動が必要となります。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

Win32並行処理プログラミング入門21

 この記事は、Win32並行処理プログラミング入門20の続きです。今回は、新しい同期オブジェクトを紹介します。
 並行プログラミングでは、「他のスレッドで初期化処理が終わった」などといった情報を知りたい場合があります。その場合は、イベントを使用します。使用方法は簡単ですが、注意するべき点もありますので、サンプルとともに解説します。

/***************************************************************

//イベントを使用したいだけのサンプル

****************************************************************/
#include <iostream>
#include <string>
#include <windows.h>
#include <WinBase.h>
#include <tchar.h>
#include <process.h>
using namespace std;

//イベントハンドル
HANDLE hEvent; 

//メッセージを保持するクラス
class Message
{
private:
    string msg;
public:
    Message() : msg( "" ) {};
    void set_Message( string msg ) { this->msg = msg; };
    string get_Message() const { return this->msg; }
}msg;

//指定されたメッセージをコンソールへ出力し続ける関数
unsigned __stdcall MessageOutput( void* ) 
{
    while( - 1 ) {

        //データが初期化されるまで待つ
        DWORD result = WaitForSingleObject( hEvent, INFINITE );

        //エラーがあれば表示
        if ( result == WAIT_FAILED ) { 
            DWORD error = GetLastError();
            LPVOID title = _T( "エラー" );
            LPVOID msg;
            FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                __nullptr,
                error,
                MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), 
                reinterpret_cast< LPTSTR >( &msg ),
                0,
                __nullptr
            );
            MessageBox( __nullptr, 
                reinterpret_cast< LPCTSTR >( msg ) , 
                reinterpret_cast< LPCTSTR >( title ), 
                MB_OK | MB_ICONERROR );
            LocalFree( msg );
            return -1;
        } 
        
        //データを出力
        cout << msg.get_Message() << " ";

        //出力スピードを遅くする
        Sleep( 50 );
    }
    return 0;
}

//イベントを使用して出力処理を制御する
int _tmain( int, _TCHAR* )
{
    //CreateEventの場合
    /*hEvent = CreateEvent( 
        __nullptr, 
        TRUE, 
        FALSE,
        _T("piyo") );*/

    //CreateEventExの場合
    hEvent = CreateEventEx( 
        0, 
        _T("piyo"), 
        CREATE_EVENT_MANUAL_RESET, 
        EVENT_MODIFY_STATE | SYNCHRONIZE  );

    //スレッドを作成
    HANDLE hThread = reinterpret_cast< HANDLE >( 
        _beginthreadex (
            __nullptr,
            0U,
            MessageOutput,
            __nullptr,
            0, 
            __nullptr ) );

    //データを準備する
    msg.set_Message( "Hello,Event!" );

    //準備が終了した事を知らせる
    SetEvent( hEvent ); 
    
    //何かの処理をしている・・・
    Sleep( 1000 ); 

    //また準備する・・・
    ResetEvent( hEvent ); 
    cout << endl << endl 
        << "メッセージを変更中・・・" 
        << endl << endl;
    Sleep( 1000 );
    msg.set_Message( "ピヨ" );
    SetEvent( hEvent );

    //また何かの処理をしている・・・
    Sleep( 1000 ); 

    //出力を終える
    ResetEvent( hEvent ); 
    cout << endl << endl 
        << "ピヨはもういい。" 
        << endl << endl;

    //後片付け
    CloseHandle( hEvent );
    CloseHandle( hThread ); 

    return 0;
}

ちょっと長いですが、やっている事は非常に単純です。新しいスレッドを作成し、そのスレッドに文字列を表示させ続けているだけです。なお、文字列は共有リソースが保持しています。
 詳しい説明は次回します。続く...

テーマ : プログラミング
ジャンル : コンピュータ

実践的オブジェクト指向分析入門15

 この記事は、実践的オブジェクト指向分析入門14の続きです。前回は、分析モデルと各種技術との関係を書きました。今回は、ネットワークとオブジェクト指向分析の関係について書きます。
 ネットワークの専門家が、オブジェクト指向分析を行うに当たって注目するべき事があります。それは、既存のネットワークシステムの状態と、お客様サイドの業務体系です。既存のシステムがある場合、ネットワークが運用されている事が多々あります。新しいシステムを構築するにあたって、既存システムのネットワークシステムを知る事は非常に重要です。
 何故ならば、ネットワークのインフラ状況は企業ごとに異なるからです。特に全国に支店がある企業は、ネットワークのインフラ状態に差異があります。例えば、1部の支店だけインフラ状態が悪く、未だにISDNや1.5Mの専用回線といった低速回線を使用している場合がありえます。最悪の場合は、何の回線もない場合があります。今時そんな事はないと思うかもしれませんが、私は過去に4800bpsの回線しかないお客様に会った事があります。今も日本のどこでも光ファイバが開通していると思わない方がいいでしょう。他国に支社がある会社は、なおさら光ファイバがない可能性も視野に入れましょう。
 新しく構築するシステムにネットワーク環境が必要な場合、お客様の業務がどのように変わるか、ある程度想定しておかねばなりません。ネットワークは管理を必要とします。人員をどのように確保するのか、ネットワーク管理業務をどのように行うのかなど考えるべき事が沢山あります。現在は、クラウドも視野に入れた方がよいでしょう。そういった事を分析時に考えておかないと、システムを構築する段階になって、トラブルが発生する可能性が高くなります。
 また、初期費用とランニングコストもよく調べましょう。既存システムがある場合、ランニングコストの削減が、システム導入の決め手になるかもしれません。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

実践的オブジェクト指向分析入門14

 この記事は、実践的オブジェクト指向分析入門13の続きです。前回は、分析モデルについて書きました。今回は、分析モデルと各種技術との関係を書きます。
 オブジェクト指向分析を実施するにあたって、聞かれる事が多く誤解も多いのが、データベース・ネットワーク・システム管理・セキュリティなどの技術とオブジェクト指向分析の関係です。オブジェクト指向分析をよくしらない人は、オブジェクト指向分析=オブジェクト指向言語でのプログラミングという誤った考えを持っています。その考えは、オブジェクト指向分析と、オブジェクト指向プログラミングを同一視する謝った考えです。
 オブジェクト指向分析は、技術領域が限定されている理論ではありません。データベースもネットワークもセキュリティも・・・全てをオブジェクトとして考えます。データベースは○○、ネットワーク××、などといった限定した考えを展開しません。全てをオブジェクトして捉える方が思考がまとまり、統一感のあるよいシステムが出来上がります。
 ただし、だからと言って、技術領域の事を考えてはならないという事ではないので注意して下さい。システムを構築する上で、データベースもネットワークもセキュリティもシステム管理もテストも全てが大事です。どれか一つが欠けても良いシステムは作れません。ですから、オブジェクト指向分析は、特定の人だけがするのではなく、専門家たちが全員参加する必要があります。日本では、どの専門分野も知らない「分析屋」やコンサルタントが自称分析な行為をする光景を目にしますが、専門的な知識無くして分析は出来ません。分析とは、専門家が行うものであり、素人が出来るものではありません。分析力は背門的な知識が動力となります。続く...
 

テーマ : ソフトウェア開発
ジャンル : コンピュータ

中の人の徒然草391

こんピヨ♪今日も情熱大陸なインドリです。
ここ最近ブログを通じて、表現の自由の大切さと、モンスタークレーマー対策が如何に大事かひしひしと感じています。
ブログは自分が思う事を自由に書けます。これは一見普通の事ですが、その当たり前がない国が結構あるようです。
それに、モンスタークレーマーのいいなりになっている変な会社に遭遇した時、如何に駄目になるかが良く分かりました。
モンスタークレーマーの要望を簡単に聞き入れると、調子に乗ってクレームを続けます。
そのクレームが正しいかどうかわからないのは論外として、日本にあるお客様信仰がモンスタークレーマーを生む土壌になっているようです。
モンスタークレーマーは一部のお客様で、その人のいいなりになると、黙ってそこを利用しないお客様がそれ以上にいます。
恐らく楽をしたいのでしょうが、モンスタークレーマーのいいなりになっていると、仕事の品質は落ち荒れ果てるばかりです。
まぁ、モンスタークレーマーの言っている事を鵜呑みにする会社は、その時点で品質云々以前の問題ですが・・・
それにしても、ブログってこれほど面白いとは思いませんでした。
モンスタークレーマー対策に、コメント管理機能が完備されており、ここは非常に快適です。

話しは変わりますが、私がブログで書いた事を無断で使用しているサイトがあるらしいです。
犯人は心当たりがあると思いますので、敢えてどこかは書きません。
著作権はちゃんと守りましょう。
それにしても、変な会社ってあるものですね。
どす黒いブラック会社には沢山遭いましたが、最低限の事も守れない会社は変すぎます。
ブラック会社と変な会社(ルーズな会社?)は同じ穴の狢ですが、ちょっと違います。
勝手に倒産すると思いますが、それにしても変な事をして何の利益があるの分かりません。
一時的な利益はあるかもしれませんが、長期的に見た場合不利益になると思います。
いや、もしかしたら、そもそも短期的利益しか考えていないのかも・・・
非常識な会社が考える事はよく分かりません。
普通の人間ならば、お日様が当たる場所で暮らしたいですよね。
私は正しい事をしてお日様が当たる場所でのびのびと暮らします。
もしそれで死んだならば、それはそれで仕方がありません。
犯罪を犯すぐらいならば、犯罪に遭う方がまだましです。

テーマ : 裏事情
ジャンル :

アジャイルな会議は開発者の心

 私は常日頃、アジャイル開発におけるコミュニケーションの重要さを説いています。アジャイル開発といえば、テストファーストやペアプログラミングが有名ですが、意外とコミュニケーションの大切さが認識されていないと感じます。これを読んだ人の中には、「日本はコミュニケーション力ばかり強調するぜ」だとか「会議がやたら多いぜ」という人がいるでしょう。ですが私が言っているのは、効率的でアジャイルなコミュニケーションです。
 どういう事なのかといいますと、コミュニケーションをやたらすればいいというものではないという事です。無駄なコミュニケーションは逆に生産性を落とし、最悪の場合プロジェクトを失敗させます。無駄な会議が多いと感じている人が多いのではないでしょうか?
 大事な事は徹底的に効率化するのが開発者の精神です。コミュニケーションも例外ではありません。コミュニケーションのコストを抑え、利益を得る方法を常に模索しなくてはなりません。開発者にとって、無駄な会議は悪以外のなにものでもありません。
 会議は参加者の時間を浪費します。ですから、コストに見合うかどうか、あらかじめ内容を吟味しなくてはなりません。つまり、会議の目的を明確にし、会議が始まったら目的に沿って、効率よく進めなくてはなりません。
 これを実現するには、様々な事を決定しなくてはなりません。発言者のルール、質問者のルール、書記のルール、役割の決定・・・など様々な事が考えられます。これは、プロジェクトが始まる前に決めておいた方がよいでしょう。そして、開発作業が進むにつれて露呈する、既存の会議の無駄な部分に対して柔軟に対処しましょう。
 この手の事を年配の人に言うと、人間味がないだとか、人間構築が出来ないなどとよく言われます。しかし、私は会議でその様な事をする必要はないと思います。そもそも、人間的な関係構築は会議でするべき事ではありません。会議でしてしまうと、公私混同していしまいます。
 公私混同は、プロジェクトを円滑に進める上で障害となります。好き嫌いは誰でもありますが、それを仕事に持ち込んではなりません。たとえ嫌いな人がいても、その人がプロジェクトに貢献するのであれば、その人の意見に耳を傾けねばなりません。もちろん、無理難題を言って場を荒らす人に対しては当てはまりません。
会議を混乱させる人はたまに見かけますが、そういう人はプロジェクトを進める上で必要なプロフェッショナルではありません。上司が適切な対応を採るべきだと言えます。最悪の場合、プロジェクトメンバーから外れてもらうしかありません。開発作業は共同作業なのです。
 しかしだからと言って、少数意見を言っている真面目な人を排除してはなりません。日本ではよくある光景ですが、上司にゴマをするYesマンしかいないと、プロジェクトは確実に失敗します。日本ではなぜか、みんな一緒に同じ意見を言わなくては場を乱すと言われますが、それでは会議の意味がありません。ルールを守って、建設的な意見を述べる場でなくてはなりません。
 私が言っている事は、国会中継を見れば分かると思います。人の話しは聞かない、やじを飛ばす、揚げ足取りに終始する、対案を述べない、官僚が書いた台本を読むだけ・・・などといった悪い例の宝庫です。あれを見ると、質が悪い会議が如何に生産性を下げるか、その意味がよくわかって頂けるかと思います。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

Win32並行処理プログラミング入門20

 この記事は、Win32並行処理プログラミング入門19の続きです。今回は、合成による並行アルゴリズムを紹介します。
 以前述べたように、継承はあまり良い方法ではなく、合成の方が良いと言えます。また、直列的な考えではなく、並行的な考え方が必要です。合成と並行的な考えを示すサンプルを掲載します。

#include <iostream>
#include <vector>
#include <windows.h>
#include <tchar.h>
#include <process.h>
using namespace std;

//インスタンスのポインタとパラメータを保持するクラス
class InstanceAndParameter
{
private:
    void* ins;
    void* param;
public:
    InstanceAndParameter( void* ins, void* param ) 
        : ins( ins ), param( param ){}
    void* getInstance() const { return ins; } 
    void* getParameter() const { return param; }
};

//並行処理を意識していないクラス
class Foo
{
private:
    long number;
public:
    Foo() : number(0) {}
    long getNumber() const { return number; }
    void setNumber( long value ) { this->number = value; }
    virtual void AddFunc( int count ) 
    {
        for ( int i = 0; i < count; i++ ) {
            ++number;
        }
    }
};

//並行処理を意識したクラス
const int threadCount = 64; //作成するスレッドの数
class ConcurrentFoo
{
private:
    //フィールド
    long number;

    //スレッドから呼び出すメソッド
    static unsigned __stdcall Add( void* pvParam ) 
    {
        //パラメータのチェック
        _ASSERTE( FALSE == IsBadReadPtr( 
                pvParam, sizeof( InstanceAndParameter ) ) 
            && "スレッドに渡されたパラメータが無効です" ); 

        //インスタンスとパラメータを取り出してメソッドを実行
        InstanceAndParameter* ip = 
            reinterpret_cast< InstanceAndParameter* >( pvParam );
        Foo* obj = reinterpret_cast< Foo* >( ip->getInstance() );
        int count = PtrToInt( reinterpret_cast< INT_PTR >( 
            ip->getParameter() ) );
        obj->AddFunc( count );
        return 0;
    }
public:
    ConcurrentFoo() : number( 0 ) { }
    ~ConcurrentFoo() { }
    long getNumber() const { return this->number; } 
    
    //並行処理用メソッド
    //※countはスレッドごとの値
    DWORD ConcurrentAdd( const int count )
    {
        //スレッド数の判定
        if ( threadCount > MAXIMUM_WAIT_OBJECTS ) {
            cout << "【エラー】" << endl;
            cout << "指定するスレッド数が多すぎます。" << endl;
            cout << "指定するスレッド数は" 
                << MAXIMUM_WAIT_OBJECTS 
                << "以下にして下さい。" << endl;
            return -1;
        }

        //スレッドを実行する
        HANDLE hThreads[ threadCount ];
        Foo* objs = new Foo[ threadCount ];
        InstanceAndParameter** params = 
            new InstanceAndParameter*[ threadCount ];
        for ( int i = 0; i < threadCount; i++ )
        {
            //スレッドのパラメータを用意する
            params[i] = new InstanceAndParameter ( 
                reinterpret_cast< void * >( &objs[ i ] ), 
                reinterpret_cast< void * >( ( INT_PTR ) count ) );

            //スレッド作成後直ぐに実行
            hThreads[ i ] = reinterpret_cast< HANDLE >( 
                _beginthreadex ( 
                    __nullptr,
                    0U,
                    ConcurrentFoo::Add,
                    reinterpret_cast< void * >( params[ i ] ),
                    0, 
                    __nullptr ) );
        }

        //タイムアウト時間をミリ単位で指定して待機
        //※指定した時間は正確ではありません
        DWORD result = WaitForMultipleObjects( 
            threadCount, hThreads, TRUE, 2000 );

        //合計値を算出
        this->number = 0;
        for ( int i = 0; i < threadCount; i++ )
            this->number += objs[ i ].getNumber();

        //後片付け
        for ( int i = 0; i < threadCount; i++ ) {
            CloseHandle( hThreads[ i ] );
            delete[] params[ i ];
        }
        delete[] objs;
        delete[] params;

        //結果を返す
        return result;
    }
};

int _tmain( int, _TCHAR* )
{
    //並行的にカウント処理を行う
    const int count = 100000;
    ConcurrentFoo obj;
    DWORD result = obj.ConcurrentAdd( count );

    //WaitForSingleObject関数が終了した原因を表示
    cout << "【スレッドの状態を表示します】" << endl;
    unsigned int max = ( WAIT_OBJECT_0 + threadCount - 1 );
    if ( result == WAIT_FAILED ) { 
        //エラーを表示する
        LPVOID title = _T( "エラー" );
        LPVOID msg;
        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
                FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
            __nullptr,
            GetLastError(),
            MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // 既定の言語
            reinterpret_cast< LPTSTR >( &msg ),
            0,
            __nullptr
        );
        MessageBox( __nullptr, 
            reinterpret_cast< LPCTSTR >( msg ) , 
            reinterpret_cast< LPCTSTR >( title ), 
            MB_OK | MB_ICONERROR );
        LocalFree( msg );
        return -1;
    } 
    if ( result == WAIT_TIMEOUT ) {
        cout << "タイムアウトしてしまいました。" << endl;
    } else if ( ( result >= WAIT_OBJECT_0 ) & ( result < max ) ) {
        cout << "全スレッドの処理が終わりました。" << endl;
    } 
    cout << endl;

    //グローバル変数の合計値を表示
    long correctValue = threadCount * count;
    long number = obj.getNumber();
    cout << "【グローバル変数の値を表示します】" << endl;
    cout << "予想値:" << correctValue << endl;  
    cout << "実際の値:" << number << endl;
    cout << "不足値:" << ( correctValue - number ) << endl;
    cout << endl;
    return 0;
}

このサンプルは、合成をあまり表現できておらず、スレッド数の決定部分がないので不完全です。しかし、不完全ながら並行アルゴリズムの考え方を示しています。
 前回までのサンプルは、ConcurrentFooをFooの子クラスにして、複数のスレッドで共有していました。しかし、一つのインスタンスだけしか作らないのは、従来の直列的な考え方です。並行アルゴリズムは、積極的にインスタンスを作って、ロックや排他制御を極力しません。ロックや排他制御をやたらと使用しないのがポイントです。
 スレッド数を決定する作業を今回紹介しませんが、これで並行アルゴリズムの片鱗が見えたと思います。じゃあ、クリティカルセクションは要らないのかというと、そうではありません。今回は偶然必要ではありませんでしたが、極力狭くしたクリティカルリージョンに対して使用します。自分で並行アルゴリズムを実装する際には、アトミックな命令とクリティカルセクションは必須アイテムです。
 必須アイテムを極力使用しないのが並行プログラミングの心です。

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター