// 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 .
#include "stdmisc.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"
#include "nel/misc/async_file_manager.h"
using namespace std;
namespace NLMISC
{
//CAsyncFileManager *CAsyncFileManager::_Singleton = NULL;
NLMISC_SAFE_SINGLETON_IMPL(CAsyncFileManager);
// ***************************************************************************
/*CAsyncFileManager::CAsyncFileManager()
{
}
*/
// ***************************************************************************
/*CAsyncFileManager &CAsyncFileManager::getInstance()
{
if (_Singleton == NULL)
{
_Singleton = new CAsyncFileManager();
}
return *_Singleton;
}
*/
// ***************************************************************************
void CAsyncFileManager::terminate ()
{
if (_Instance != NULL)
{
INelContext::getInstance().releaseSingletonPointer("CAsyncFileManager", _Instance);
delete _Instance;
_Instance = NULL;
}
}
void CAsyncFileManager::addLoadTask(IRunnable *ploadTask)
{
addTask(ploadTask);
}
bool CAsyncFileManager::cancelLoadTask(const CAsyncFileManager::ICancelCallback &callback)
{
CSynchronized >::CAccessor acces(&_TaskQueue);
list &rTaskQueue = acces.value ();
list::iterator it = rTaskQueue.begin();
while (it != rTaskQueue.end())
{
IRunnable *pR = it->Task;
// check the task with the cancel callback.
if (callback.callback(pR))
{
// Delete the load task
delete pR;
rTaskQueue.erase (it);
return true;
}
++it;
}
// If not found, the current running task may be the one we want to cancel. Must wait it.
// Beware that this code works because of the CSynchronized access we made above (ensure that the
// taskmanager will end just the current task async (if any) and won't start an other one.
waitCurrentTaskToComplete ();
return false;
}
// ***************************************************************************
/*
void CAsyncFileManager::loadMesh(const std::string& meshName, IShape **ppShp, IDriver *pDriver)
{
addTask (new CMeshLoad(meshName, ppShp, pDriver));
}
*/
// ***************************************************************************
/*
bool CAsyncFileManager::cancelLoadMesh(const std::string& sMeshName)
{
CSynchronized >::CAccessor acces(&_TaskQueue);
list &rTaskQueue = acces.value ();
list::iterator it = rTaskQueue.begin();
while (it != rTaskQueue.end())
{
IRunnable *pR = *it;
CMeshLoad *pML = dynamic_cast(pR);
if (pML != NULL)
{
if (pML->MeshName == sMeshName)
{
// Delete mesh load task
delete pML;
rTaskQueue.erase (it);
return true;
}
}
++it;
}
return false;
}
*/
// ***************************************************************************
/*
void CAsyncFileManager::loadIG (const std::string& IGName, CInstanceGroup **ppIG)
{
addTask (new CIGLoad(IGName, ppIG));
}
// ***************************************************************************
void CAsyncFileManager::loadIGUser (const std::string& IGName, UInstanceGroup **ppIG)
{
addTask (new CIGLoadUser(IGName, ppIG));
}
*/
// ***************************************************************************
void CAsyncFileManager::loadFile (const std::string& sFileName, uint8 **ppFile)
{
addTask (new CFileLoad (sFileName, ppFile));
}
// ***************************************************************************
void CAsyncFileManager::loadFiles (const std::vector &vFileNames, const std::vector &vPtrs)
{
addTask (new CMultipleFileLoad (vFileNames, vPtrs));
}
// ***************************************************************************
void CAsyncFileManager::signal (bool *pSgn)
{
addTask (new CSignal (pSgn));
}
// ***************************************************************************
void CAsyncFileManager::cancelSignal (bool *pSgn)
{
CSynchronized >::CAccessor acces(&_TaskQueue);
list &rTaskQueue = acces.value ();
list::iterator it = rTaskQueue.begin();
while (it != rTaskQueue.end())
{
IRunnable *pR = it->Task;
CSignal *pS = dynamic_cast(pR);
if (pS != NULL)
{
if (pS->Sgn == pSgn)
{
// Delete signal task
delete pS;
rTaskQueue.erase (it);
return;
}
}
++it;
}
}
// ***************************************************************************
// FileLoad
// ***************************************************************************
// ***************************************************************************
CAsyncFileManager::CFileLoad::CFileLoad (const std::string& sFileName, uint8 **ppFile)
{
_FileName = sFileName;
_ppFile = ppFile;
}
// ***************************************************************************
void CAsyncFileManager::CFileLoad::run (void)
{
FILE *f = fopen (_FileName.c_str(), "rb");
if (f != NULL)
{
uint8 *ptr;
long filesize=CFile::getFileSize (f);
//fseek (f, 0, SEEK_END);
//long filesize = ftell (f);
//nlSleep(5);
//fseek (f, 0, SEEK_SET);
ptr = new uint8[filesize];
if (fread (ptr, filesize, 1, f) != 1)
nlwarning("AFM: Couldn't read '%s'", _FileName.c_str());
fclose (f);
*_ppFile = ptr;
}
else
{
nlwarning ("AFM: Couldn't load '%s'", _FileName.c_str());
*_ppFile = (uint8*)-1;
}
}
// ***************************************************************************
void CAsyncFileManager::CFileLoad::getName (std::string &result) const
{
result = "FileLoad (" + _FileName + ")";
}
// ***************************************************************************
// MultipleFileLoad
// ***************************************************************************
// ***************************************************************************
CAsyncFileManager::CMultipleFileLoad::CMultipleFileLoad (const std::vector &vFileNames,
const std::vector &vPtrs)
{
_FileNames = vFileNames;
_Ptrs = vPtrs;
}
// ***************************************************************************
void CAsyncFileManager::CMultipleFileLoad::run (void)
{
for (uint32 i = 0; i < _FileNames.size(); ++i)
{
FILE *f = fopen (_FileNames[i].c_str(), "rb");
if (f != NULL)
{
uint8 *ptr;
long filesize=CFile::getFileSize (f);
//fseek (f, 0, SEEK_END);
//long filesize = ftell (f);
//nlSleep(5);
//fseek (f, 0, SEEK_SET);
ptr = new uint8[filesize];
if (fread (ptr, filesize, 1, f) != 1)
nlwarning("AFM: Couldn't read '%s'", _FileNames[i].c_str());
fclose (f);
*_Ptrs[i] = ptr;
}
else
{
nlwarning ("AFM: Couldn't load '%s'", _FileNames[i].c_str());
*_Ptrs[i] = (uint8*)-1;
}
}
}
// ***************************************************************************
void CAsyncFileManager::CMultipleFileLoad::getName (std::string &result) const
{
result = "MultipleFileLoad (";
uint i;
for (i=0; i<_FileNames.size (); i++)
{
if (i)
result += ", ";
result += _FileNames[i];
}
result += ")";
}
// ***************************************************************************
// Signal
// ***************************************************************************
// ***************************************************************************
CAsyncFileManager::CSignal::CSignal (bool *pSgn)
{
Sgn = pSgn;
*Sgn = false;
}
// ***************************************************************************
void CAsyncFileManager::CSignal::run (void)
{
*Sgn = true;
}
// ***************************************************************************
void CAsyncFileManager::CSignal::getName (std::string &result) const
{
result = "Signal";
}
} // NLMISC