東京総合車両センターと房総半島に行ってきた

昨日昼頃にトシ様から東京に行くことになったけど一緒に行かない?と誘われたから、朝から東京へ出発。
8時過ぎに品川で合流して、まずは東京総合車両センター夏休みフェアへ。
トシ様は9時開始と思ってたようだが、実際は10時開始。ただ、毎度のごとくフライング開始で30分早く入場。
ちなみに、入場列と廃車部品販売で別々に並んでいたんだけど、廃車部品販売のほうが倍位列が長かった…
入って速攻で、くじ見つけたから「1等(Nゲージレール付きのセット)当たったらどうするよw」とか言いながら引いてみたら、4等だったから、201系の方向幕キーチェーンもらった。後でもう一回引いたら、4等だったから、今度は前面種別表示機のキーホルダーを獲得。
その後115系試乗会乗ったりして10時過ぎに撤収。
品川から横須賀、総武快速線で稲毛へ移動し、113系回送を撮影。
内房線で木更津へ移動し、久留里線に乗って久留里で撮影。1時間待機してまた木更津へ。
千葉行きの113系を撮った後乗車し、蘇我駅で下車して、外房線を待つも、やってきたのはさっきまで乗ってた113系だった。このとき、Twitterに「さよなら113系」の表示を投稿しようとしたけど、上手く行かないように見えて3回くらい投稿しちまった…
外房線誉田駅駅で特急退避中に撮影。209系に乗って蘇我から京葉線で東京に戻って夕飯食った後、新幹線ホームで解散。
帰って速攻風呂に入って、帰宅報告した後写真の回収と動画の変換とアップロード。途中操作ミスってデータ軽く消去したが、無事にアップ。
URLは http://mattyan.net/photo.php?d=1314370800
トシ様、お疲れ様でした。

クラスのメンバ関数をマルチスレッドで動かすためのメモ書き

クラスのメンバ関数をSDLのSDL_CreateThread関数で扱うためのメモ書き。ちょっと流用すれば他のライブラリでも使えるかも?
staticメンバ渡せば一発なんだろうけど。派生することを考えるとなんか色々面倒くさそうなんで、普通のメンバ関数を呼び出すようにした。

基底クラスの用意

マルチスレッドで動かすクラスの基底クラスでは、至るところで派生クラスの型がわからないと使えないので、テンプレートクラスで作成。


template <typename T> class Thread{
		private:
			struct ThreadParameter{
				T    *instance;
				void *parameter;
			};
			SDL_Thread *thread;
			/**
			 * スレッド関数呼び出し
			 * @param[in] param スレッド情報
			 * @return function()の戻り値
			 */
			static int callThread(void *param){
				ThreadParameter *tp = pointer_cast<ThreadParameter *>(param);
				return pointer_cast<T *>(tp->instance)->function(tp->parameter);
			}
		public:
			/**
			 * スレッド実行関数
			 * @param[in] param 引数
			 * @return 不明
			 */
			virtual int function(void *param) = 0;
			/**
			 * スレッド実行関数
			 * @param[in] p     派生クラスのポインタ
			 * @param[in] param スレッドに渡す引数
			 */
			void run(T *p,void *param){
				ThreadParameter tp = {p,param};
				this->thread = SDL_CreateThread(&Thread<T>::callThread,&tp);
			}
	};

1.privateにSDL_CreateThreadから呼んでもらうメンバ関数をstaticで宣言。その関数への引数として、派生クラスのポインタとスレッドへの引数をまとめた構造体を渡す。
2.callThread関数では、渡されたポインタから派生クラスのインスタンスのポインタを取り出して、マルチスレッドで実行したいメンバ関数を呼び出す。
派生クラス


class Add:public Thread<Add>{
	public:
		virtual int function(void *p);
};
int Add::function(void *p){
	FILE *file = fopen(pointer_cast<char *>(p),"w");
	fprintf(file,"start = %d\n",SDL_GetTicks());
	for(int i=0;i<2000;i++){
		fprintf(file,"i = %d\n",i);
	}
	fprintf(file,"end = %d\n",SDL_GetTicks());
	fclose(file);
	return 0;
}

マルチスレッドで使用する関数をオーバーライドするだけ。
これが呼び出されると、プログラムが起動してからのミリ秒を記録したあと、2000回ほどループして、終了時間を記録してスレッド終了する仕組み。
実行結果は

スレッドID 開始時刻 終了時刻
1 515 536
2 515 536

だから、マルチスレッドで動いてる。はず…
ちなみにpointer_castはこんな関数


/**
 * ポインターキャスト
 * @param[in] p キャストするポインター
 * @return キャスト結果
 */
template <typename T> inline T pointer_cast(void *p){return reinterpret_cast<T>(p);}