root/trunk/0037_SynchronizedObject/SynchronizedObjectTest.cpp

User picture

Author: Setsu

Revision: 348 («Previous)


File Size: 6.68 KB

(June 30, 2010 09:07 UTC) Almost 2 years ago

Changed the number of SynchronizedObject from 3 to 6.

 
Show/hide line numbers
//
//  SynchronizedObjectTest.cpp
//
//  Created by Setsu on 6/29/10.
//  Copyright 2010 RoundSquare Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

//----------------------------------------
//	include
//----------------------------------------
#include <Poco/Logger.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/SynchronizedObject.h>
#include <Poco/Runnable.h>
#include <Poco/Thread.h>
#include <Poco/Format.h>
#include <Poco/Stopwatch.h>

#include <string>

#include "ScopedLogMessage.h"

//----------------------------------------
//	const
//----------------------------------------
const std::size_t kNumThreads = 3;
const std::size_t kNumSyncObjects = 2*kNumThreads;
const std::size_t kNumJobs = 4;

enum
{
	eNotifyNone = 0
,	eNotifyAB
,	eNotifyAC
,	eNotifyBA
,	eNotifyBC
,	eNotifyCA
,	eNotifyCB
};

enum
{
	eWaitNone = 0
,	eWaitAB
,	eWaitAC
,	eWaitBA
,	eWaitBC
,	eWaitCA
,	eWaitCB
};

typedef struct
{
	long	sleep;
	int		notify[kNumThreads-1];
	int		wait;
} JobSpec;

const JobSpec kJobSpec[kNumThreads][kNumJobs] =
{
	{	// for threadA
		{	200,	{eNotifyAB,   eNotifyAC},	eWaitBA	}
	,	{	100,	{eNotifyNone, eNotifyNone},	eWaitCA	}
	,	{	 50,	{eNotifyNone, eNotifyNone},	eWaitNone	}
	,	{	400,	{eNotifyNone, eNotifyNone},	eWaitNone	}
	},
	{	// for threadB
		{	 50,	{eNotifyNone, eNotifyNone},	eWaitAB	}
	,	{	200,	{eNotifyBA,   eNotifyBC},	eWaitCB	}
	,	{	100,	{eNotifyNone, eNotifyNone},	eWaitNone	}
	,	{	400,	{eNotifyNone, eNotifyNone},	eWaitNone	}
	},
	{	// for threadC
		{	100,	{eNotifyNone, eNotifyNone},	eWaitAC	}
	,	{	 50,	{eNotifyNone, eNotifyNone},	eWaitBC	}
	,	{	200,	{eNotifyCA,   eNotifyCB},	eWaitNone	}
	,	{	550,	{eNotifyNone, eNotifyNone},	eWaitNone	}
	}
};

//----------------------------------------
//	MySyncObject
//----------------------------------------
class MySyncObject: public Poco::SynchronizedObject
{
public:
	MySyncObject() :
		m_Name("")
	{
	}

	void setName(const std::string& name)
	{
		m_Name = name;
	}

	std::string getName(void) const
	{
		return m_Name;
	}

private:
	std::string	m_Name;
};

//----------------------------------------
//	MyRunnable
//----------------------------------------
class MyRunnable : public Poco::Runnable
{
public:
	MyRunnable() :
		m_pMsg(NULL)
	,	m_pStopwatch(NULL)
	,	m_Index(0)
	,	m_IndexChar('A')
	,	m_SyncObjects(NULL)
	{
	}

	void setIndex(ScopedLogMessage* pMsg
					, Poco::Stopwatch* pStopwatch
					, std::size_t index
					, MySyncObject* syncObjects)
	{
		m_pMsg = pMsg;
		m_pStopwatch = pStopwatch;
		m_Index = index;
		m_IndexChar = static_cast<char>(m_IndexChar+index);
		m_SyncObjects = syncObjects;
	}

	void run()
	{
		if(NULL != m_pMsg)
		{
			for(std::size_t i=0; i<kNumJobs; ++i)
			{
				const JobSpec& spec = kJobSpec[m_Index][i];

				job(i, spec);

				for(std::size_t j=0; j<kNumThreads-1; ++j)
				{
					int notify = spec.notify[j];
					if(eNotifyNone != notify)
					{
						s_Indent += " ";
						m_SyncObjects[--notify].notify();
					}
				}

				int wait = spec.wait;
				if(eWaitNone != wait)
				{
					m_pMsg->Message(Poco::format("%06Ld %s Thread%c sleeps"
										, m_pStopwatch->elapsed()/1000
										, s_Indent
										, m_IndexChar));

					m_SyncObjects[--wait].wait();

					m_pMsg->Message(Poco::format("%06Ld %s Thread%c woke up by SyncObject%s"
										, m_pStopwatch->elapsed()/1000
										, s_Indent
										, m_IndexChar
										, m_SyncObjects[wait].getName()));
				}
			}
		}
	}

private:
	void job(std::size_t jobIndex, const JobSpec& spec)
	{
		++jobIndex;
		m_pMsg->Message(Poco::format("%06Ld %s Thread%c Job%z start"
										, m_pStopwatch->elapsed()/1000
										, s_Indent
										, m_IndexChar
										, jobIndex));
		Poco::Thread::sleep(spec.sleep);
		m_pMsg->Message(Poco::format("%06Ld %s Thread%c Job%z end"
										, m_pStopwatch->elapsed()/1000
										, s_Indent
										, m_IndexChar
										, jobIndex));
	}

	static std::string	s_Indent;
	ScopedLogMessage*	m_pMsg;
	Poco::Stopwatch*	m_pStopwatch;
	std::size_t			m_Index;
	char				m_IndexChar;
	MySyncObject*		m_SyncObjects;
};

std::string MyRunnable::s_Indent = "";

//----------------------------------------
//	PrepareConsoleLogger
//----------------------------------------
void PrepareConsoleLogger(const std::string& name, int level=Poco::Message::PRIO_INFORMATION)
{
	Poco::FormattingChannel* pFCConsole = new Poco::FormattingChannel(new Poco::PatternFormatter("%t"));
	pFCConsole->setChannel(new Poco::ConsoleChannel);
	pFCConsole->open();

	Poco::Logger::create(name, pFCConsole, level);
}

//----------------------------------------
//	main
//----------------------------------------
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);

	ScopedLogMessage msg("SynchronizedObjectTest ", "start", "end");

	Poco::Stopwatch		stopwatch;
	Poco::Thread		thread[kNumThreads];
	MyRunnable			runnable[kNumThreads];
	MySyncObject		syncObjects[kNumSyncObjects];
	const std::string	SyncObjNameTable[kNumSyncObjects] =
							{"AB", "AC", "BA", "BC", "CA", "CB"};

	for(std::size_t i=0; i<kNumThreads; ++i)
	{
		runnable[i].setIndex(&msg, &stopwatch, i, syncObjects);
	}
	for(std::size_t i=0; i<kNumSyncObjects; ++i)
	{
		syncObjects[i].setName(SyncObjNameTable[i]);
	}

	stopwatch.start();

	for(std::size_t i=0; i<kNumThreads; ++i)
	{
		thread[i].start(runnable[i]);
	}

	for(std::size_t i=0; i<kNumThreads; ++i)
	{
		thread[i].join();
	}

	return 0;
}