Turned more global objects into pointers in order to allow late initialization. Also slightly restructured the global locks and added another global lock to guard the IPC struct.

This commit is contained in:
LoRd_MuldeR 2012-08-18 16:36:39 +02:00
parent 2cb3ec7719
commit eb88a05341
2 changed files with 150 additions and 91 deletions

View File

@ -30,7 +30,7 @@
#define VER_LAMEXP_MINOR_LO 5
#define VER_LAMEXP_TYPE Beta
#define VER_LAMEXP_PATCH 4
#define VER_LAMEXP_BUILD 1087
#define VER_LAMEXP_BUILD 1089
///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!)

View File

@ -86,6 +86,8 @@ Q_IMPORT_PLUGIN(QICOPlugin)
#endif
#endif
#define LAMEXP_ZERO_MEMORY(X) SecureZeroMemory(&X, sizeof(X))
///////////////////////////////////////////////////////////////////////////////
// TYPES
///////////////////////////////////////////////////////////////////////////////
@ -201,8 +203,8 @@ static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO
//Special folders
static struct
{
QString temp;
QString knownFolders[3];
QString *temp;
QMap<size_t, QString> *knownFolders;
QReadWriteLock lock;
}
g_lamexp_folder;
@ -210,8 +212,8 @@ g_lamexp_folder;
//Tools
static struct
{
QMap<QString, LockedFile*> registry;
QMap<QString, unsigned int> versions;
QMap<QString, LockedFile*> *registry;
QMap<QString, unsigned int> *versions;
QReadWriteLock lock;
}
g_lamexp_tools;
@ -219,10 +221,10 @@ g_lamexp_tools;
//Languages
static struct
{
QMap<QString, QString> files;
QMap<QString, QString> names;
QMap<QString, unsigned int> sysid;
QMap<QString, unsigned int> cntry;
QMap<QString, QString> *files;
QMap<QString, QString> *names;
QMap<QString, unsigned int> *sysid;
QMap<QString, unsigned int> *cntry;
QReadWriteLock lock;
}
g_lamexp_translation;
@ -230,11 +232,19 @@ g_lamexp_translation;
//Translator
static struct
{
QVariant instance;
QTranslator *instance;
QReadWriteLock lock;
}
g_lamexp_currentTranslator;
//CLI Arguments
static struct
{
QStringList *list;
QReadWriteLock lock;
}
g_lamexp_argv;
//Shared memory
static const struct
{
@ -259,11 +269,9 @@ static struct
QSystemSemaphore *semaphore_read_mutex;
QSystemSemaphore *semaphore_write;
QSystemSemaphore *semaphore_write_mutex;
QReadWriteLock lock;
}
g_lamexp_ipc_ptr =
{
NULL, NULL, NULL
};
g_lamexp_ipc_ptr;
//Image formats
static const char *g_lamexp_imageformats[] = {"bmp", "png", "jpg", "gif", "ico", "xpm", NULL}; //"svg"
@ -277,14 +285,6 @@ static const DWORD g_main_thread_id = GetCurrentThreadId();
//Log file
static FILE *g_lamexp_log_file = NULL;
//CLI Arguments
static struct
{
QStringList list;
QReadWriteLock lock;
}
g_lamexp_argv;
///////////////////////////////////////////////////////////////////////////////
// GLOBAL FUNCTIONS
///////////////////////////////////////////////////////////////////////////////
@ -1182,8 +1182,10 @@ bool lamexp_init_qt(int argc, char* argv[])
//Add default translations
QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
g_lamexp_translation.files.insert(LAMEXP_DEFAULT_LANGID, "");
g_lamexp_translation.names.insert(LAMEXP_DEFAULT_LANGID, "English");
if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
g_lamexp_translation.files->insert(LAMEXP_DEFAULT_LANGID, "");
g_lamexp_translation.names->insert(LAMEXP_DEFAULT_LANGID, "English");
writeLockTranslations.unlock();
//Check for process elevation
@ -1223,6 +1225,8 @@ bool lamexp_init_qt(int argc, char* argv[])
*/
int lamexp_init_ipc(void)
{
QWriteLocker writeLock(&g_lamexp_ipc_ptr.lock);
if(g_lamexp_ipc_ptr.sharedmem && g_lamexp_ipc_ptr.semaphore_read && g_lamexp_ipc_ptr.semaphore_write && g_lamexp_ipc_ptr.semaphore_read_mutex && g_lamexp_ipc_ptr.semaphore_write_mutex)
{
return 0;
@ -1315,6 +1319,8 @@ int lamexp_init_ipc(void)
*/
void lamexp_ipc_send(unsigned int command, const char* message)
{
QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
{
throw "Shared memory for IPC not initialized yet.";
@ -1347,6 +1353,8 @@ void lamexp_ipc_send(unsigned int command, const char* message)
*/
void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize)
{
QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
*command = 0;
message[0] = '\0';
@ -1416,17 +1424,26 @@ const QString &lamexp_temp_folder2(void)
QReadLocker readLock(&g_lamexp_folder.lock);
//Already initialized?
if(!g_lamexp_folder.temp.isEmpty())
if(g_lamexp_folder.temp)
{
if(QDir(g_lamexp_folder.temp).exists())
if(!g_lamexp_folder.temp->isEmpty())
{
return g_lamexp_folder.temp;
if(QDir(*g_lamexp_folder.temp).exists())
{
return *g_lamexp_folder.temp;
}
}
}
readLock.unlock();
QWriteLocker writeLock(&g_lamexp_folder.lock);
g_lamexp_folder.temp.clear();
if(!g_lamexp_folder.temp)
{
g_lamexp_folder.temp = new QString();
}
g_lamexp_folder.temp->clear();
static const char *TEMP_STR = "Temp";
const QString WRITE_TEST_DATA = lamexp_rand_str();
@ -1444,14 +1461,14 @@ const QString &lamexp_temp_folder2(void)
{
if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
{
g_lamexp_folder.temp = temp.canonicalPath();
(*g_lamexp_folder.temp) = temp.canonicalPath();
}
testFile.remove();
}
}
if(!g_lamexp_folder.temp.isEmpty())
if(!g_lamexp_folder.temp->isEmpty())
{
return g_lamexp_folder.temp;
return *g_lamexp_folder.temp;
}
}
@ -1479,22 +1496,22 @@ const QString &lamexp_temp_folder2(void)
{
if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
{
g_lamexp_folder.temp = localAppData.canonicalPath();
(*g_lamexp_folder.temp) = localAppData.canonicalPath();
}
testFile.remove();
}
}
}
}
if(!g_lamexp_folder.temp.isEmpty())
if(!g_lamexp_folder.temp->isEmpty())
{
return g_lamexp_folder.temp;
return *g_lamexp_folder.temp;
}
}
//Failed to create TEMP folder!
qFatal("Temporary directory could not be initialized!\n\nFirst attempt:\n%s\n\nSecond attempt:\n%s", temp.canonicalPath().toUtf8().constData(), localAppData.canonicalPath().toUtf8().constData());
return g_lamexp_folder.temp;
return *g_lamexp_folder.temp;
}
/*
@ -1534,13 +1551,16 @@ void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned in
{
QWriteLocker writeLock(&g_lamexp_tools.lock);
if(g_lamexp_tools.registry.contains(toolName.toLower()))
if(!g_lamexp_tools.registry) g_lamexp_tools.registry = new QMap<QString, LockedFile*>();
if(!g_lamexp_tools.versions) g_lamexp_tools.versions = new QMap<QString, unsigned int>();
if(g_lamexp_tools.registry->contains(toolName.toLower()))
{
throw "lamexp_register_tool: Tool is already registered!";
}
g_lamexp_tools.registry.insert(toolName.toLower(), file);
g_lamexp_tools.versions.insert(toolName.toLower(), version);
g_lamexp_tools.registry->insert(toolName.toLower(), file);
g_lamexp_tools.versions->insert(toolName.toLower(), version);
}
/*
@ -1549,7 +1569,7 @@ void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned in
bool lamexp_check_tool(const QString &toolName)
{
QReadLocker readLock(&g_lamexp_tools.lock);
return g_lamexp_tools.registry.contains(toolName.toLower());
return (g_lamexp_tools.registry) ? g_lamexp_tools.registry->contains(toolName.toLower()) : false;
}
/*
@ -1559,9 +1579,16 @@ const QString lamexp_lookup_tool(const QString &toolName)
{
QReadLocker readLock(&g_lamexp_tools.lock);
if(g_lamexp_tools.registry.contains(toolName.toLower()))
if(g_lamexp_tools.registry)
{
return g_lamexp_tools.registry.value(toolName.toLower())->filePath();
if(g_lamexp_tools.registry->contains(toolName.toLower()))
{
return g_lamexp_tools.registry->value(toolName.toLower())->filePath();
}
else
{
return QString();
}
}
else
{
@ -1576,9 +1603,16 @@ unsigned int lamexp_tool_version(const QString &toolName)
{
QReadLocker readLock(&g_lamexp_tools.lock);
if(g_lamexp_tools.versions.contains(toolName.toLower()))
if(g_lamexp_tools.versions)
{
return g_lamexp_tools.versions.value(toolName.toLower());
if(g_lamexp_tools.versions->contains(toolName.toLower()))
{
return g_lamexp_tools.versions->value(toolName.toLower());
}
else
{
return UINT_MAX;
}
}
else
{
@ -1629,10 +1663,15 @@ bool lamexp_translation_register(const QString &langId, const QString &qmFile, c
return false;
}
g_lamexp_translation.files.insert(langId, qmFile);
g_lamexp_translation.names.insert(langId, langName);
g_lamexp_translation.sysid.insert(langId, systemId);
g_lamexp_translation.cntry.insert(langId, country);
if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
if(!g_lamexp_translation.sysid) g_lamexp_translation.sysid = new QMap<QString, unsigned int>();
if(!g_lamexp_translation.cntry) g_lamexp_translation.cntry = new QMap<QString, unsigned int>();
g_lamexp_translation.files->insert(langId, qmFile);
g_lamexp_translation.names->insert(langId, langName);
g_lamexp_translation.sysid->insert(langId, systemId);
g_lamexp_translation.cntry->insert(langId, country);
return true;
}
@ -1642,8 +1681,8 @@ bool lamexp_translation_register(const QString &langId, const QString &qmFile, c
*/
QStringList lamexp_query_translations(void)
{
QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.files.keys();
QReadLocker readLockTranslations(&g_lamexp_translation.lock);
return (g_lamexp_translation.files) ? g_lamexp_translation.files->keys() : QStringList();
}
/*
@ -1651,8 +1690,8 @@ QStringList lamexp_query_translations(void)
*/
QString lamexp_translation_name(const QString &langId)
{
QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.names.value(langId.toLower(), QString());
QReadLocker readLockTranslations(&g_lamexp_translation.lock);
return (g_lamexp_translation.names) ? g_lamexp_translation.names->value(langId.toLower(), QString()) : QString();
}
/*
@ -1660,8 +1699,8 @@ QString lamexp_translation_name(const QString &langId)
*/
unsigned int lamexp_translation_sysid(const QString &langId)
{
QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.sysid.value(langId.toLower(), 0);
QReadLocker readLockTranslations(&g_lamexp_translation.lock);
return (g_lamexp_translation.sysid) ? g_lamexp_translation.sysid->value(langId.toLower(), 0) : 0;
}
/*
@ -1669,8 +1708,8 @@ unsigned int lamexp_translation_sysid(const QString &langId)
*/
unsigned int lamexp_translation_country(const QString &langId)
{
QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.cntry.value(langId.toLower(), 0);
QReadLocker readLockTranslations(&g_lamexp_translation.lock);
return (g_lamexp_translation.cntry) ? g_lamexp_translation.cntry->value(langId.toLower(), 0) : 0;
}
/*
@ -1687,7 +1726,9 @@ bool lamexp_install_translator(const QString &langId)
else
{
QReadLocker readLock(&g_lamexp_translation.lock);
QString qmFile = g_lamexp_translation.files.value(langId.toLower(), QString());
QString qmFile = (g_lamexp_translation.files) ? g_lamexp_translation.files->value(langId.toLower(), QString()) : QString();
readLock.unlock();
if(!qmFile.isEmpty())
{
success = lamexp_install_translator_from_file(QString(":/localization/%1").arg(qmFile));
@ -1709,19 +1750,18 @@ bool lamexp_install_translator_from_file(const QString &qmFile)
QWriteLocker writeLock(&g_lamexp_currentTranslator.lock);
bool success = false;
if(!g_lamexp_currentTranslator.instance.isValid())
if(!g_lamexp_currentTranslator.instance)
{
g_lamexp_currentTranslator.instance.setValue<QObject*>(new QTranslator());
g_lamexp_currentTranslator.instance = new QTranslator();
}
if(!qmFile.isEmpty())
{
QString qmPath = QFileInfo(qmFile).canonicalFilePath();
QTranslator *poTranslator = dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>());
QApplication::removeTranslator(poTranslator);
if(success = poTranslator->load(qmPath))
QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
if(success = g_lamexp_currentTranslator.instance->load(qmPath))
{
QApplication::installTranslator(poTranslator);
QApplication::installTranslator(g_lamexp_currentTranslator.instance);
}
else
{
@ -1730,7 +1770,7 @@ bool lamexp_install_translator_from_file(const QString &qmFile)
}
else
{
QApplication::removeTranslator(dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>()));
QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
success = true;
}
@ -1741,11 +1781,13 @@ const QStringList &lamexp_arguments(void)
{
QReadLocker readLock(&g_lamexp_argv.lock);
if(g_lamexp_argv.list.isEmpty())
if(!g_lamexp_argv.list)
{
readLock.unlock();
QWriteLocker writeLock(&g_lamexp_argv.lock);
g_lamexp_argv.list = new QStringList;
int nArgs = 0;
LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
@ -1753,7 +1795,7 @@ const QStringList &lamexp_arguments(void)
{
for(int i = 0; i < nArgs; i++)
{
g_lamexp_argv.list << WCHAR2QSTR(szArglist[i]);
(*g_lamexp_argv.list) << WCHAR2QSTR(szArglist[i]);
}
LocalFree(szArglist);
}
@ -1763,7 +1805,7 @@ const QStringList &lamexp_arguments(void)
}
}
return g_lamexp_argv.list;
return (*g_lamexp_argv.list);
}
/*
@ -1812,9 +1854,12 @@ QString lamexp_known_folder(lamexp_known_folder_t folder_id)
}
//Already in cache?
if(!g_lamexp_folder.knownFolders[folderCacheId].isEmpty())
if(g_lamexp_folder.knownFolders)
{
return g_lamexp_folder.knownFolders[folderCacheId];
if(g_lamexp_folder.knownFolders->contains(folderCacheId))
{
return g_lamexp_folder.knownFolders->value(folderCacheId, QString());
}
}
readLock.unlock();
@ -1875,7 +1920,8 @@ QString lamexp_known_folder(lamexp_known_folder_t folder_id)
//Update cache
if(!folder.isEmpty())
{
g_lamexp_folder.knownFolders[folderCacheId] = folder;
if(!g_lamexp_folder.knownFolders) g_lamexp_folder.knownFolders = new QMap<size_t, QString>();
g_lamexp_folder.knownFolders->insert(folderCacheId, folder);
}
return folder;
@ -2144,6 +2190,15 @@ extern "C"
FatalAppExit(0, L"Not a debug build. Please unload debugger and try again!");
TerminateProcess(GetCurrentProcess(), -1);
}
//Init global structs to NULL *before* constructors are called
LAMEXP_ZERO_MEMORY(g_lamexp_argv);
LAMEXP_ZERO_MEMORY(g_lamexp_tools);
LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
LAMEXP_ZERO_MEMORY(g_lamexp_translation);
LAMEXP_ZERO_MEMORY(g_lamexp_folder);
LAMEXP_ZERO_MEMORY(g_lamexp_ipc_ptr);
return WinMainCRTStartup();
}
}
@ -2156,43 +2211,47 @@ void lamexp_finalization(void)
qDebug("lamexp_finalization()");
//Free all tools
if(!g_lamexp_tools.registry.isEmpty())
if(g_lamexp_tools.registry)
{
QStringList keys = g_lamexp_tools.registry.keys();
QStringList keys = g_lamexp_tools.registry->keys();
for(int i = 0; i < keys.count(); i++)
{
LAMEXP_DELETE(g_lamexp_tools.registry[keys.at(i)]);
LAMEXP_DELETE((*g_lamexp_tools.registry)[keys.at(i)]);
}
g_lamexp_tools.registry.clear();
g_lamexp_tools.versions.clear();
LAMEXP_DELETE(g_lamexp_tools.registry);
LAMEXP_DELETE(g_lamexp_tools.versions);
}
//Delete temporary files
if(!g_lamexp_folder.temp.isEmpty())
if(g_lamexp_folder.temp)
{
for(int i = 0; i < 100; i++)
if(!g_lamexp_folder.temp->isEmpty())
{
if(lamexp_clean_folder(g_lamexp_folder.temp))
for(int i = 0; i < 100; i++)
{
break;
if(lamexp_clean_folder(*g_lamexp_folder.temp))
{
break;
}
Sleep(125);
}
Sleep(125);
}
g_lamexp_folder.temp.clear();
LAMEXP_DELETE(g_lamexp_folder.temp);
}
//Clear folder cache
LAMEXP_DELETE(g_lamexp_folder.knownFolders);
//Clear languages
if(g_lamexp_currentTranslator.instance.isValid())
if(g_lamexp_currentTranslator.instance)
{
QTranslator *poTranslator = dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>());
g_lamexp_currentTranslator.instance.clear();
QApplication::removeTranslator(poTranslator);
LAMEXP_DELETE(poTranslator);
QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
LAMEXP_DELETE(g_lamexp_currentTranslator.instance);
}
g_lamexp_translation.files.clear();
g_lamexp_translation.names.clear();
g_lamexp_translation.cntry.clear();
g_lamexp_translation.sysid.clear();
LAMEXP_DELETE(g_lamexp_translation.files);
LAMEXP_DELETE(g_lamexp_translation.names);
LAMEXP_DELETE(g_lamexp_translation.cntry);
LAMEXP_DELETE(g_lamexp_translation.sysid);
//Destroy Qt application object
QApplication *application = dynamic_cast<QApplication*>(QApplication::instance());
@ -2229,7 +2288,7 @@ void lamexp_finalization(void)
}
//Free CLI Arguments
g_lamexp_argv.list.clear();
LAMEXP_DELETE(g_lamexp_argv.list);
}
/*