// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef UT_MISC_CO_TASK
#define UT_MISC_CO_TASK
#include
#include
const char *referenceResult[] =
{
"Task1 : 0",
"Task2 : 0",
"Main : 0",
"Task1 : 1",
"Task2 : 1",
"Main : 1",
"Task1 : 2",
"Task2 : 2",
"Task1 : 3",
"Task2 : 3",
"Task1 : 4",
"Task2 : 4",
"Task2 : 5",
"Task2 : 6",
};
const char *referenceResultThread1[] =
{
"Task1 : 0",
"Thread : 0",
"Task1 : 1",
"Thread : 1",
"Task1 : 2",
"Thread : 2",
"Task1 : 3",
"Thread : 3",
"Task1 : 4",
"Thread : 4",
};
const char *referenceResultThread2[] =
{
"Task2 : 0",
"Main : 0",
"Task2 : 1",
"Main : 1",
"Task2 : 2",
"Task2 : 3",
"Task2 : 4",
};
vector result;
vector result2;
// a simple task
class CTask1 : public NLMISC::CCoTask
{
vector &Output;
public:
CTask1(vector &output = result)
: Output(output)
{}
void run()
{
for (uint i=0; i<5; ++i)
{
string s = NLMISC::toString("Task1 : %u", i);
Output.push_back(s);
yield();
}
}
};
// another simple task
class CTask2 : public NLMISC::CCoTask
{
vector &Output;
public:
CTask2(vector &output = result)
: Output(output)
{}
void run()
{
for (uint i=0; i<7; ++i)
{
string s = NLMISC::toString("Task2 : %u", i);
Output.push_back(s);
yield();
}
}
};
// a thread runnable class
class CTaskThread : public NLMISC::IRunnable
{
void run()
{
CTask1 t1(result2);
for (uint i=0; i<5; ++i)
{
t1.resume();
string s = NLMISC::toString("Thread : %u", i);
result2.push_back(s);
NLMISC::nlSleep(0);
}
}
};
// Test suite for coroutine task
class CUTMiscCoTask: public Test::Suite
{
public:
CUTMiscCoTask()
{
TEST_ADD(CUTMiscCoTask::runTasks);
TEST_ADD(CUTMiscCoTask::tasksAndThreads);
}
void tasksAndThreads()
{
// test running task in two separate thread (this stress the
// multithreading support of task). CoTask API ;ake use of
// thread local storage API to store by thread current task info.
result.clear();
result2.clear();
CTaskThread tt;
NLMISC::IThread *th = NLMISC::IThread::create(&tt);
CTask2 t2;
// start the thread
th->start();
for (uint i=0; i<2; ++i)
{
t2.resume();
string s = NLMISC::toString("Main : %u", i);
result.push_back(s);
NLMISC::nlSleep(0);
}
// wait task completion
t2.wait();
// wait thread completion
th->wait();
delete th;
// test result
for (uint i=0; i