/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include #include #define threadNum 4 // IF LCMS GETS THREAD SAFETY WE CAN ENABLE MORE THREADS ThumbImageUpdater thumbImageUpdater; ThumbImageUpdater::ThumbImageUpdater () : tostop(false), stopped(true), qMutex(NULL), startMutex(NULL) { //threadPool = new Glib::Thread* [threadNum]; threadPool = 0;; } //ThumbImageUpdater::~ThumbImageUpdater () //{ // delete threadPool; //} void ThumbImageUpdater::add (Thumbnail* t, const rtengine::procparams::ProcParams& params, int height, bool* priority, ThumbImageUpdateListener* l) { if (!qMutex) qMutex = new Glib::Mutex (); if (!startMutex) startMutex = new Glib::Mutex (); qMutex->lock (); // look up if an older version is in the queue std::list::iterator i; for (i=jqueue.begin(); i!=jqueue.end(); i++) if (i->thumbnail==t && i->listener==l) { i->pparams = params; i->height = height; i->priority = priority; break; } // not found, create and append new job if (i==jqueue.end ()) { Job j; j.thumbnail = t; j.pparams = params; j.height = height; j.listener = l; j.priority = priority; jqueue.push_back (j); } qMutex->unlock (); } void ThumbImageUpdater::process () { if (stopped) { #undef THREAD_PRIORITY_LOW stopped = false; // if (thread) // thread->join(); if(!threadPool) threadPool = new Glib::ThreadPool(4,0); thread = Glib::Thread::create(sigc::mem_fun(*this, &ThumbImageUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); //qMutex->lock (); // threadPool->push(sigc::mem_fun(*this, &ThumbImageUpdater::process_)); //qMutex->unlock (); } } void ThumbImageUpdater::process_ () { stopped = false; tostop = false; // GError *err; while (!tostop && !jqueue.empty ()) { qMutex->lock (); //int threads = 0; //for (; threads::iterator i; for (i=jqueue.begin (); i!=jqueue.end(); i++) if (*(i->priority)) break; if (i==jqueue.end()) i = jqueue.begin(); Job current = *i; if (current.listener) threadPool->push(sigc::bind(sigc::mem_fun(*this, &ThumbImageUpdater::processJob), current)); // if(! threadPool) // threadPool = g_thread_pool_new((void*)&ThumbImageUpdater::processJob, (gpointer)¤t, 4, FALSE, &err); // else // g_thread_pool_push(threadPool, (gpointer)current, &err); //threadPool[threads] = // Glib::Thread::create (sigc::bind(sigc::mem_fun(*this, &ThumbImageUpdater::processJob), current), 0, false, true, Glib::THREAD_PRIORITY_LOW); jqueue.erase (i); //else // threadPool[threads] = NULL; // } qMutex->unlock (); // for (int j=0; j join (); //for(int j =0; j processThumbImage (current.pparams, current.height, scale); if (img) current.listener->updateImage (img, scale, current.pparams.crop); } } void ThumbImageUpdater::stop () { if (stopped) { tostop = true; return; } gdk_threads_leave(); tostop = true; Glib::Thread::self()->yield(); if (!stopped) threadPool->shutdown(TRUE); thread->join (); gdk_threads_enter(); } void ThumbImageUpdater::removeJobs () { if (!qMutex) return; qMutex->lock (); while (!jqueue.empty()) jqueue.pop_front (); qMutex->unlock (); } void ThumbImageUpdater::removeJobs (ThumbImageUpdateListener* listener) { if (!qMutex) return; qMutex->lock (); bool ready = false; while (!ready) { ready = true; std::list::iterator i; for (i=jqueue.begin(); i!=jqueue.end(); i++) if (i->listener == listener) { jqueue.erase (i); ready = false; break; } } qMutex->unlock (); } void ThumbImageUpdater::terminate () { stop (); removeJobs (); }