I/Oポートのライブラリ

途中までできた。バッファとファイル間が自由になったヽ(´ー`)ノ

使い心地はこんな。

	completion_port port;
	port.initialize();

	parallel_pipeline pipeline(port);

	HANDLE file=CreateFile(_T("test.txt")
		,GENERIC_READ,FILE_SHARE_READ
		,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);

	file_input_device ifile_dev(file);
	pipeline >> ifile_dev >> obuffer_dev;
	pipeline.async();
	pipeline.join();

	CloseHandle(file);
	port.finalize();

あぁ・・シンプルでいいかも。

同じ要領でバッファからファイル、バッファからバッファ、ファイルからバッファに対して

非同期I/Oができちゃう。

CreateFileを外側でやってるのはdeviceクラスは

同期/非同期のI/Oをパイプライン的にするためだけに特化したかったため。

もっと言うとI/O自体も関係なくて同期/非同期のコールバックシステムという感じにしました。

そのコールバックにIOCPが使われてて、だからバッファがあるかどうかは任意みたいなつくりになってます。


何日か前に書いた非同期の並列計算処理をパイプライン化みたいなこともがんばればできるかも。

おかげで作るのが余計に大変になった気がします・・・特にWriteFile。


こんなつくりにしたかった理由は、たとえばAcceptEx

これはwinsock2の非同期版acceptでaccept+はじめのデータのReceiveが可能だそうで

まぁデータ自体は受け取るのは任意なのですが、どうやらこれにIOCPが対応してるようで

これもパイプラインに組み込みたいなーと・・・

データがなしの場合にGetQueuedCompletionStatusが反応するかは謎なんですけどねw

それはまたこれから作るってことで

まだまだ試行錯誤は続きます。

ヽ(`Д´)ノウワァァァン!!

開発中のソースより抜粋

	...
	if(CreateIoCompletionPort(handle,handle_,completion_key,0)==0)
		//エラー処理
	...
	unsigned long buffer_size=(unsigned long)operation.buffer_->capacity()-operation.buffer_->offset();
	if(ReadFileEx(handle_,(void*)operation.buffer_->begin(),buffer_size,(LPOVERLAPPED)&operation,0)==0)
		//エラー処理


なぜかReadFileEx君が毎回エラーの困ったちゃん

いろいろ修正してみても全然だめ

MSDNを見てるとCreateIoCompletionPortのところに

開いたファイルのインスタンスを I/O 完了ポートに関連付けた後は、このインスタンスを  ReadFileEx 関数、
または  WriteFileEx 関数で使うことはできません。


あいた口がふさがらない。

ちなみにwinsock2のSOCKETではRecvExを使うべし。->WSARecvの間違い

1時間無駄にしましたw

\(^o^)/\(^o^)/\(^o^)/

全enumが泣いた

どうもC++enumは使いにくいときがあって困る。

たとえばseek関数を作るときに

	enum seek_option
	{
		...
		seek_end,
		...
	};

	class file
	{
		...
		void seek(unsigned long offset,seek_option option);
		...
	};

	file f;
	f.seek(100,seek_option::seek_end);


といった感じで使いたい。ところがseek_option::seek_endという使い方は非標準だしダメダメと警告がでる(VS2005)

えー・・と思いつつ一瞬脳内で思いついたのが

	struct seek_option
	{
		...
		static const int seek_end=3,
		...
	};


でもこれじゃあseek関数のプロトタイプと合わないね・・

こんなときこそtag dispatchなのかしら・・・

	template <int i>
	struct int_to_type
	{
		enum{value=i};
	};

	struct seek_option
	{
		...
		typedef int_to_type<3> seek_end;
		...
	};

	class file
	{
		...
		void seek(unsigned long offset,seek_option::seek_end option);
		...
	};

	file f;
	f.seek(100,seek_option::seek_end());


これが一番ましかなぁ。

int_to_typeの中身がenumだけになんかだまされてるような気がw

boost::anyとType Erasure

復習しないと復習しないと

Type Erasureの本質は型を消すことにあるんじゃなくて

消した型をtype safeに元に戻せることにあるんじゃないのかな・・

ぐぐって見るとstruct anyのほうは結構あるのにany_castのほうはあまり触れてないのよね

というわけでサンプルを書いてみるテスト



#include <tchar.h>
#include <string>

#include <boost/type_traits.hpp>

struct any
{
	struct placeholder
	{
		virtual ~placeholder()
		{
		}
		virtual const std::type_info& type() const = 0;
	};

	template <typename T>
	struct holder
		:public placeholder
	{
		holder(const T& value)
			:value_(value)
		{
		}
		virtual const std::type_info& type() const
		{
			return typeid(T);
		}
		T value_;
	};

	template <typename T>
	any(const T& value)
		:holder_(new holder<T>(value))
	{
	}

	~any()
	{
		delete holder_;
	}
	placeholder* holder_;

	template <typename T>
	friend T any_cast(const any& a);
};

template <typename T>
T any_cast(const any& a)
{
	typedef typename boost::remove_reference<T>::type cast_type;

	if(typeid(cast_type)!=a.holder_->type())
		printf("cast error\n");

	return (static_cast<any::holder<cast_type>*>(a.holder_))->value_;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int i=5;
	any a(i);
	int j=any_cast<int>(a);
	printf("j=%d\n",j);

	std::string s("abc");
	any b(s);
	std::string t=any_cast<std::string>(b);
	printf("t=%s\n",t.c_str());

	struct vec
	{
		long x;
		long y;
	};

	vec v;
	v.x=10;
	v.y=20;
	any c(v);
	printf("vec=(%d,%d)\n",any_cast<vec>(c).x,any_cast<vec>(c).y);
}

今日も元気にMMOつくるお!

せっかくなのでMMO作成カテゴリでも作ってみます。


MMO作るのは思った以上にしんどいですよね。

いまどきこんなこと言ってたら脳外科池って言われそうですw

前回マルベリーフィールドの時にもかなりの量のソースコードを書きました。

今回もC++で作ろうと思っていますがあの時とは違って今はboostがありますし

かなり開発効率もよくなるんじゃないかな。


とはいってもやっぱりやらないといけないことはたくさんですので

その中でいろいろポイントになることや苦戦したことでも書いてけたらなーと。


おそらくMMOを作るのにとって一番必要なのは『考えること』

これしかないと思います。

ほかのwindowsアプリケーションのようにぐぐってみてもMMOのサンプルソースなんて

なかなかないでしょうし、あったとしても膨大で参考になるか分かりません。

どういう風に設計したらいいか、実装したらいいのか情報を自分で調べて考えて決めてください。

これができないとおそらく開発するのは難しいです。


ちなみに現在はベースとなるライブラリを作ってます。

これの良し悪しで今後のすっきり感がえらい違うのでがんばらないと。

内容は最近IOCPの話題しかないとおり、IOCPサーバー、クライアントのフレームワーク部分ですね。

このフレームワークを設計中なのであります。


どんな構成があるのかはWinsock Programmer's FAQに詳しくありますのでそちらを見てください。

Winsock Programmer's FAQ
第7章 論説記事: どの I/O 戦略を使うべきか?
http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/io-strategies.html