1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++とPthreadでJavaライクなスレッドライブラリを作る~その1 - Threadクラス

Last updated at Posted at 2017-12-24

ここでは,C++でRead/Write Lockデザインパターンを実装すべく,Javaのスレッドライブラリ風なAPIを作っていく.Threadクラスを継承して使う設計にする.

まず,pthread_createの定義は

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
         void *(*start_routine)(void *), void *arg);

であり,第3引数にvoidを引数で受取,voidを返す関数ポインタを指定する必要がある.そして,第4引数は
第3引数の関数へ与える引数のためのvoidポインタを指定することになっている.
今回,Javaのスレッドライブラリのように,new Thread().start()でThreadを継承するクラスのrunを実行する.
ところが,この第3引数に与える関数ポインタは,スタティックじゃなければいけないので,そのままrunをわたす訳にはいかない.そこで,Threadにstaticなwrapメソッドを用意し,これ経由でインスタンスメソッドであるrunを実行するようにした.

Thread.hpp
class Thread {
private:
    pthread_t thread;   // pthreadのための構造体
    void *args;         // runの引数のためのポインタ

protected:
    static int tcount;

public:
    Thread(){tcount++; /*printf("thread\n");*/}
    virtual ~Thread() {}
    virtual void* run(void *arg) = 0;

    static void* wrap(void *arg) {
        Thread* pt = (Thread*)arg;  // 第4引数で自分自身(this)が渡されるので,キャストしてrunを実行
        return pt->run(pt->args);
    }
    void start(void *arg) {
        this->args = arg;
        if (pthread_create(&this->thread, NULL, wrap, this)) {  // スレッドの生成. 第4引数にthisを指定
            printf("thread create error\n");
            abort();
        }
    }

    void wait() {
        if (pthread_join(this->thread, NULL)) {
            printf("join error");
            abort();
        }
    }

続いて,Threadを継承するReadThread.これは単に,スレッドIDとともに1秒ごとに"work by Thread ..."と表示するだけ.
なお,スレッドIDとして利用しているtcountはクラス変数であるため,どこかで実体を定義する必要がある.

rw.hpp
#include "Thread.hpp"

class ReadThread : public Thread {
private:
    int id;

public:

    ReadThread();
    ~ReadThread();
    void* run(void *arg);
};
ReadWrite.cpp
ReadThread::ReadThread() {
	this->id = tcount;
}

ReadThread::~ReadThread() {    
}
void* ReadThread::run(void* arg) {
    printf("run Thread %d\n", this->id);
	for (int i = 0; i < 5; ++i) {
		printf("work by Thread %d\n", this->id);
		sleep(1);
	}
    return NULL;
}

次は,これを利用するmain.cpp

main.cpp
int main(void) {
    ReadThread rt1, rt2;

	rt1.start(NULL);
	usleep(500000);
	rt2.start(NULL);

	rt1.wait();
	rt2.wait();

    printf("end of mein thread\n");

    return 0;
}

実行結果

> ./main
run Thread 1
work by Thread 1
run Thread 2
work by Thread 2
work by Thread 1
work by Thread 2
work by Thread 1
work by Thread 2
work by Thread 1
work by Thread 2
work by Thread 1
work by Thread 2
end of mein thread

個々のスレッドか交互ログが出力されていることわかる.

全部のソースコードはこちら

次回に続く

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?