C++: boost: boost::thread を C++ の class で使う

pthread と Windows Thread は元々使っていたんだけれど、boost::thread が C++0x での Thread 実装の殆どそのままらしいから、使ってみることに。
っていうか、こういうライブラリ使わないと、Linux と Windows で動かすときに不便だしねー

ってかね、サンプルの殆どが class を使ってないんだよね。
その場合、pthread とか使っていれば直ぐに分かるから、まあいいんだけれど、class を使った場合のが苦労した。
最初、static なメソッドしかスレッドで実行できないと思っていたんだけれど、実はそうじゃないっぽい。

とりあえず、コンパイル通って実行してるやつを元に、簡略化して抜き出し。
簡略化の後コンパイル通してないから、若干タイプミスあるかも。

#include 

#include 

class MyThread
{
 public:
  MyThread();
  ~MyThread();

  void Create();
  void Release();

  void TerminateThread();

 private:
  bool terminate_;

  std::tr1::shared_ptr thread_;

void Run();
};

MyThread::MyThread()
{
  this->terminate_ = false;
}

MyThread::~MyThread()
{
  this->Release();
}

void MyThread::Create()
{
  this->thread_ = std::tr1::shared_ptr(new boost::thread(boost::bind(&MyThread::Run, this)));
}

void MyThread::Release()
{
  if (this->thread_.get() && this->thread_->joinable()) {
    this->terminate_ = true;
    this->thread_->join();
  }
}

void MyThread::TerminateThread()
{
  this->terminate_ = true;
}

void MyThread::Run()
{
  while(!this->terminate_) {
    this->thread_->sleep(boost::get_system_time() + boost::posix_time::milliseconds(2000));
  }
}

int main()
{
  MyThread thread1;
  MyThread thread2;
  MyThread thread3;

  thread1.Create();
  thread2.Create();
  thread3.Create();

  thread1.Release();
  thread2.Release();
  thread3.Release();

  return 0;
}

boost::thread を new する時に、 boost::bind を使って、を複数の引数を持たせられるようにしてある。
boostのライブラリって、本当にシンタックスシュガーを目指している感じがするなぁ・・・

この手のライブラリは便利なんだけれど、名前空間のおかげでコードが長くなるねー
まあ、自分は using は使わない方針なので、仕方がないのだけれどw

C++: Google C++ Style Guide

Google C++ Style Guide
Google C++スタイルガイド 日本語訳

全てがそのまま、自分の組み方にいい訳じゃないけれど、
組み方の参考にはなる。

最近の流行、というか、2年くらい前から自分のTABじゃなくてスペースを使っている。
Eclipse環境の時だけ、JavaはTABだけれどね。
Pythonの影響だね。
PythonとかC/C++のソースコードを組む時に、
Pythonのコーディング規約を結構参考にしていたからねー。

他にも、多重継承は基本的に禁止だけれど、
インターフェースクラスだけは、有益と判断されれば多重継承を用いても良い。
など、Javaの人たちの考えを参考にしているところもある。

Operatorの多重定義の禁止は結構大胆。

正直な話、MAYA C++ APIとかを触っていると、classのoperatorの多重定義は使いやすい。
でも、あれはMAYAっていう3D分野に限られているから、余り混乱しなくていいんじゃないかな~って思ったりもする。
という訳で、どっちかに統一されていればいいんだけれど、数学的な部分以外を扱う時には、
余り上書きは良くないかもね。

まあ、Javaが長かったから、classでoperatorを使うのは、build-inライブラリのもの意外は抵抗があるね。

namespaceは自分も同じ考えで、usingは絶対使わない。
名前空間が分けわからなくなるんだよね・・・。
STLを使う時でも、自分は
std::cout << std::endl;
と、名前空間から書くほう。
理由は、どのcoutを参照しているか明確にしたいだけ。
後でソースコードを見た時に、STLとかboostくらいなら別に分かるからいいんだけれど、
それ以外のライブラリの時、どのライブラリを参照しているのか明確にしておきたいんだよね。
書くのが面倒という人もいるだろうけれど、自分はそこは面倒でも割り切って書くほう。

後は、定数の命名規則もなかなか好み。
MAYA::kWorld
という感じで、MAYA APIを使った時から、prefixにkを使っていると、非常に分かりやすい。
マクロ名と定数名って今までごっちゃになっていたから、これからはそこを分けるために、kを使うね。

後面白いのが、変数名と変数スコープ。
classのメンバ変数はprivateのみ。っていうのは、凄い割り切っている。
自分もJavaが長かったから、Java Beanっていう考え方で、
基本的にデータ構造として扱う時はprivateにset、get関数付けていたけれど、
それ以外のclassではたまに、publicな関数があったりはした。
そこを、private限定って割り切ってる辺りが凄い。
こういう徹底をしないと、globalスコープにどんどん変数を露出させていく人がいるから、
コーディング規約でそれを出来なくしてしまうのは、正解だと思う。

基本的に、設計がおかしい。まあ、簡単に言えば汚いソースコードは、
コーディング規約がきちんとまとまっていなかったり、
デザインパターンなどの技法を使っていなかったりする場合が多い。

Javaで一緒にプログラムを組んでいた人が、
こういう場合はこのデザインパターンを使う。とかある程度決まっていて、
そういう中でプログラムを組んでいけば、Javaプログラマーの間では、
ソースコードが読みやすくなる。
と言っていた。

まあ、その人とプログラムを組んでいて困ったことはないし、
次に自分が設計をした時も、他の人が結構触れていたしね。

ま、設計を覚えるのは大変だけれど、
こういうきちんと理由付けがあるコーディング規約を見るのは、
どうしてそうなってるんだろう?と、考えるために知識を仕入れたりもするので、
なかなかいい勉強材料じゃないかな。

しかし、C++0xも触ってみないとなぁ・・・
Threadが標準がされるって素晴らしい!!
Googleが触れてるね。
Programming Languages C++ Threads

余談だが・・・Guideの部分が何度もGuildになったのはおかしい。
手がいけないんだ!!

GNU make: -j オプション

職場でコンパイル時間の遅いプロジェクトの、コンパイル時間の最適化を行っているんだけれど
その中で見つけたのが、make -j オプション。知らなかった・・・

make -j2
make -j4

などで、コンパイル時に同時に走るJob数を選択できる。
物理的なコアの数分指定するのが妥当かな。ということで
Core2Duo だから -j2 で1.8倍くらいは早くなった。
Core2Quad で、 -j4 だと、 3.4倍くらいは早くなるんじゃないだろうか?

という事で、Core2Quad じゃないけれど、Xeonで試してみました。

早かった!!

20分コンパイルにかかっていたのを、こっちの作業で10分以内まで短縮していて
Core2Duoで-j2 で5分だったのが、Xeon で -j4 は3分以内だった!!

すばらしい!!

っていうか、20分もかかっていたのはソースコードとかクラス設計がおかしかったせいなので
直すのしんどいです・・・
新卒に設計を任せちゃダメって事ですね。

コンパイラの最適化オプション

gcc だと、-O0 -O1 -O2 -O3 とあるけれど
Visual C++ だと
/Os サイズ優先
/Ot 実行速度優先
となるらしい。

VC++: ミリ秒取得

Java でいう、System.currentTimeMillis() みたいなのがないかな。と探したらあった。

#include <mmsystem.h>

timeBeginPeriod(1);
DWORD currentTime = timeGetTime();
timeEndPeriod(1);

この時 winmm.lib にリンクを張る必要性がある。

UNIX系なら

#include <sys/time.h>

gettimeofday()

で取れるらしい。
こっちはまだ試してない。

依存の強弱

ゲームエンジンを組んでいて、デバイスへの依存度が高いと、キャストや抽象化の数が減るから
パフォーマンスは上がるかもしれないけれど、後で違うデバイスへ同じロジックで乗せ替えをしたい時に難しくなる。

デバイスではなくて、ドライバ(API) だけれど、DirectX と openGL のそれぞれに依存している部分を
どの程度依存を強くするか。というのが、両方に対応させるポイントかなと。

たとえば、C++ で InterfaceClass を定義して、それを継承したクラスが
DirectX用の Vector, openGL用の Vector クラスを内包していて
Interfaceは統一されている状態であっても、そのポインタを更に DirectX 用の API に渡すには更にキャストが必要。
しかも、そこに必ず DirectX 用の Vector オブジェクトがこないといけない。
ポインタとしては、抽象クラスに一度キャストされているし、受け口もそうすれば受け取れるけれど
中身が違ったら結局実行時エラーが出る。
それじゃ、抽象化に成功しているとはいえない。
組む時の苦労は何も減らない。むしろ、キャストしてただ単にパフォーマンスが落ちるだけじゃないのか?

どんなに Vector や Matrix, Light を抽象化しようが、最終的にはそれぞれの API が指定しているオブジェクトを渡さないといけないんだもん。

って言うことで、余り依存関係を弱くしても、それがシステム的にいい設計とは限らないと思うわけです。
じゃあ、どこまでを依存にして、どこからを非依存にすれば
ゲームエンジンとして、性能がいいのだろうか?

おそらく、デバイス依存する部分はがっつり依存する。つまり描画周り。
そこを、きちんと切り出しておいて、DIコンテナみたいに、動的に入れ替えが出来れば問題がないはず。
アスペクト指向ってやつかな。

で、ゲーム側ロジック側では抽象クラスとしてしか扱わない。
つまり、InterfaceClass のポインタを受け取って、その関数を扱うけれど、オブジェクトには直にアクセスしない。
描画部分だけは、InterfaceClassのポインタではなく、完全にデバイス依存のオブジェクトポインタを受け取る。
これで、ある程度は分離できるはず。

Javaのフレームワークで、散々アスペクト指向というものに触れてきたけれど
それが役に立っている感じ?

まあ、オブジェクト指向、アスペクト指向、エージェント指向って色々あるけれど
プログラムを本格的に組んでいると必ずぶち当たる壁に対する、解決手段思想だよね。

たまに、そういう思想を一切勉強しないでプログラムを組んでいる人を見かけるけれど
そういう人って、性格にもよるけれど、ちょっと困る場合が多い。

大抵の場合そういう人のプログラムは読めないし、後から変更が出来ない、どこかをいじると次々と動かなくなる。
という場合が多いからだ。

個人差はあるけれど、自分が見かけた人たちは、得てして頑固な性格をしていて
根拠がない理由で頑固なんだよね。

これはどうしてこういう方法を使っているの?
このカラムは何でこのテーブルにあるの?
って聞いても、なんとなく。って答えるんだよね。

まあ、話はそれたけれど、その思想への好き嫌いはそれぞれあるだろうし
勉強しなくても、別にいいんだけれど

他人が読めるプログラムを組んで欲しい。
それに付きます。
動けばいい。っていうプログラムの組み方する人のプログラムはもう二度と見たくないなぁ・・・

Google Performance Tools を使ってみる

Google Performance Toolsっていうのが結構前からあって、ずっとバージョンアップを重ねていたりします。
http://code.google.com/p/google-perftools/
どんなものかというと、マルチスレッドでのメモリ確保や、CPUプロファイル、Heepプロファイルなど、パフォーマンスを上げるためのプロファイルに必要な情報を引き出すためのツールだったりします。
とりあえず、rpm版が使い易いので、rpmをダウンロードしてインストール。バージョンは安定してるやつの最新バージョンを取得。
### 追記 ###
openSUSE 11.0 だと、google-perftools google-perftools-devel というパッケージがあったので以下のコマンドでインストールできる。
yast -i google-perftools google-perftools-devel
######
wget http://google-perftools.googlecode.com/files/google-perftools-0.99.1-1.i386.rpm
wget http://google-perftools.googlecode.com/files/google-perftools-devel-0.99.1-1.i386.rpm
rpm -ivh ./google-perftools-0.99.1-1.i386.rpm
rpm -ivh ./google-perftools-devel-0.99.1-1.i386.rpm
それで、どんなもんかと試してみたいので、プログラムを準備。
今回は、CPU Profiler を試してみます。
CPU全体のProfileを取る時はこんな感じ。
-lprofilerをコンパイル時にリンクします。

env CPUPROFILE=/tmp/prof.prof ./prof.elf

場所を区切って取りたいときは
#include
ProfilerStart(“prof_file_name”);
// ここに処理
ProfilerStop();
といった感じになる。
で、ログを取ったら、それを元に分かり易く画像ファイルなぞを作成。
perl5と、gvとdotが必要。なかったらインストールを。
pprof –dot ./prof.elf /tmp/prof.prof > prof.dot
dot -T png prof.dot > prof.png
で、これがサンプル。実行したプログラムはこんな感じ。
prof
最初sleepでやったんだけれど、そりゃ、CPU負荷ないから出ないわw
って事で、ださいけれど、forでぐるんぐるん回してます。
内部処理を一つの関数に統一してしまうと、その関数の数字しかでなくなっちゃうから、わざとコピペで二つの関数に同じ実装しています。

ポインタと配列の違い + 参照もちろっと

前に書いた「C言語のポインタとか難しく考えすぎじゃね?」という記事で、ポインタと配列が同じ様に扱える部分だけを書いていたので、今回は二つの違いについて。
トラックバックを見たら、違うよ?と言われていたので、トラックバック先の記事と自分が書いたやつを見たら
ポインタ、配列の違い書いていないのと、自分が勘違いしていた部分があるみたいなので、復習も兼ねて・・・
とりあえず、一番違うところは、配列の持っているアドレス値は定数なので変更できない。ってところ。
大体、そこを解かってるの?って指摘されているね・・・
正直、配列変数にアドレス値を代入しようとしたことが無かったので、思いっきり失念していました。
なので、前の記事を書いたときは、その部分を意識していなかったですね。
こんがらがるかもしれないけれど、前に自分が書いたのは、どちらもアドレス値を持っている変数だから、同じ様な操作が出来る。って事。
それを、ポインタと配列が同じ。って書いたから、同じじゃないよ!!って言われてるんだよね。
> char szMsg1[];
> char *szMsg2;
>
> という宣言があったら、
> C言語のポインタを理解している人に取ってはszMsg1 とszMsg2 は同じ物じゃないだろうか?
ここね。
同じ様にメモリ演算してくれる物。って意味に、訂正で・・・
お二方共に、指摘してくれてどうもありがとうございました(。。
気になったのが、配列は関数に渡す事が出来ない。ってのも、失念していたかも。
値渡しが出来ない。って意味なんだろうけれど、これも、配列を値渡ししようと思ったことがないので、気にしたことがなかった・・・
配列を何かしたいときは、disp_pointerな感じになるかな。こういう使い方自体が間違ってる?
どちらの関数も参照渡しかな。
dip_arrayは、nt items[] で受け取れるのかな?ってやってみたら、受け取れたので書いてみた。
配列の中身を変更させようとしたら、変更できたので通常の参照渡しになっているみたい。
これは今までやったことがないから、どういう風になっているのか調べてみないとだなぁ
arraypointer.c
更に、C++の参照とCの const についても指摘されているし。
という事で、こっちも確認しておこう・・・自分、勘違いしまくりだなぁ
動かしてみたら、参照って、別名でしかないから、値の変更できるんだ・・・
普通に、Cでいう const int * とかの代わりだと思っていた。
const.c
これはコンパイルエラーになってくれる。
reference.cpp
こっちは、参照は変数名の別名+アドレス値が変更できない。っていうだけだから、コンパイルが通るし、値も書き換えられる。
っていうことで、C++でも、関数の中で値を変更されたくない時は、きちんと const を付けて引数指定しなさい。って事かな。

Doxygen

前に知り合いに教えてもらった、C/C++用のドキュメントトール。
C++だと class の階層構造が凄いからねー って事で、さっそく使ってみた。
公式はこちら。
http://www.stack.nl/~dimitri/doxygen/
JavaDocスタイルにも対応しているので、Javaをやっていた人にも使い易くていいかも?
ソースファイルから、勝手に色々とパースしてくれて、LaTexとHTMLで出力してくれます。
コメントさえきちんと書いておけば、プログラマー同士でのやり取りにはこれで十分じゃないかな?
まあ、他人のソースコードを理解するのが大変だっていう事実は変わらないだろうけれどねw
しかしなんだ、最近Tracを全然使っていないな。あれって大体にして、Python + Djangoのアプリ用に置いてあるんだけれど
面倒な仕様にしすぎて、途中で放置状態w まあ、そのうち簡単なHTMLだけの構造にして組みなおすけれどさー
で、今回新しく組んでいるアプリは何で管理しようかなぁ~ と悩み中。
Redmineっていう、Ruby on Railsのツールが最近噂に聞くけれど、見てみたら、Tracと余り変わらない?
まあ、Pythonはメンテできても、Rubyはメンテできないので、Tracになるのかなぁ~
色々なツール使いすぎるといいことないし、Tracでいきますか~

C言語のポインタとか難しく考えすぎじゃね?

Javaの配列を扱おうとすると、毎回度忘れしてしまっているので、使う度にぐぐっているんだけれど(ぉぃ
何故か・・・HatenaDiaryにあるC/C++の配列とポインタの解決をしているエントリーに行き当たった・・・そこからしてかなり謎w
相当、有名な人の日記なのかね?それか、HatenaDiary自体のSEOが高いとか?
ま、その記事を読んでみたんだけれど・・・
配列とポインタの違いを解説するのに、アセンブリを持ち出していたよ!!
ええええ!!まぢですか!?って、ちょっと思ってしまった・・・
そんな解説の仕方をしていたら、アセンブリ解かる人しか、ポインタ理解できないじゃん。
しかも、内容間違っていたし。
昔、自分がC/C++を始めた時は、まだJavaは全然流行ってなくて、JavaAppletでChatとして使われていたくらいだったかなぁ
そんな時代は、「C言語のポインタを理解できる」と銘打った本が世の中に沢山あった。
自分は一度もそういう本を読んだことがない。
だから、C言語の入門書で解説している概念だけで、ポインタは理解できたし、ポインタを説明するのにも、C言語の概念だけでいいと思う。
それ以上の知識は蛇足だと思う。
もっと、深く知りたい時には必要な知識だとは思うけれど、C言語のポインタを理解するのにアセンブリはいつ必要なんだ?ずっと知らなくても別に理解できるだろ?って思う。
さて、C言語のポインタって、ぶっちゃけただのアドレス値じゃない?
それ以上に何かあるとしたら、ポインタと配列は同じ様に扱う事が出来る。という事だろう。
前に、同じ年の人が一時的に今の職場に来て、C言語できる。というから、ポインタと配列の違いが解かります?って聞いたら
「え?ポインタも配列も同じじゃないっすか。」
と言われた。
そうだよね。理解してる人に取っては、特に何でもないものなんだと思う。
char szMsg1[];
char *szMsg2;
という宣言があったら、
C言語のポインタを理解している人に取ってはszMsg1 とszMsg2 は同じ物じゃないだろうか?
=== 追記 ===
勘違いしてるやつが書いた、勘違いを促す文章だったので
同じ様にメモリ演算してくれる物。って意味に、訂正で・・・
トラックバックで指摘されているので、そちらなどを参考にどうぞ。
===
C言語で構造体を扱うと一発で解かると思う。
C言語使いの人達は当たり前にこういう使い方をするからねぇ・・・
なんだろう。動的に、プログラマーがメモリを確保する言語だから、そういう概念があるんだよね。
だから、他の言語をやってる人からは余り理解できない部分かもしれない。
DirectXで、WindowsApplicationを創っていたはずなんだけれど・・・何故か、Linux上でC言語のサンプルコード書いてしまった!!w
昔に書いた、構造体の穴と言われる、alignmentに関しても一緒に見ておくといいかも。
自分で、メモリを16進数で計算しようとしても、処理系によってはこうやって、アクセスを早くしようとalignmentを揃える時があるというのを覚えておくべきだね。
C言語の場合、きちんとコンパイラが[]演算子でサイズを計算して、ポインタ値をずらしてくれているから、構造体の穴にはまることはないかな。アセンブリ書く人は、気をつけないといけないかも(・・?
ちなみに、PS3のCellのサブチップなんかは、Alignmentを揃えない変数は使うことすら難しいです。ってか、SIMDにかけられないから、使えないです。
structure.c
alignment.c
ちなみに、自分がみた記事だと、どうにも、ポインタへの const と勘違いしていたようだ。
C言語では、const に関しても色々なテクニックがあるっていうか、常識なんだけれど
ポインタ値に対しての const なのか、ポインタ値が指している先の値に対しての const なのかによってかなり違う。
C++の参照なんかは、前者だね。一度設定した、ポインタ変数のアドレス値は変えられません。
他にも、標準関数なんかで自分は最初に見たけれど、引数指定がに const char * になってるやつなんかは頭良いよね。
こいつを受け取っても、値を変化させたりして返しませんよ。という意志表示なんだよね。
あー ついでに、const の話をしちゃったから、const の例も書いてみた。
const.c
gccだとちゃんとチェックしてくれるからいいけれど、コンパイラによってはチェックしないのもあるかも?
自分は、gccでコンパイル通すためにコメントアウトしたけれど、コメント外して make 実行すると、コンパイル通らないのが解かります。
const.c:15: error: assignment of read-only variable str2
と出るはず。
これは、str1が、文字列に対しての const なのに対して(最近のC言語の解釈では、”"で挟まれる文字列リテラルは元々constだった気がする)
str2は、文字列を指すポインタ値がconstなのですよ。なので、ポインタ値の変更は許されません。
ま、C言語使っている人にとってはこの辺りは当たり前だよねぇ
これを理解していないと、プログラムなんて全然組めない気がする。
最後になったけれど、自分がJavaの配列で調べたかったのは・・・
public String[] names;
という書き方できるよね?
っていう事でした。
Javaの配列はちょっとおかしくて
public String names[];
というC言語スタイルの書き方も出来るんだよね~
でも、職場のJava使い曰く、前者を書く人はJavaの配列を理解している!!って言っていた。
確かに、自分もそう思う。
だって、Javaの場合
「String型の配列のインスタンス」
と考えた場合、前者の方がすっきりこない?変数型の部分だけに意味を持たせているよね。
C言語と違ってポインタがないから、これで良いと思う。