usbloadergx/source/libwiigui/gui_image_async.cpp

188 lines
5.2 KiB
C++
Raw Normal View History

2009-09-27 20:19:53 +02:00
/****************************************************************************
* libwiigui
*
* Tantric 2009
*
* gui_imagea_sync.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
//#include <string.h>
#include <unistd.h>
#include "gui_image_async.h"
static mutex_t debugLock = LWP_MUTEX_NULL;
2010-09-24 02:48:03 +02:00
void debug(int Line, const char* Format, ...)
{
2010-09-24 02:48:03 +02:00
if (debugLock == 0) LWP_MutexInit(&debugLock, false);
2009-09-27 20:19:53 +02:00
2010-09-24 02:48:03 +02:00
LWP_MutexLock(debugLock);
2010-09-24 02:48:03 +02:00
FILE *fp = fopen("SD:/debug.txt", "a");
if (fp)
{
char theTime[10];
2010-09-24 02:48:03 +02:00
time_t rawtime = time(0); //this fixes code dump caused by the clock
struct tm * timeinfo = localtime(&rawtime);
strftime(theTime, sizeof(theTime), "%H:%M:%S", timeinfo);
char format[10 + strlen(Format) + strlen(theTime)];
sprintf(format, "%s %i - %s\n", theTime, Line, Format);
va_list va;
va_start( va, Format );
2010-09-24 02:48:03 +02:00
vfprintf(fp, format, va);
va_end( va );
2010-09-24 02:48:03 +02:00
fclose(fp);
}
2010-09-24 02:48:03 +02:00
LWP_MutexUnlock(debugLock);
2009-09-27 20:19:53 +02:00
}
//#define DEBUG(format, ...) debug(__LINE__, format, ##__VA_ARGS__)
#define DEBUG(format, ...)
2009-09-27 20:19:53 +02:00
2010-09-24 02:48:03 +02:00
static void *memdup(const void* src, size_t len)
{
2010-09-24 02:48:03 +02:00
void *dst = malloc(len);
if (dst) memcpy(dst, src, len);
return dst;
2009-09-27 20:19:53 +02:00
}
static std::vector<GuiImageAsync *> List;
static u32 ThreadCount = 0;
static lwp_t Thread = LWP_THREAD_NULL;
static mutex_t ListLock = LWP_MUTEX_NULL;
static mutex_t InUseLock = LWP_MUTEX_NULL;
static GuiImageAsync *InUse = NULL;
static bool Quit = false;
static bool CanSleep = true;
2010-09-24 02:48:03 +02:00
void *GuiImageAsyncThread(void *arg)
{
2010-09-24 02:48:03 +02:00
while (!Quit)
{
2010-09-24 02:48:03 +02:00
LWP_MutexLock(ListLock);
if (List.size())
{
2010-09-24 02:48:03 +02:00
LWP_MutexLock(InUseLock);
2009-09-27 20:19:53 +02:00
InUse = List.front();
2010-09-24 02:48:03 +02:00
List.erase(List.begin());
2009-09-27 20:19:53 +02:00
2010-09-24 02:48:03 +02:00
LWP_MutexUnlock(ListLock);
2009-09-27 20:19:53 +02:00
2010-09-24 02:48:03 +02:00
if (InUse)
{
2010-09-24 02:48:03 +02:00
GuiImageData *data = InUse->callback(InUse->arg);
InUse->loadet_imgdata = data;
2010-09-24 02:48:03 +02:00
if (InUse->loadet_imgdata && InUse->loadet_imgdata->GetImage())
{
// InUse->SetImage(InUse->loadet_imgdata); can<61>t use here. There can occur a deadlock
// Sets the image directly without lock. This is not fine, but it prevents a deadlock
InUse->image = InUse->loadet_imgdata->GetImage();
InUse->width = InUse->loadet_imgdata->GetWidth();
InUse->height = InUse->loadet_imgdata->GetHeight();
}
}
InUse = NULL;
2010-09-24 02:48:03 +02:00
LWP_MutexUnlock(InUseLock);
}
else
{
2010-09-24 02:48:03 +02:00
LWP_MutexUnlock(ListLock);
if (!Quit && CanSleep) LWP_SuspendThread(Thread);
}
CanSleep = true;
}
Quit = false;
return NULL;
2009-09-27 20:19:53 +02:00
}
static u32 GuiImageAsyncThreadInit()
{
2010-09-24 02:48:03 +02:00
if (0 == ThreadCount++)
{
CanSleep = false;
2010-09-24 02:48:03 +02:00
LWP_MutexInit(&ListLock, false);
LWP_MutexInit(&InUseLock, false);
LWP_CreateThread(&Thread, GuiImageAsyncThread, NULL, NULL, 16384, 75);
// while(!CanSleep)
// usleep(20);
}
return ThreadCount;
2009-09-27 20:19:53 +02:00
}
static u32 GuiImageAsyncThreadExit()
{
2010-09-24 02:48:03 +02:00
if (--ThreadCount == 0)
{
Quit = true;
2010-09-24 02:48:03 +02:00
LWP_ResumeThread(Thread);
// while(Quit)
// usleep(20);
LWP_JoinThread(Thread, NULL);
LWP_MutexDestroy(ListLock);
LWP_MutexDestroy(InUseLock);
Thread = LWP_THREAD_NULL;
ListLock = LWP_MUTEX_NULL;
InUseLock = LWP_MUTEX_NULL;
}
return ThreadCount;
2009-09-27 20:19:53 +02:00
}
2010-09-24 02:48:03 +02:00
static void GuiImageAsyncThread_AddImage(GuiImageAsync* Image)
{
2010-09-24 02:48:03 +02:00
LWP_MutexLock(ListLock);
List.push_back(Image);
LWP_MutexUnlock(ListLock);
CanSleep = false;
2010-09-24 02:48:03 +02:00
// if(LWP_ThreadIsSuspended(Thread))
LWP_ResumeThread(Thread);
2009-09-27 20:19:53 +02:00
}
2010-09-24 02:48:03 +02:00
static void GuiImageAsyncThread_RemoveImage(GuiImageAsync* Image)
{
2010-09-24 02:48:03 +02:00
LWP_MutexLock(ListLock);
for (std::vector<GuiImageAsync *>::iterator iter = List.begin(); iter != List.end(); iter++)
{
2010-09-24 02:48:03 +02:00
if (*iter == Image)
{
2010-09-24 02:48:03 +02:00
List.erase(iter);
LWP_MutexUnlock(ListLock);
return;
}
}
2010-09-24 02:48:03 +02:00
if (InUse == Image)
{
2010-09-24 02:48:03 +02:00
LWP_MutexLock(InUseLock);
LWP_MutexUnlock(InUseLock);
}
2010-09-24 02:48:03 +02:00
LWP_MutexUnlock(ListLock);
2009-09-27 20:19:53 +02:00
}
/**
* Constructor for the GuiImageAsync class.
*/
2010-09-24 02:48:03 +02:00
GuiImageData *StdImageLoaderCallback(void *arg)
{
return new GuiImageData((char*) arg);
2009-09-27 20:19:53 +02:00
}
2010-09-24 02:48:03 +02:00
GuiImageAsync::GuiImageAsync(const char *Filename, GuiImageData * PreloadImg) :
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename))
{
GuiImageAsyncThreadInit();
2010-09-24 02:48:03 +02:00
GuiImageAsyncThread_AddImage(this);
2009-09-27 20:19:53 +02:00
}
2010-09-24 02:48:03 +02:00
GuiImageAsync::GuiImageAsync(ImageLoaderCallback Callback, void *Arg, int ArgLen, GuiImageData * PreloadImg) :
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(Callback), arg(memdup(Arg, ArgLen))
{
DEBUG( "Constructor %p", this );
GuiImageAsyncThreadInit();
2010-09-24 02:48:03 +02:00
GuiImageAsyncThread_AddImage(this);
2009-09-27 20:19:53 +02:00
}
GuiImageAsync::~GuiImageAsync()
{
2010-09-24 02:48:03 +02:00
GuiImageAsyncThread_RemoveImage(this);
GuiImageAsyncThreadExit();
DEBUG( "Deconstructor %p (loadet_imgdata=%p)", this, loadet_imgdata );
2010-09-24 02:48:03 +02:00
if (loadet_imgdata) delete loadet_imgdata;
if (arg) free(arg);
2009-09-27 20:19:53 +02:00
}