performance/Tutorial_Multithread_Multiworld.cpp

performance/Tutorial_Multithread_Multiworld.cpp
/*
* Copyright 2015 Autodesk, Inc. All rights reserved.
* Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
* or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
*/
#include "GwNavTestFwk/GwNavTestFwk.h"
#include "common/basesystemenv.h"
#include "LabEngine/gameworld.h"
//RUN_THIS_FILE
// TUTORIAL FOR MMO
// Irrelevant scenario for consoles or mobile platforms
#if !defined (KY_OS_WIN32) && !defined(KY_OS_LINUX) && !defined(KY_OS_MAC)
DONT_RUN_THIS_FILE
#endif
namespace
{
class MultiWorldThread : public Kaim::Thread
{
KY_CLASS_WITHOUT_COPY(MultiWorldThread)
public:
explicit MultiWorldThread(const Kaim::KyArray<Kaim::Ptr<Kaim::BlobAggregate> > sharedMemoryNavData)
: m_numWorlds(5)
, m_numBots(10)
, m_secondsToUpdate(2)
, m_sharedMemoryNavData(sharedMemoryNavData) {}
virtual int Run()
{
Kaim::KyArray<bool > navDataLoadedStatus;
const KyUInt32 navDataCount = m_sharedMemoryNavData.GetCount();
navDataLoadedStatus.Resize(m_numWorlds * navDataCount);
navDatas.Resize(m_numWorlds * navDataCount);
for (KyUInt32 worldIndex = 0; worldIndex < m_numWorlds; ++worldIndex)
{
worlds.PushBack(*KY_NEW LabEngine::GameWorld);
worlds.Back()->Initialize(1, LabEngine::WorkerThreadDeactivated);
Kaim::Database* database = worlds.Back()->GetWorld()->GetDatabase(0);
// We add the shared data to the world.
for (KyUInt32 navDataIndex = 0; navDataIndex < m_sharedMemoryNavData.GetCount(); ++navDataIndex)
{
Kaim::Ptr<Kaim::NavData> navData = *KY_NEW Kaim::NavData;
navData->SetBlobAggregate(m_sharedMemoryNavData[navDataIndex]);
worlds.Back()->AddToDatabase(navData);
navDatas[worldIndex*navDataCount + navDataIndex] = navData;
navDataLoadedStatus[worldIndex*navDataCount + navDataIndex] = true;
}
// make sure all the NavData are fully loaded
while ((database->IsThereNavDataToBeAddedOrRemoved() == true || database->IsDatabaseUpdatingNavData() == true))
worlds.Back()->Update(0.016f);
// We create the bots for the world.
if (m_numBots > 0)
{
LabEngine::GameBotInitConfig config;
config.m_botInitConfig.m_database = worlds.Back()->GetWorld()->GetDatabase(0);
worlds.Back()->AddRandomBots(m_numBots, config);
}
}
Kaim::Profiler profiler;
// The world is now correctly setup. We update it for a while.
while (profiler.GetSeconds() < m_secondsToUpdate)
{
for (KyUInt32 worldIndex = 0; worldIndex < worlds.GetCount(); worldIndex++)
worlds[worldIndex]->Update(0.0166f);
}
return 0;
}
private:
const KyUInt32 m_numWorlds;
const KyUInt32 m_numBots;
const KyUInt32 m_secondsToUpdate;
const Kaim::KyArray<Kaim::Ptr<Kaim::BlobAggregate> > m_sharedMemoryNavData;
};
class AsyncMultiWordTutorialEnv : public BaseSystemEnv
{
bool LoadNavData(const std::string& rootFolder, const std::string& indexFileName, Kaim::KyArray<Kaim::Ptr<Kaim::BlobAggregate> >& navDataLoaded)
{
// Load NavDataIndex
Kaim::Ptr< Kaim::BlobHandler<Kaim::NavDataIndex> > navDataIndexHandler = Kaim::NavDataIndexLoader::LoadNavDataIndex(
GetAbsoluteInputFileName(rootFolder + indexFileName).c_str(), &m_fileOpener);
if (navDataIndexHandler == KY_NULL)
return false;
Kaim::NavDataIndex* navDataIndex = navDataIndexHandler->Blob();
if (navDataIndex == KY_NULL)
return false;
// Load each sector
for (KyUInt32 i = 0; i < navDataIndex->GetDescriptorsCount(); ++i)
{
navDataLoaded.PushBack(*KY_NEW Kaim::BlobAggregate);
const std::string sectorFileName(navDataIndex->GetDescriptor(i).m_fileName.GetValues());
if (Kaim::Result::Fail(navDataLoaded[i]->Load(GetAbsoluteInputFileName(rootFolder + sectorFileName).c_str(), &m_fileOpener)))
{
navDataLoaded.Clear();
return false;
}
}
return true;
}
public:
bool Run()
{
KT_LOG_TITLE_BEGIN("TUTORIAL - AsyncMultiWorld");
// First, load the data that will be shared across all worlds, once.
const std::string rootFolder("GeneratedNavData/city_9SectorsAndSeeds/");
const std::string indexFileName("city_9SectorsAndSeeds.GenIO");
if (!LoadNavData(rootFolder, indexFileName, loadedNavData))
return false;
KyUInt32 numThreads = 4;
// We create our threads and pass them the shared data.
for(KyUInt32 i = 0; i < numThreads; ++i)
{
threadHandles.PushBack( *KY_NEW MultiWorldThread(loadedNavData) );
threadHandles[i]->Start();
}
// Wait till threads have completed.
for(KyUInt32 i = 0; i < numThreads; ++i)
{
threadHandles[i]->Wait();
}
return true;
}
};
#define TEST_ENV_CLASS AsyncMultiWordTutorialEnv
TEST_ENV {}
TEST //("Run 5 worlds of 20 entities in 4 separate threads.")
{
CHECK( env.Run() );
}
} // anonymous namespace