// 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