Threading cleanups

This commit is contained in:
Oliver Duis 2011-06-21 21:59:51 +02:00
parent 0583d2bc39
commit c1a8e6bbbd
13 changed files with 260 additions and 276 deletions

View File

@ -91,7 +91,8 @@ void Crop::update (int todo) {
bool needstransform = parent->ipf.needsTransform(); bool needstransform = parent->ipf.needsTransform();
if (todo & M_INIT) { if (todo & M_INIT) {
parent->minit.lock (); Glib::Mutex::Lock lock(parent->minit); // Also used in inproccoord
int tr = TR_NONE; int tr = TR_NONE;
if (params.coarse.rotate==90) tr |= TR_R90; if (params.coarse.rotate==90) tr |= TR_R90;
if (params.coarse.rotate==180) tr |= TR_R180; if (params.coarse.rotate==180) tr |= TR_R180;
@ -103,8 +104,6 @@ void Crop::update (int todo) {
setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true); setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true);
PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw ); parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw );
parent->minit.unlock ();
} }
// transform // transform
@ -134,7 +133,7 @@ void Crop::update (int todo) {
if (colortest && cropw>115 && croph>115) if (colortest && cropw>115 && croph>115)
for(int j=1;j<5;j++){ for(int j=1;j<5;j++){
xref+=j*30;yref+=j*30; xref+=j*30;yref+=j*30;
printf("before rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f gamma=%f \n",xref,yref,skip, \ if (settings->verbose) printf("before rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f gamma=%f \n",xref,yref,skip, \
baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\ baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\
baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \ baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \
baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256, baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256,
@ -148,14 +147,16 @@ void Crop::update (int todo) {
if (colortest && cropw>115 && croph>115) if (colortest && cropw>115 && croph>115)
for(int j=1;j<5;j++){ for(int j=1;j<5;j++){
xref+=j*30;yref+=j*30; xref+=j*30;yref+=j*30;
printf("after rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f \n",xref,yref,skip, \ if (settings->verbose) {
baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\ printf("after rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f \n",xref,yref,skip, \
baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \ baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\
baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256); baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \
printf("after rgbProc Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256);
laboCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, \ printf("after rgbProc Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip,
laboCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, \ laboCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, \
laboCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); laboCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, \
laboCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327);
}
} }
// apply luminance operations // apply luminance operations

View File

@ -122,7 +122,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
} }
if (todo & M_INIT) { if (todo & M_INIT) {
Glib::Mutex::Lock lock(minit); Glib::Mutex::Lock lock(minit); // Also used in crop window
if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n"); if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n");
currWB = ColorTemp (params.wb.temperature, params.wb.green); currWB = ColorTemp (params.wb.temperature, params.wb.green);
@ -150,7 +150,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
setScale (scale); setScale (scale);
imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw); imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw);
ipf.firstAnalysis (orig_prev, &params, vhist16, imgsrc->getGamma()); ipf.firstAnalysis (orig_prev, &params, vhist16, imgsrc->getGamma());
} }
readyphase++; readyphase++;
@ -313,7 +312,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
hListener->histogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histRedRaw, histGreenRaw, histBlueRaw); hListener->histogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histRedRaw, histGreenRaw, histBlueRaw);
} }
progress ("Ready",100*readyphase/numofphases);
mProcessing.unlock (); mProcessing.unlock ();
} }
@ -479,6 +477,7 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double&
ColorTemp ret = imgsrc->getSpotWB (red, green, blue, tr); ColorTemp ret = imgsrc->getSpotWB (red, green, blue, tr);
currWB = ColorTemp (params.wb.temperature, params.wb.green); currWB = ColorTemp (params.wb.temperature, params.wb.green);
mProcessing.unlock (); mProcessing.unlock ();
if (ret.getTemp() > 0) { if (ret.getTemp() > 0) {
temp = ret.getTemp (); temp = ret.getTemp ();
tgreen = ret.getGreen (); tgreen = ret.getGreen ();

View File

@ -208,8 +208,7 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s
void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw ) void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw )
{ {
Glib::Mutex::Lock lock(getImageMutex);
isrcMutex.lock ();
tran = defTransform (tran); tran = defTransform (tran);
@ -421,8 +420,6 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre
// Applying postmul // Applying postmul
colorSpaceConversion (image, cmp, embProfile, camProfile, xyz_cam, defGain); colorSpaceConversion (image, cmp, embProfile, camProfile, xyz_cam, defGain);
isrcMutex.unlock ();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View File

@ -55,7 +55,7 @@ template<class T> void freeArray2 (T** a, int H) {
class RawImageSource : public ImageSource { class RawImageSource : public ImageSource {
protected: protected:
Glib::Mutex isrcMutex; Glib::Mutex getImageMutex; // locks getImage
int W, H; int W, H;
ColorTemp wb; ColorTemp wb;

View File

@ -122,68 +122,72 @@ bool BatchQueue::saveBatchQueue( )
return true; return true;
} }
bool BatchQueue::loadBatchQueue( ) void BatchQueue::loadBatchQueue( )
{ {
// TODO: Check for Linux {
#ifdef WIN32 // TODO: Check for Linux
Glib::Mutex::Lock lock(entryMutex); #ifdef WIN32
#endif Glib::Mutex::Lock lock(entryMutex);
#endif
Glib::ustring savedQueueFile; Glib::ustring savedQueueFile;
savedQueueFile = options.rtdir+"/batch/queue"; savedQueueFile = options.rtdir+"/batch/queue";
FILE *f = safe_g_fopen (savedQueueFile, "rt"); FILE *f = safe_g_fopen (savedQueueFile, "rt");
if (f==NULL) if (f!=NULL) {
return false; char *buffer = new char[1024];
char *buffer = new char[1024]; unsigned numLoaded=0;
unsigned numLoaded=0; while (fgets (buffer, 1024, f)){
while (fgets (buffer, 1024, f)){ char *p = strchr(buffer,';' );
char *p = strchr(buffer,';' ); if( p ){
if( p ){ char *le = buffer + strlen(buffer);
char *le = buffer + strlen(buffer); while( --le > buffer && (*le == '\n' || *le == '\r') );
while( --le > buffer && (*le == '\n' || *le == '\r') ); Glib::ustring source(buffer, p-buffer );
Glib::ustring source(buffer, p-buffer ); Glib::ustring paramsFile(p+1, (le +1)- (p+1) );
Glib::ustring paramsFile(p+1, (le +1)- (p+1) );
rtengine::procparams::ProcParams pparams; rtengine::procparams::ProcParams pparams;
if( pparams.load( paramsFile ) ) if( pparams.load( paramsFile ) )
continue; continue;
::Thumbnail *thumb = cacheMgr->getEntry( source ); ::Thumbnail *thumb = cacheMgr->getEntry( source );
if( thumb ){ if( thumb ){
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create(source, thumb->getType() == FT_Raw, pparams); rtengine::ProcessingJob* job = rtengine::ProcessingJob::create(source, thumb->getType() == FT_Raw, pparams);
int prevh = options.maxThumbnailHeight; int prevh = options.maxThumbnailHeight;
int prevw = prevh; int prevw = prevh;
guint8* prev = NULL; guint8* prev = NULL;
double tmpscale; double tmpscale;
rtengine::IImage8* img = thumb->processThumbImage(pparams, options.maxThumbnailHeight, tmpscale); rtengine::IImage8* img = thumb->processThumbImage(pparams, options.maxThumbnailHeight, tmpscale);
if (img) { if (img) {
prevw = img->getWidth(); prevw = img->getWidth();
prevh = img->getHeight(); prevh = img->getHeight();
prev = new guint8[prevw * prevh * 3]; prev = new guint8[prevw * prevh * 3];
memcpy(prev, img->getData(), prevw * prevh * 3); memcpy(prev, img->getData(), prevw * prevh * 3);
img->free(); img->free();
} }
BatchQueueEntry *entry = new BatchQueueEntry(job, pparams,source, prev, prevw, prevh, thumb); BatchQueueEntry *entry = new BatchQueueEntry(job, pparams,source, prev, prevw, prevh, thumb);
entry->setParent(this); entry->setParent(this);
entry->resize(options.thumbSize); entry->resize(options.thumbSize);
entry->savedParamsFile = paramsFile; entry->savedParamsFile = paramsFile;
entry->selected = false; entry->selected = false;
fd.push_back(entry); fd.push_back(entry);
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet(entry); BatchQueueButtonSet* bqbs = new BatchQueueButtonSet(entry);
bqbs->setButtonListener(this); bqbs->setButtonListener(this);
entry->addButtonSet(bqbs); entry->addButtonSet(bqbs);
numLoaded++; numLoaded++;
} }
} }
}
delete [] buffer;
fclose(f);
}
} }
delete [] buffer;
fclose(f);
arrangeFiles (); arrangeFiles ();
queue_draw (); queue_draw ();
return numLoaded > 0;
notifyListener();
} }
Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename ) Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename )
@ -214,95 +218,99 @@ int deleteitem (void* data)
void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) { void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) {
{ {
// TODO: Check for Linux // TODO: Check for Linux
#ifdef WIN32 #ifdef WIN32
Glib::Mutex::Lock lock(entryMutex); Glib::Mutex::Lock lock(entryMutex);
#endif #endif
for (int i=0; i<items->size(); i++) { for (int i=0; i<items->size(); i++) {
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
if (entry->processing) if (entry->processing)
continue; continue;
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry); std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
if (pos!=fd.end()) { if (pos!=fd.end()) {
fd.erase (pos); fd.erase (pos);
rtengine::ProcessingJob::destroy (entry->job); rtengine::ProcessingJob::destroy (entry->job);
if (entry->thumbnail) if (entry->thumbnail)
entry->thumbnail->imageRemovedFromQueue (); entry->thumbnail->imageRemovedFromQueue ();
g_idle_add (deleteitem, entry); g_idle_add (deleteitem, entry);
}
} }
} for (int i=0; i<fd.size(); i++)
for (int i=0; i<fd.size(); i++) fd[i]->selected = false;
fd[i]->selected = false; lastClicked = NULL;
lastClicked = NULL; selected.clear ();
selected.clear ();
saveBatchQueue( );
}
saveBatchQueue( );
}
redraw (); redraw ();
notifyListener (); notifyListener ();
} }
void BatchQueue::headItems (std::vector<ThumbBrowserEntryBase*>* items) { void BatchQueue::headItems (std::vector<ThumbBrowserEntryBase*>* items) {
{ {
// TODO: Check for Linux // TODO: Check for Linux
#ifdef WIN32 #ifdef WIN32
Glib::Mutex::Lock lock(entryMutex); Glib::Mutex::Lock lock(entryMutex);
#endif #endif
for (int i=items->size()-1; i>=0; i--) { for (int i=items->size()-1; i>=0; i--) {
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
if (entry->processing) if (entry->processing)
continue; continue;
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry); std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
if (pos!=fd.end() && pos!=fd.begin()) { if (pos!=fd.end() && pos!=fd.begin()) {
fd.erase (pos); fd.erase (pos);
// find the first item that is not under processing // find the first item that is not under processing
for (pos=fd.begin(); pos!=fd.end(); pos++) for (pos=fd.begin(); pos!=fd.end(); pos++)
if (!(*pos)->processing) { if (!(*pos)->processing) {
fd.insert (pos, entry); fd.insert (pos, entry);
break; break;
} }
}
} }
saveBatchQueue( );
} }
saveBatchQueue( );
}
redraw (); redraw ();
} }
void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) { void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) {
{ {
// TODO: Check for Linux // TODO: Check for Linux
#ifdef WIN32 #ifdef WIN32
Glib::Mutex::Lock lock(entryMutex); Glib::Mutex::Lock lock(entryMutex);
#endif #endif
for (int i=0; i<items->size(); i++) { for (int i=0; i<items->size(); i++) {
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
if (entry->processing) if (entry->processing)
continue; continue;
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry); std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
if (pos!=fd.end()) { if (pos!=fd.end()) {
fd.erase (pos); fd.erase (pos);
fd.push_back (entry); fd.push_back (entry);
}
} }
saveBatchQueue( );
} }
saveBatchQueue( );
}
redraw (); redraw ();
} }
void BatchQueue::selectAll () { void BatchQueue::selectAll () {
// TODO: Check for Linux {// TODO: Check for Linux
#ifdef WIN32 #ifdef WIN32
Glib::Mutex::Lock lock(entryMutex); Glib::Mutex::Lock lock(entryMutex);
#endif #endif
lastClicked = NULL; lastClicked = NULL;
selected.clear (); selected.clear ();
for (int i=0; i<fd.size(); i++) { for (int i=0; i<fd.size(); i++) {
if (fd[i]->processing) if (fd[i]->processing)
continue; continue;
fd[i]->selected = true; fd[i]->selected = true;
selected.push_back (fd[i]); selected.push_back (fd[i]);
}
} }
queue_draw (); queue_draw ();
} }
@ -387,46 +395,46 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
delete processing; delete processing;
processing = NULL; processing = NULL;
{ {
// TODO: Check for Linux // TODO: Check for Linux
#ifdef WIN32 #ifdef WIN32
Glib::Mutex::Lock lock(entryMutex); Glib::Mutex::Lock lock(entryMutex);
#endif #endif
fd.erase (fd.begin()); fd.erase (fd.begin());
// return next job // return next job
if (fd.size()==0) { if (fd.size()==0) {
if (listener) if (listener)
listener->queueEmpty (); listener->queueEmpty ();
} }
else if (listener && listener->canStartNext ()) { else if (listener && listener->canStartNext ()) {
BatchQueueEntry* next = (BatchQueueEntry*)fd[0]; BatchQueueEntry* next = (BatchQueueEntry*)fd[0];
// tag it as selected // tag it as selected
next->processing = true; next->processing = true;
processing = next; processing = next;
// remove from selection // remove from selection
if (processing->selected) { if (processing->selected) {
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (selected.begin(), selected.end(), processing); std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (selected.begin(), selected.end(), processing);
if (pos!=selected.end()) if (pos!=selected.end())
selected.erase (pos); selected.erase (pos);
processing->selected = false; processing->selected = false;
}
// remove button set
next->removeButtonSet ();
}
if( saveBatchQueue( ) ){
safe_g_remove( processedParams );
// Delete all files in directory \batch when finished, just to be sure to remove zombies
if( fd.size()==0 ){
std::vector<Glib::ustring> names;
Glib::ustring batchdir = options.rtdir+"/batch/";
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (batchdir);
safe_build_file_list (dir, names, batchdir);
for(std::vector<Glib::ustring>::iterator iter=names.begin(); iter != names.end();iter++ )
safe_g_remove( *iter );
}
} }
// remove button set
next->removeButtonSet ();
} }
if( saveBatchQueue( ) ){
safe_g_remove( processedParams );
// Delete all files in directory \batch when finished, just to be sure to remove zombies
if( fd.size()==0 ){
std::vector<Glib::ustring> names;
Glib::ustring batchdir = options.rtdir+"/batch/";
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (batchdir);
safe_build_file_list (dir, names, batchdir);
for(std::vector<Glib::ustring>::iterator iter=names.begin(); iter != names.end();iter++ )
safe_g_remove( *iter );
}
}
}
redraw (); redraw ();
notifyListener (); notifyListener ();

View File

@ -56,6 +56,7 @@ class BatchQueue : public ThumbBrowserBase,
Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format);
Glib::ustring getTempFilenameForParams( const Glib::ustring filename ); Glib::ustring getTempFilenameForParams( const Glib::ustring filename );
bool saveBatchQueue( ); bool saveBatchQueue( );
void notifyListener ();
public: public:
BatchQueue (); BatchQueue ();
@ -78,8 +79,8 @@ class BatchQueue : public ThumbBrowserBase,
void redrawNeeded (LWButton* button); void redrawNeeded (LWButton* button);
void setBatchQueueListener (BatchQueueListener* l) { listener = l; } void setBatchQueueListener (BatchQueueListener* l) { listener = l; }
void notifyListener ();
bool loadBatchQueue (); void loadBatchQueue ();
static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName); static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName);
}; };

View File

@ -56,8 +56,7 @@ void BatchQueueEntry::refreshThumbnailImage () {
if (!opreview) if (!opreview)
return; return;
batchQueueEntryUpdater.add (opreview, origpw, origph, preh, this); batchQueueEntryUpdater.process (opreview, origpw, origph, preh, this);
batchQueueEntryUpdater.process ();
} }
void BatchQueueEntry::calcThumbnailSize () { void BatchQueueEntry::calcThumbnailSize () {

View File

@ -133,7 +133,6 @@ BatchQueuePanel::BatchQueuePanel () {
show_all (); show_all ();
batchQueue->loadBatchQueue (); batchQueue->loadBatchQueue ();
batchQueue->notifyListener ();
} }

View File

@ -26,8 +26,7 @@ BatchQueueEntryUpdater::BatchQueueEntryUpdater ()
: tostop(false), stopped(true), qMutex(NULL) { : tostop(false), stopped(true), qMutex(NULL) {
} }
void BatchQueueEntryUpdater::add (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener) { void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener) {
if (!qMutex) if (!qMutex)
qMutex = new Glib::Mutex (); qMutex = new Glib::Mutex ();
@ -42,6 +41,7 @@ void BatchQueueEntryUpdater::add (guint8* oimg, int ow, int oh, int newh, BQEntr
i->listener = listener; i->listener = listener;
break; break;
} }
// not found, create and append new job // not found, create and append new job
if (i==jqueue.end ()) { if (i==jqueue.end ()) {
Job j; Job j;
@ -53,33 +53,30 @@ void BatchQueueEntryUpdater::add (guint8* oimg, int ow, int oh, int newh, BQEntr
jqueue.push_back (j); jqueue.push_back (j);
} }
qMutex->unlock (); qMutex->unlock ();
}
void BatchQueueEntryUpdater::process () { // Start thread if not running yet
if (stopped) {
stopped = false;
tostop = false;
if (stopped){
#undef THREAD_PRIORITY_LOW #undef THREAD_PRIORITY_LOW
thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::processThread), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW);
} }
} }
void BatchQueueEntryUpdater::process_ () { void BatchQueueEntryUpdater::processThread () {
// TODO: process visible jobs first
stopped = false; bool isEmpty=false;
tostop = false;
// TODO: process visible jobs first
bool isEmpty=false;
while (!tostop && !isEmpty) { while (!tostop && !isEmpty) {
qMutex->lock (); qMutex->lock ();
isEmpty=jqueue.empty (); // do NOT put into while() since it must be within mutex section isEmpty=jqueue.empty (); // do NOT put into while() since it must be within mutex section
Job current; Job current;
if (!isEmpty) { if (!isEmpty) {
current = jqueue.front (); current = jqueue.front ();
jqueue.pop_front (); jqueue.pop_front ();
} }
qMutex->unlock (); qMutex->unlock ();
if (!isEmpty && current.listener) { if (!isEmpty && current.listener) {
@ -89,38 +86,13 @@ void BatchQueueEntryUpdater::process_ () {
current.listener->updateImage (img, neww, current.newh); current.listener->updateImage (img, neww, current.newh);
} }
} }
stopped = true; stopped = true;
} }
void BatchQueueEntryUpdater::stop () {
if (stopped) {
tostop = true;
return; }
gdk_threads_leave();
tostop = true;
Glib::Thread::self()->yield();
if (!stopped)
thread->join ();
gdk_threads_enter();
}
void BatchQueueEntryUpdater::removeJobs () {
if (!qMutex)
return;
qMutex->lock ();
while (!jqueue.empty())
jqueue.pop_front ();
qMutex->unlock ();
}
void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) { void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) {
if (!qMutex) return;
if (!qMutex)
return;
qMutex->lock (); qMutex->lock ();
bool ready = false; bool ready = false;
@ -138,9 +110,22 @@ void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) {
} }
void BatchQueueEntryUpdater::terminate () { void BatchQueueEntryUpdater::terminate () {
// never started or currently not running?
if (!qMutex || stopped) return;
stop (); if (!stopped) {
removeJobs (); // Yield to currenly running thread and wait till it's finished
gdk_threads_leave();
tostop = true;
Glib::Thread::self()->yield();
if (!stopped) thread->join ();
gdk_threads_enter();
}
// Remove remaining jobs
qMutex->lock ();
while (!jqueue.empty()) jqueue.pop_front ();
qMutex->unlock ();
} }

View File

@ -47,14 +47,11 @@ class BatchQueueEntryUpdater {
public: public:
BatchQueueEntryUpdater (); BatchQueueEntryUpdater ();
void add (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener); void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener);
void process ();
void stop ();
void removeJobs ();
void removeJobs (BQEntryUpdateListener* listener); void removeJobs (BQEntryUpdateListener* listener);
void terminate (); void terminate ();
void process_ (); void processThread ();
}; };
extern BatchQueueEntryUpdater batchQueueEntryUpdater; extern BatchQueueEntryUpdater batchQueueEntryUpdater;

View File

@ -48,7 +48,7 @@ struct iaimgpar {
CropParams cp; CropParams cp;
}; };
int iasetimage (void* data) { int setImageThread (void* data) {
gdk_threads_enter (); gdk_threads_enter ();
@ -66,13 +66,14 @@ int iasetimage (void* data) {
} }
if (pih->phandler->image) { if (pih->phandler->image) {
IImage8* temp = pih->phandler->image; IImage8* oldImg = pih->phandler->image;
temp->getMutex().lock (); oldImg->getMutex().lock ();
pih->phandler->image = iap->image; pih->phandler->image = iap->image;
temp->getMutex().unlock (); oldImg->getMutex().unlock ();
} }
else else
pih->phandler->image = iap->image; pih->phandler->image = iap->image;
pih->phandler->cropParams = iap->cp; pih->phandler->cropParams = iap->cp;
pih->phandler->previewScale = iap->scale; pih->phandler->previewScale = iap->scale;
pih->pending--; pih->pending--;
@ -93,10 +94,11 @@ void PreviewHandler::setImage (rtengine::IImage8* i, double scale, rtengine::pro
iap->scale = scale; iap->scale = scale;
iap->cp = cp; iap->cp = cp;
g_idle_add (iasetimage, iap); g_idle_add (setImageThread, iap);
} }
int iadelimage (void* data) {
int delImageThread (void* data) {
gdk_threads_enter (); gdk_threads_enter ();
@ -114,10 +116,10 @@ int iadelimage (void* data) {
} }
if (pih->phandler->image) { if (pih->phandler->image) {
IImage8* temp = pih->phandler->image; IImage8* oldImg = pih->phandler->image;
temp->getMutex().lock (); oldImg->getMutex().lock ();
pih->phandler->image = NULL; pih->phandler->image = NULL;
temp->getMutex().unlock (); oldImg->getMutex().unlock ();
} }
iap->image->free (); iap->image->free ();
pih->phandler->previewImgMutex.lock (); pih->phandler->previewImgMutex.lock ();
@ -140,10 +142,10 @@ void PreviewHandler::delImage (IImage8* i) {
iap->image = i; iap->image = i;
iap->pih = pih; iap->pih = pih;
g_idle_add (iadelimage, iap); g_idle_add (delImageThread, iap);
} }
int imready (void* data) { int imageReadyThread (void* data) {
gdk_threads_enter (); gdk_threads_enter ();
@ -179,7 +181,7 @@ void PreviewHandler::imageReady (CropParams cp) {
iaimgpar* iap = new iaimgpar; iaimgpar* iap = new iaimgpar;
iap->pih = pih; iap->pih = pih;
iap->cp = cp; iap->cp = cp;
g_idle_add (imready, iap); g_idle_add (imageReadyThread, iap);
} }
Glib::RefPtr<Gdk::Pixbuf> PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) { Glib::RefPtr<Gdk::Pixbuf> PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) {

View File

@ -38,9 +38,9 @@ struct PreviewHandlerIdleHelper {
class PreviewHandler : public rtengine::PreviewImageListener { class PreviewHandler : public rtengine::PreviewImageListener {
friend int iasetimage (void* data); friend int setImageThread (void* data);
friend int iadelimage (void* data); friend int delImageThread (void* data);
friend int imready (void* data); friend int imageReadyThread (void* data);
protected: protected:
rtengine::IImage8* image; rtengine::IImage8* image;

View File

@ -75,15 +75,11 @@ public:
} }
Glib::ThreadPool* threadPool_; Glib::ThreadPool* threadPool_;
Glib::Mutex mutex_; Glib::Mutex mutex_;
JobSet jobs_; JobSet jobs_;
gint nConcurrentThreads; gint nConcurrentThreads;
void void processNextJob()
processNextJob(void)
{ {
Job j; Job j;
{ {
@ -102,10 +98,12 @@ public:
DEBUG("processing %s",j.dir_entry_.c_str()); DEBUG("processing %s",j.dir_entry_.c_str());
DEBUG("%d job(s) remaining",jobs_.size()); DEBUG("%d job(s) remaining",jobs_.size());
} }
g_atomic_int_inc (&nConcurrentThreads);
g_atomic_int_inc (&nConcurrentThreads); // to detect when last thread in pool has run out
// unlock and do processing; will relock on block exit, then call listener // unlock and do processing; will relock on block exit, then call listener
// if something got // if something got
try{ try {
Thumbnail* tmb = 0; Thumbnail* tmb = 0;
{ {
if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS))
@ -114,22 +112,17 @@ public:
} }
} }
// we got something so notify listener // we got something, so notify listener
if ( tmb ) if ( tmb )
{ {
j.listener_->previewReady(j.dir_id_,new FileBrowserEntry(tmb,j.dir_entry_)); j.listener_->previewReady(j.dir_id_,new FileBrowserEntry(tmb,j.dir_entry_));
} }
}catch(Glib::Error){ } catch (Glib::Error){} catch(...){}
}catch(...){} bool last = g_atomic_int_dec_and_test (&nConcurrentThreads);
bool last = g_atomic_int_dec_and_test(& nConcurrentThreads);
// signal at end // signal at end
if ( jobs_.empty() ) if (last && jobs_.empty()) j.listener_->previewsFinished(j.dir_id_);
{
if(last)
j.listener_->previewsFinished(j.dir_id_);
}
} }
}; };
@ -138,29 +131,33 @@ PreviewLoader::PreviewLoader():
{ {
} }
PreviewLoader* PreviewLoader* PreviewLoader::getInstance(void)
PreviewLoader::getInstance(void)
{ {
// this will not be deleted... // this will not be deleted...
static PreviewLoader* instance_ = 0; static PreviewLoader* instance_ = NULL;
if ( instance_ == 0 ) if ( instance_ == NULL )
{ {
instance_ = new PreviewLoader(); static Glib::Mutex smutex_;
Glib::Mutex::Lock lock(smutex_);
if ( instance_ == NULL ) instance_ = new PreviewLoader();
} }
return instance_; return instance_;
} }
void void PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* l)
PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* l)
{ {
// somebody listening? // somebody listening?
if ( l != 0 ) if ( l != 0 )
{ {
Glib::Mutex::Lock lock(impl_->mutex_); {
Glib::Mutex::Lock lock(impl_->mutex_);
// create a new job and append to queue // create a new job and append to queue
DEBUG("saving job %s",dir_entry.c_str()); DEBUG("saving job %s",dir_entry.c_str());
impl_->jobs_.insert(Impl::Job(dir_id,dir_entry,l)); impl_->jobs_.insert(Impl::Job(dir_id,dir_entry,l));
}
// queue a run request // queue a run request
DEBUG("adding run request %s",dir_entry.c_str()); DEBUG("adding run request %s",dir_entry.c_str());
@ -168,8 +165,7 @@ PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderList
} }
} }
void void PreviewLoader::removeAllJobs(void)
PreviewLoader::removeAllJobs(void)
{ {
DEBUG("stop %d",impl_->nConcurrentThreads); DEBUG("stop %d",impl_->nConcurrentThreads);
Glib::Mutex::Lock lock(impl_->mutex_); Glib::Mutex::Lock lock(impl_->mutex_);