Can you determine the "stage" when corruption occures.
(eg. by setting CS arround gflLoadBitmap and/or gflSaveBitmap).
I think that would give Pierre a better clue.
(I know about the problems of debugging MT-code on a single processor box :p)
Something like:
Code: Select all
#include <libgfl.h>
#include <fstream>
#include <iostream>
#include <windows.h>
#include <string>
#include <time.h>
class CondCS
{
CRITICAL_SECTION s;
public:
CondCS() { InitializeCriticalSection(&s); }
~CondCS() { DeleteCriticalSection(&s); }
void lock(const BOOL x, const char *i, std::string name)
{
if (x)
{
EnterCriticalSection(&s);
std::cerr << name << " - lock: " << i << std::endl;
}
}
void unlock(const BOOL x, const char *i, std::string name)
{
if (x)
{
std::cerr << name << " - unlock: " << i << std::endl;
LeaveCriticalSection(&s);
}
}
};
CondCS sec;
#define TOPROT 2 // [0-3[
#define PROT(x) (TOPROT & x)
class Thread;
DWORD ThreadFunc(Thread *thread);
static unsigned hrand(unsigned high)
{
return (unsigned)((double)(rand() % RAND_MAX) / (double)RAND_MAX * (double)high);
}
class Thread
{
public:
unsigned id;
unsigned short prio;
HANDLE hThread;
DWORD dwThread;
GFL_UINT8 *pData;
GFL_UINT32 sSize;
std::string name;
Thread(unsigned i, GFL_UINT8 *d, GFL_UINT32 s) : id(i), hThread(NULL), dwThread(0), pData(d), sSize(s)
{
hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
(LPVOID)this,
CREATE_SUSPENDED,
&dwThread
);
prio = hrand(3);
SetThreadPriority(
hThread,
(prio == 2)
? THREAD_PRIORITY_HIGHEST
: (
!prio
? THREAD_PRIORITY_IDLE
: THREAD_PRIORITY_NORMAL
)
);
if (!hThread)
std::cerr << "Failed to create!" << std::endl;
char n[1024];
sprintf(n, "Thread %.2d (%p) p%d", id, hThread, prio);
name.assign(n);
}
~Thread() { if (hThread) CloseHandle(hThread); };
void Execute() { if (hThread) ResumeThread(hThread); }
};
DWORD ThreadFunc(Thread *thread)
{
DWORD err;
GFL_LOAD_PARAMS load_option;
gflGetDefaultLoadParams(&load_option);
GFL_FILE_INFORMATION GflFI;
GFL_BITMAP *GflBitmap;
sec.lock(PROT(1), "load", thread->name);
err = MAKELONG(gflLoadBitmapFromMemory(
thread->pData,
thread->sSize,
&GflBitmap,
&load_option,
&GflFI
), 0);
sec.unlock(PROT(1), "load", thread->name);
std::string filename(thread->name);
filename.append(".jpg");
GFL_SAVE_PARAMS save_option;
gflGetDefaultSaveParams(&save_option);
save_option.FormatIndex = gflGetFormatIndexByName("jpeg");
sec.lock(PROT(2), "save", thread->name);
err |= MAKELONG(0, gflSaveBitmap(
(char*)filename.c_str(),
GflBitmap,
&save_option
));
sec.unlock(PROT(2), "save", thread->name);
return err;
}
#define THREADS 10
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cout << "/me takes 1 arg" << std::endl;
return 1;
}
gflLibraryInit();
srand((unsigned)time(NULL));
std::ifstream ficDoc(
argv[1],
std::ios::in | std::ios::binary | std::ios::ate
);
GFL_UINT32 sSize = ficDoc.tellg();
GFL_UINT8 *pData = new GFL_UINT8[sSize];
ficDoc.seekg (0, std::ios::beg);
ficDoc.read (reinterpret_cast<char*>(pData), sSize);
ficDoc.close();
HANDLE *pHandles = new HANDLE[THREADS];
Thread **pThreads = new Thread*[THREADS];
std::cout << "Protected stages: " << TOPROT << std::endl;
for (unsigned i = 0; i < THREADS; ++i)
{
pThreads[i] = new Thread(i, pData, sSize);
pHandles[i] = pThreads[i]->hThread;
}
for (unsigned i = 0; i < THREADS; ++i)
{
pThreads[i]->Execute();
}
WaitForMultipleObjects(
THREADS,
pHandles,
TRUE,
INFINITE
);
for (unsigned i = 0; i < THREADS; ++i)
{
DWORD ec;
if (GetExitCodeThread(pHandles[i], &ec))
{
std::cout << pThreads[i]->name << ") - load: " << LOWORD(ec) << " - save: " << HIWORD(ec) << std::endl;
}
else
{
std::cout << pThreads[i]->name << "): ABANDONED" << std::endl;
}
delete pThreads[i];
}
delete [] pData;
delete [] pHandles;
delete [] pThreads;
return 0;
}
But Im only single-core, so output is fine for all four TOPROTs :p