// pool.cpp : コンソール アプリケーション用のエントリ ポイントの定義
//

#include "stdafx.h"
#include "pool2.h"
#include <string>
#include <memory>
#include <vector>
#include <boost/pool/object_pool.hpp>
#include <misc/StopWatch.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

typedef const char cchar;
typedef const CString cCString;

#if 0
ostream operator<<(ostream &out, const CString &text)
{
	out << (const tchar *)text;
	return out;
}
#endif

/////////////////////////////////////////////////////////////////////////////
// 唯一のアプリケーション オブジェクト

CWinApp theApp;

using namespace std;

#define		OBJECT_POOL		1		//	boost::object_pool 使用

//----------------------------------------------------------------------

struct CNode		//	双方向リンク
{
	CNode	*m_next;
	CNode	*m_prev;
public:
	CNode() {};
	~CNode() {};

	void	link(CNode *next)
	{
		m_next = next;
		next->m_prev = this;
	};
};
struct CLineNode : public CNode		//	行ノード
{
	CString	m_text;
public:
	CLineNode() {};
	CLineNode(cCString &text) : m_text(text) {};
	~CLineNode() {};
};
class CLineMgr		//	行管理クラス
{
	int			m_nLines;			//	行数
	CLineNode	*m_dummy;			//	ダミー行へのポインタ
#if		OBJECT_POOL
	boost::object_pool<CLineNode> pool;
#endif
public:
	CLineMgr();
	~CLineMgr();

	bool	appendLine(cCString&);				//	EOF行の直後に1行追加

	const CLineNode	*getLineNode(int);
protected:
	bool	removeAll();						//	全ての行を削除

};
CLineMgr::CLineMgr()
{
	m_nLines = 0;
#if		OBJECT_POOL
	m_dummy = pool.construct();
#else
	m_dummy = new CLineNode;
#endif
	m_dummy->link(m_dummy);
}
CLineMgr::~CLineMgr()
{
}
bool CLineMgr::appendLine(cCString &text)
{
	m_nLines += 1;
#if		OBJECT_POOL
	CLineNode *np = pool.construct(text);
#else
	CLineNode *np = new CLineNode(text);
#endif
	m_dummy->m_prev->link(np);					//	ダミーの直前に挿入
	np->link(m_dummy);
	return true;
}
const CLineNode *CLineMgr::getLineNode(int line)
{
	if( line <= 0 || line > m_nLines )
		return NULL;
	CLineNode *ptr = m_dummy;
	for(int i = 0; i < line; ++i)
		ptr = (CLineNode *)ptr->m_next;
	return ptr;
}
//----------------------------------------------------------------------

#define		N_LOOP	1
#define		N_LINES	10000

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		return 1;
	}
	cout << "pool test\n\n";
	
	if( 0 ) {
		auto_ptr<StopWatch<> > sw(new StopWatch<>);
		CString text(_T("abc\n"));
		cout << (cchar*)text << "\n";
		printf("%s", text);
		double sum = 1.0;
		for(int i = 0; i < 1000000; ++i)
			sum *= 2;
	}
	{
		cout << "固定文字列\n";
		auto_ptr<StopWatch<> > sw(new StopWatch<>);
		CString text("123456789\n");
		for(int i = 0; i < N_LOOP; ++i) {
			CLineMgr lineMgr;
			for(int k = 0; k < N_LINES; ++k) {
				lineMgr.appendLine(text);
			}
		}
	}
	if( 1 ) {
		cout << "行ごとに異なる文字列の生成のみ\n";
		auto_ptr<StopWatch<> > sw(new StopWatch<>);
		CString text;
		for(int i = 0; i < N_LOOP; ++i) {
			CLineMgr lineMgr;
			for(int k = 0; k < N_LINES; ++k) {
				text.Format("line %d\n", k + 1);
				//lineMgr.appendLine(text);
			}
		}
	}
	if( 1 ) {
		cout << "行ごとに異なる文字列を lineMgr に append\n";
		auto_ptr< StopWatch<> > sw(new StopWatch<>);
		CString text;
		for(int i = 0; i < N_LOOP; ++i) {
			CLineMgr lineMgr;
			for(int k = 0; k < N_LINES; ++k) {
				text.Format("line %d\n", k + 1);
				lineMgr.appendLine(text);
			}
#if 0	//	文字列がちゃんと格納されているか確認
			const CLineNode *ptr = lineMgr.getLineNode(1);
			ASSERT( ptr != NULL );
			for(int j = 0; j < N_LINES; ++j, ptr = (CLineNode *)ptr->m_next) {
				text.Format("line %d\n", j + 1);
				if( text != ptr->m_text )
					cout << "error at line " << (j+1) << "\n";
			}
#endif
		}
	}

	cout << "\nHit Any Key.\n";
	getchar();
	return 0;
}


