Solving issue 1684: "thumbnail.cc uses Glib::Mutex recusively" ; this changeset introduce a new MyMutex and MyMutex::MyLock class that has to be used instead of Glib ones

This commit is contained in:
Hombre
2013-08-11 23:33:10 +02:00
parent 987e4dcd89
commit f512d74323
55 changed files with 1037 additions and 751 deletions

View File

@@ -19,6 +19,7 @@
#define _BATCHQUEUE_
#include <gtkmm.h>
#include "threadutils.h"
#include "batchqueueentry.h"
#include "../rtengine/rtengine.h"
#include "options.h"

View File

@@ -21,6 +21,7 @@
#include <cstring>
#include "guiutils.h"
#include "threadutils.h"
#include "../rtengine/safegtk.h"
#include "multilangmgr.h"

View File

@@ -33,7 +33,7 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ
}
if (!qMutex)
qMutex = new Glib::Mutex ();
qMutex = new MyMutex ();
qMutex->lock ();
// look up if an older version is in the queue

View File

@@ -21,6 +21,7 @@
#include <glibmm.h>
#include "../rtengine/rtengine.h"
#include "threadutils.h"
#include "thumbnail.h"
class BQEntryUpdateListener {
@@ -45,7 +46,7 @@ class BatchQueueEntryUpdater {
bool stopped;
std::list<Job> jqueue;
Glib::Thread* thread;
Glib::Mutex* qMutex;
MyMutex* qMutex;
public:
BatchQueueEntryUpdater ();

View File

@@ -36,73 +36,73 @@ int CacheImageData::load (const Glib::ustring& fname) {
rtengine::SafeKeyFile keyFile;
try {
bool loaded = keyFile.load_from_file (fname);
if (!loaded) {
#ifndef NDEBUG
printf("Failed to load_from_file(%s)\n", fname.c_str());
#endif
return 1;
}
if (keyFile.load_from_file (fname)) {
if (keyFile.has_group ("General")) {
if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5");
if (keyFile.has_key ("General", "Version")) version = keyFile.get_string ("General", "Version");
if (keyFile.has_key ("General", "Supported")) supported = keyFile.get_boolean ("General", "Supported");
if (keyFile.has_key ("General", "Format")) format = (ThFileType)keyFile.get_integer ("General", "Format");
if (keyFile.has_key ("General", "Rank")) rankOld = keyFile.get_integer ("General", "Rank");
if (keyFile.has_key ("General", "InTrash")) inTrashOld = keyFile.get_boolean ("General", "InTrash");
if (keyFile.has_key ("General", "RecentlySaved")) recentlySaved = keyFile.get_boolean ("General", "RecentlySaved");
}
timeValid = keyFile.has_group ("DateTime");
if (timeValid) {
if (keyFile.has_key ("DateTime", "Year")) year = keyFile.get_integer ("DateTime", "Year");
if (keyFile.has_key ("DateTime", "Month")) month = keyFile.get_integer ("DateTime", "Month");
if (keyFile.has_key ("DateTime", "Day")) day = keyFile.get_integer ("DateTime", "Day");
if (keyFile.has_key ("DateTime", "Hour")) hour = keyFile.get_integer ("DateTime", "Hour");
if (keyFile.has_key ("DateTime", "Min")) min = keyFile.get_integer ("DateTime", "Min");
if (keyFile.has_key ("DateTime", "Sec")) sec = keyFile.get_integer ("DateTime", "Sec");
if (keyFile.has_key ("DateTime", "MSec")) msec = keyFile.get_integer ("DateTime", "MSec");
}
exifValid = false;
if (keyFile.has_group ("ExifInfo")) {
exifValid = true;
if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid");
if (exifValid) {
if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber");
if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter");
if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen");
if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm");
else focalLen35mm=focalLen; // prevent crashes on old files
if (keyFile.has_key ("ExifInfo", "FocusDist")) focusDist = keyFile.get_double ("ExifInfo", "FocusDist");
else focusDist=0;
if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO");
if (keyFile.has_key ("ExifInfo", "ExpComp")) expcomp = keyFile.get_string ("ExifInfo", "ExpComp");
if (keyFile.has_group ("General")) {
if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5");
if (keyFile.has_key ("General", "Version")) version = keyFile.get_string ("General", "Version");
if (keyFile.has_key ("General", "Supported")) supported = keyFile.get_boolean ("General", "Supported");
if (keyFile.has_key ("General", "Format")) format = (ThFileType)keyFile.get_integer ("General", "Format");
if (keyFile.has_key ("General", "Rank")) rankOld = keyFile.get_integer ("General", "Rank");
if (keyFile.has_key ("General", "InTrash")) inTrashOld = keyFile.get_boolean ("General", "InTrash");
if (keyFile.has_key ("General", "RecentlySaved")) recentlySaved = keyFile.get_boolean ("General", "RecentlySaved");
}
if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens");
if (keyFile.has_key ("ExifInfo", "Camera")) camera = keyFile.get_string ("ExifInfo", "Camera");
}
if (keyFile.has_group ("FileInfo")) {
if (keyFile.has_key ("FileInfo", "Filetype")) filetype = keyFile.get_string ("FileInfo", "Filetype");
}
timeValid = keyFile.has_group ("DateTime");
if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType");
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset");
if (timeValid) {
if (keyFile.has_key ("DateTime", "Year")) year = keyFile.get_integer ("DateTime", "Year");
if (keyFile.has_key ("DateTime", "Month")) month = keyFile.get_integer ("DateTime", "Month");
if (keyFile.has_key ("DateTime", "Day")) day = keyFile.get_integer ("DateTime", "Day");
if (keyFile.has_key ("DateTime", "Hour")) hour = keyFile.get_integer ("DateTime", "Hour");
if (keyFile.has_key ("DateTime", "Min")) min = keyFile.get_integer ("DateTime", "Min");
if (keyFile.has_key ("DateTime", "Sec")) sec = keyFile.get_integer ("DateTime", "Sec");
if (keyFile.has_key ("DateTime", "MSec")) msec = keyFile.get_integer ("DateTime", "MSec");
}
exifValid = false;
if (keyFile.has_group ("ExifInfo")) {
exifValid = true;
if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid");
if (exifValid) {
if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber");
if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter");
if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen");
if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm");
else focalLen35mm=focalLen; // prevent crashes on old files
if (keyFile.has_key ("ExifInfo", "FocusDist")) focusDist = keyFile.get_double ("ExifInfo", "FocusDist");
else focusDist=0;
if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO");
if (keyFile.has_key ("ExifInfo", "ExpComp")) expcomp = keyFile.get_string ("ExifInfo", "ExpComp");
}
if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens");
if (keyFile.has_key ("ExifInfo", "Camera")) camera = keyFile.get_string ("ExifInfo", "Camera");
}
if (keyFile.has_group ("FileInfo")) {
if (keyFile.has_key ("FileInfo", "Filetype")) filetype = keyFile.get_string ("FileInfo", "Filetype");
}
if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType");
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset");
}
else {
rotate = 0;
thumbImgType = 0;
}
return 0;
}
else {
rotate = 0;
thumbImgType = 0;
}
return 0;
}
catch (Glib::Error &err) {
printf("Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str());
if (options.rtSettings.verbose)
printf("CacheImageData::load / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str());
}
catch (...) {
if (options.rtSettings.verbose)
printf("CacheImageData::load / Unknown exception while trying to load \"%s\"!\n", fname.c_str());
}
return 1;
}
@@ -114,7 +114,19 @@ int CacheImageData::save (const Glib::ustring& fname) {
rtengine::SafeKeyFile keyFile;
if (safe_file_test(fname,Glib::FILE_TEST_EXISTS)) keyFile.load_from_file (fname);
if (safe_file_test(fname,Glib::FILE_TEST_EXISTS)) {
try {
keyFile.load_from_file (fname);
}
catch (Glib::Error &err) {
if (options.rtSettings.verbose)
printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str());
}
catch (...) {
if (options.rtSettings.verbose)
printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str());
}
}
keyFile.set_string ("General", "MD5", md5);
keyFile.set_string ("General", "Version", VERSION); // Application's version
@@ -126,7 +138,7 @@ int CacheImageData::save (const Glib::ustring& fname) {
if (keyFile.has_key ("General", "Rank")) keyFile.remove_key("General", "Rank");
if (keyFile.has_key ("General", "InTrash")) keyFile.remove_key("General", "InTrash");
if (timeValid) {
if (timeValid) {
keyFile.set_integer ("DateTime", "Year", year);
keyFile.set_integer ("DateTime", "Month", month);
keyFile.set_integer ("DateTime", "Day", day);
@@ -137,7 +149,7 @@ int CacheImageData::save (const Glib::ustring& fname) {
}
keyFile.set_boolean ("ExifInfo", "Valid", exifValid);
if (exifValid) {
if (exifValid) {
keyFile.set_double ("ExifInfo", "FNumber", fnumber);
keyFile.set_double ("ExifInfo", "Shutter", shutter);
keyFile.set_double ("ExifInfo", "FocalLen", focalLen);
@@ -156,8 +168,11 @@ int CacheImageData::save (const Glib::ustring& fname) {
}
FILE *f = safe_g_fopen (fname, "wt");
if (!f)
if (!f) {
if (options.rtSettings.verbose)
printf("CacheImageData::save / Error: unable to open file \"\" with write access!\n", fname.c_str());
return 1;
}
else {
fprintf (f, "%s", keyFile.to_data().c_str());
fclose (f);

View File

@@ -33,8 +33,8 @@ CacheManager::getInstance(void)
static CacheManager* instance_ = 0;
if ( instance_ == 0 )
{
static Glib::Mutex smutex_;
Glib::Mutex::Lock lock(smutex_);
static MyMutex smutex_;
MyMutex::MyLock lock(smutex_);
if ( instance_ == 0 )
{
instance_ = new CacheManager();
@@ -45,7 +45,7 @@ CacheManager::getInstance(void)
void CacheManager::init () {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
openEntries.clear ();
baseDir = options.cacheBaseDir;
@@ -75,7 +75,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname, const rtengine::p
// take manager lock and search for entry, if found return it else release
// lock and create it
{
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
string_thumb_map::iterator r = openEntries.find (fname);
// if it is open, return it
@@ -119,7 +119,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname, const rtengine::p
// was use it over our version. if not added we create the cache entry
if (res)
{
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
string_thumb_map::iterator r = openEntries.find (fname);
if (r!=openEntries.end()) {
@@ -138,7 +138,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname, const rtengine::p
void CacheManager::deleteEntry (const Glib::ustring& fname) {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
// check if it is opened
string_thumb_map::iterator r = openEntries.find (fname);
@@ -200,7 +200,7 @@ void CacheManager::clearFromCache (const Glib::ustring& fname, bool leavenotrace
void CacheManager::renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename) {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
std::string newmd5 = getMD5 (newfilename);
@@ -228,7 +228,7 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin
void CacheManager::closeThumbnail (Thumbnail* t) {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
t->updateCache ();
string_thumb_map::iterator r = openEntries.find (t->getFileName());
@@ -239,14 +239,14 @@ void CacheManager::closeThumbnail (Thumbnail* t) {
void CacheManager::closeCache () {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
applyCacheSizeLimitation ();
}
void CacheManager::clearAll () {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
deleteDir ("images");
deleteDir ("aehistograms");
@@ -264,7 +264,7 @@ void CacheManager::clearAll () {
}
void CacheManager::clearThumbImages () {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
deleteDir ("images");
deleteDir ("aehistograms");
@@ -272,7 +272,7 @@ void CacheManager::clearThumbImages () {
}
void CacheManager::clearProfiles () {
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
deleteDir ("profiles");
}

View File

@@ -25,6 +25,7 @@
#include "thumbnail.h"
#include <cstdio>
#include "../rtengine/procparams.h"
#include "threadutils.h"
class Thumbnail;
@@ -35,7 +36,7 @@ class CacheManager {
string_thumb_map openEntries;
Glib::ustring baseDir;
Glib::Mutex mutex_;
MyMutex mutex_;
void deleteDir (const Glib::ustring& dirName);
@@ -43,20 +44,20 @@ class CacheManager {
public:
static CacheManager* getInstance(void);
static CacheManager* getInstance(void);
void init ();
Thumbnail* getEntry (const Glib::ustring& fname, const rtengine::procparams::ProcParams *pparams=NULL);
void deleteEntry (const Glib::ustring& fname);
void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename);
void closeThumbnail (Thumbnail* t);
const Glib::ustring& getBaseDir () { Glib::Mutex::Lock lock(mutex_); return baseDir; }
const Glib::ustring& getBaseDir () { MyMutex::MyLock lock(mutex_); return baseDir; }
void closeCache ();
static std::string getMD5 (const Glib::ustring& fname);
void clearAll ();
void clearThumbImages ();
void clearProfiles ();

View File

@@ -20,6 +20,7 @@
#define __CROPHANDLER__
#include "../rtengine/rtengine.h"
#include "threadutils.h"
#include <gtkmm.h>
class CropHandlerListener {
@@ -48,7 +49,7 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size
int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf
bool enabled;
unsigned char* cropimg;
unsigned char* cropimgtrue;
unsigned char* cropimgtrue;
int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis;
bool initial;
bool isLowUpdatePriority;
@@ -60,24 +61,24 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size
CropHandlerIdleHelper* chi;
void compDim ();
public:
void update ();
void update ();
rtengine::procparams::CropParams cropParams;
rtengine::procparams::ColorManagementParams colorParams;
rtengine::procparams::ColorManagementParams colorParams;
Glib::RefPtr<Gdk::Pixbuf> cropPixbuf;
Glib::RefPtr<Gdk::Pixbuf> cropPixbuftrue;
Glib::RefPtr<Gdk::Pixbuf> cropPixbuftrue;
Glib::Mutex cimg;
MyMutex cimg;
CropHandler ();
~CropHandler ();
void setCropHandlerListener (CropHandlerListener* l) { listener = l; }
void newImage (rtengine::StagedImageProcessor* ipc_);
void setZoom (int z, int centerx=-1, int centery=-1);
double getFitZoom ();
@@ -93,11 +94,11 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size
// DetailedCropListener interface
void setDetailedCrop (rtengine::IImage8* im, rtengine::IImage8* imworking,rtengine::procparams::ColorManagementParams cmp,
rtengine::procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip);
rtengine::procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip);
bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip);
// SizeListener interface
void sizeChanged (int w, int h, int ow, int oh);
void cutRectToImgBounds (int& x, int& y, int& w, int& h);
};

View File

@@ -21,6 +21,7 @@
#include "cropwindow.h"
#include "options.h"
#include "guiutils.h"
#include "threadutils.h"
#include "../rtengine/mytime.h"
#include "imagearea.h"
#include "cursormanager.h"
@@ -488,7 +489,7 @@ void CropWindow::pointerMoved (int x, int y) {
if (pmhlistener) pmhlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1);
}
else {
/*Glib::Mutex::Lock lock(cropHandler.cimg);
/*MyMutex::MyLock lock(cropHandler.cimg);
int vx = x - xpos - imgX;
int vy = y - ypos - imgY;
@@ -630,7 +631,7 @@ void CropWindow::updateCursor (int x, int y) {
}
void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr) {
Glib::Mutex::Lock lock(cropHandler.cimg);
MyMutex::MyLock lock(cropHandler.cimg);
//MyTime t1, t2, t3, t4;

View File

@@ -22,6 +22,7 @@
#include "rtwindow.h"
#include <gtk/gtk.h>
#include "rtimage.h"
#include "threadutils.h"
static EditWindow* editWnd = NULL;
@@ -36,16 +37,16 @@ EditWindow* EditWindow::getInstance(RTWindow* p)
if ( editWnd == NULL )
{
static Glib::Mutex smutex_;
Glib::Mutex::Lock lock(smutex_);
static MyMutex smutex_;
MyMutex::MyLock lock(smutex_);
if ( editWnd == 0 )
{
editWnd = new EditWindow(p);
// Determine the other display and maximize the window on that
const Glib::RefPtr< Gdk::Window >& wnd=p->get_window();
const Glib::RefPtr< Gdk::Window >& wnd=p->get_window();
int monNo=p->get_screen()->get_monitor_at_window (wnd);
Gdk::Rectangle lMonitorRect;
editWnd->get_screen()->get_monitor_geometry(monNo==0 ? 1:0, lMonitorRect);
editWnd->move(lMonitorRect.get_x(), lMonitorRect.get_y());

View File

@@ -68,8 +68,8 @@ ExtProgStore* ExtProgStore::getInstance()
static ExtProgStore* instance_ = 0;
if ( instance_ == 0 )
{
static Glib::Mutex smutex_;
Glib::Mutex::Lock lock(smutex_);
static MyMutex smutex_;
MyMutex::MyLock lock(smutex_);
if ( instance_ == 0 )
{
instance_ = new ExtProgStore();
@@ -84,7 +84,7 @@ ExtProgStore::~ExtProgStore() {
// Reads all profiles from the given profiles dir
void ExtProgStore::init () {
Glib::Mutex::Lock lock(mtx);
MyMutex::MyLock lock(mtx);
lActions.clear();

View File

@@ -22,6 +22,7 @@
#include <glibmm.h>
#include <list>
#include "threadutils.h"
class ExtProgAction {
public:
@@ -40,7 +41,7 @@ public:
// Stores all external programs that could be called by the user
class ExtProgStore {
Glib::Mutex mtx; // covers actions
MyMutex mtx; // covers actions
bool SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess);

View File

@@ -29,7 +29,7 @@
#include "../rtengine/dfmanager.h"
#include "../rtengine/ffmanager.h"
#include "rtimage.h"
#include "guiutils.h"
#include "threadutils.h"
extern Options options;

View File

@@ -21,6 +21,7 @@
#include "cursormanager.h"
#include <iomanip>
#include "guiutils.h"
#include "threadutils.h"
#include "../rtengine/safegtk.h"
#include <cstring>

View File

@@ -463,7 +463,7 @@ void FileCatalog::closeDir () {
fileNameList.clear ();
{
Glib::Mutex::Lock lock(dirEFSMutex);
MyMutex::MyLock lock(dirEFSMutex);
dirEFS.clear ();
}
hasValidCurrentEFS = false;
@@ -588,7 +588,7 @@ void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) {
const CacheImageData* cfs = fdn->thumbnail->getCacheImageData();
{
Glib::Mutex::Lock lock(dirEFSMutex);
MyMutex::MyLock lock(dirEFSMutex);
if (cfs->exifValid) {
if (cfs->fnumber < dirEFS.fnumberFrom)
dirEFS.fnumberFrom = cfs->fnumber;
@@ -634,7 +634,7 @@ void FileCatalog::previewsFinishedUI () {
if (filterPanel) {
filterPanel->set_sensitive (true);
if ( !hasValidCurrentEFS ){
Glib::Mutex::Lock lock(dirEFSMutex);
MyMutex::MyLock lock(dirEFSMutex);
currentEFS = dirEFS;
filterPanel->setFilter ( dirEFS,true );
}else {
@@ -672,7 +672,7 @@ void FileCatalog::previewsFinished (int dir_id) {
}
if (!hasValidCurrentEFS) {
Glib::Mutex::Lock lock(dirEFSMutex);
MyMutex::MyLock lock(dirEFSMutex);
currentEFS = dirEFS;
}
@@ -1322,7 +1322,7 @@ BrowserFilter FileCatalog::getFilter () {
filter.exifFilterEnabled = false;
else {
if (!hasValidCurrentEFS) {
Glib::Mutex::Lock lock(dirEFSMutex);
MyMutex::MyLock lock(dirEFSMutex);
filter.exifFilter = dirEFS;
}
else

View File

@@ -36,6 +36,7 @@
#include "exportpanel.h"
#include "previewloader.h"
#include "multilangmgr.h"
#include "threadutils.h"
class DirEntry {
@@ -133,7 +134,7 @@ class FileCatalog : public Gtk::VBox,
Gtk::Button* zoomInButton;
Gtk::Button* zoomOutButton;
Glib::Mutex dirEFSMutex;
MyMutex dirEFSMutex;
ExifFilterSettings dirEFS;
ExifFilterSettings currentEFS;
bool hasValidCurrentEFS;

View File

@@ -20,7 +20,6 @@
#define __GUI_UTILS_
#include <gtkmm.h>
#include <glibmm.h>
#include "../rtengine/rtengine.h"
#include <sstream>
#include <iostream>
@@ -77,455 +76,6 @@ public:
}
};
#ifdef NDEBUG
// We don't trace mutex
#undef TRACE_MYRWMUTEX
#define TRACE_MYRWMUTEX 0
#endif
// Uncomment this if you want to bypass the CMakeList options and force the values
// Of course, DO NOT COMMIT! :)
//#undef PROTECT_VECTORS
//#define PROTECT_VECTORS 1
//#undef TRACE_MYRWMUTEX
//#define TRACE_MYRWMUTEX 1
/**
* @brief Custom RWLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
* It may be slower, but thread safe!
*/
class MyRWMutex {
public:
Glib::Mutex handlerMutex;
Glib::Cond access;
size_t writerCount;
size_t readerCount;
#if TRACE_MYRWMUTEX
Glib::ustring lastWriterFile;
int lastWriterLine;
// Unfortunately, ownerThread may not be the culprit of a deadlock, it can be another concurrent Reader...
void* ownerThread;
MyRWMutex() : writerCount(0), readerCount(0), lastWriterLine(0), ownerThread(NULL) {}
#else
MyRWMutex() : writerCount(0), readerCount(0) {}
#endif
};
/**
* @brief Custom ReaderLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
*/
class MyReaderLock {
MyRWMutex& rwMutex;
bool locked;
#if TRACE_MYRWMUTEX
static unsigned int readerLockCounter;
int locknumber;
public:
inline MyReaderLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
#else
public:
inline MyReaderLock(MyRWMutex& mutex) : rwMutex(mutex)
#endif
{
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
locknumber = readerLockCounter++;
void* thread = Glib::Thread::self();
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R";
#endif
if (!rwMutex.writerCount) {
// There's no writer operating, we can increment the writer count which will lock writers
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << " ++ new owner";
#endif
}
else {
// The writer count is non null, but we can be the owner of the writer lock
// It will be the case if the reader count is non null too.
if (!rwMutex.readerCount) {
// the mutex is in real write mode, we're waiting to see it null
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R ++ new owner";
#endif
}
}
// then we can increment the reader count
++rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire(const char* file, const int line)
#else
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (!locked) {
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock)";
#endif
if (!rwMutex.writerCount) {
// There's no writer operating, we can increment the writer count which will lock writers
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << " ++ new owner";
#endif
}
else {
// The writer count is non null, but a reader can be the owner of the writer lock,
// it will be the case if the reader count is non null too.
if (!rwMutex.readerCount) {
// the mutex is in real write mode, we're waiting to see it null
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock) ++ new owner";
#endif
}
}
// then we can increment the reader count
++rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already locked by this object - R (lock)" << std::endl;
#endif
}
inline ~MyReaderLock() {
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - R - ReaderCount: " << rwMutex.readerCount;
#endif
if (!rwMutex.readerCount) {
// no more reader, so we decrement the writer count
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
#endif
// and signal the next waiting reader/writer that it's free
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << std::endl;
#endif
rwMutex.handlerMutex.unlock();
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - R" << std::endl;
#endif
}
#if TRACE_MYRWMUTEX
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release(const char* file, const int line)
#else
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - R (release) - ReaderCount: " << rwMutex.readerCount;
#endif
if (!rwMutex.readerCount) {
// no more reader, so we decrement the writer count
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
#endif
// and signal the next waiting reader/writer that it's free
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = false;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked - R (release)" << std::endl;
#endif
}
};
/**
* @brief Custom WriterLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
*/
class MyWriterLock {
MyRWMutex& rwMutex;
bool locked;
#if TRACE_MYRWMUTEX
static unsigned int writerLockCounter;
int locknumber;
public:
inline MyWriterLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
#else
public:
inline MyWriterLock(MyRWMutex& mutex) : rwMutex(mutex)
#endif
{
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
locknumber = writerLockCounter++;
void* thread = Glib::Thread::self();
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - W";
#endif
if (rwMutex.writerCount) {
// The writer count is non null, so we have to wait for it to be null again
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W";
#endif
}
// then we can increment the writer count
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire(const char* file, const int line)
#else
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (!locked) {
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
#endif
if (rwMutex.writerCount) {
// The writer count is non null, so we have to wait for it to be null again
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
#endif
}
// then we can increment the reader count
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already locked by this object - W (lock)" << std::endl;
#endif
}
inline ~MyWriterLock() {
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - W";
#endif
if (!rwMutex.writerCount) {
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!";
#endif
// The writer count is null again, so we can wake up the next writer or reader
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W" << std::endl;
#endif
}
#if TRACE_MYRWMUTEX
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release(const char* file, const int line)
#else
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - W (release)";
#endif
if (!rwMutex.writerCount) {
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!";
#endif
// The writer count is null again, so we can wake up the next writer or reader
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = false;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W (release)" << std::endl;
#endif
}
};
#if TRACE_MYRWMUTEX
#define MYREADERLOCK(ln, e) MyReaderLock ln(e, #e, __FILE__, __LINE__);
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e, #e, __FILE__, __LINE__);
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
#define MYREADERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
#define MYWRITERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
#else
#define MYREADERLOCK(ln, e) MyReaderLock ln(e);
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e);
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire();
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire();
#define MYREADERLOCK_RELEASE(ln) ln.release();
#define MYWRITERLOCK_RELEASE(ln) ln.release();
#endif
/**
* @brief subclass of Gtk::ScrolledWindow in order to handle the scrollwheel
*/

View File

@@ -90,6 +90,12 @@ int processLineParams( int argc, char **argv );
int main(int argc, char **argv)
{
setlocale(LC_ALL,"");
Glib::thread_init();
gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave)));
gdk_threads_init();
Gio::init ();
#ifdef BUILD_BUNDLE
char exname[512] = {0};
Glib::ustring exePath;
@@ -127,11 +133,6 @@ int main(int argc, char **argv)
licensePath = LICENCE_SEARCH_PATH;
#endif
Glib::thread_init();
gdk_threads_set_lock_functions(G_CALLBACK(myGdkLockEnter), (G_CALLBACK(myGdkLockLeave)));
gdk_threads_init();
Gio::init ();
mainThread = Glib::Thread::self();
Options::load ();

View File

@@ -499,22 +499,20 @@ int Options::readFromFile (Glib::ustring fname) {
rtengine::SafeKeyFile keyFile;
try {
if( !safe_file_test(fname,Glib::FILE_TEST_EXISTS))
return 1;
if (!keyFile.load_from_file (fname))
return 1;
}
catch (Glib::FileError &err) {
if( !safe_file_test(fname,Glib::FILE_TEST_EXISTS))
return 1;
}
setDefaults ();
try {
if (keyFile.load_from_file (fname)) {
setDefaults ();
// --------------------------------------------------------------------------------------------------------
if (keyFile.has_group ("General")) {
if (keyFile.has_key ("General", "TabbedEditor")) tabbedUI= keyFile.get_boolean ("General", "TabbedEditor");
if (keyFile.has_key ("General", "StartupDirectory")){
if( keyFile.get_string ("General", "StartupDirectory") == "home") startupDir = STARTUPDIR_HOME;
if ( keyFile.get_string ("General", "StartupDirectory") == "home") startupDir = STARTUPDIR_HOME;
else if ( keyFile.get_string ("General", "StartupDirectory") == "current") startupDir = STARTUPDIR_CURRENT;
else if ( keyFile.get_string ("General", "StartupDirectory") == "last") startupDir = STARTUPDIR_LAST;
else if ( keyFile.get_string ("General", "StartupDirectory") == "custom") startupDir = STARTUPDIR_CUSTOM;
@@ -669,8 +667,6 @@ if (keyFile.has_group ("GUI")) {
if (keyFile.has_key ("GUI", "UseIconNoText")) UseIconNoText = keyFile.get_boolean ("GUI", "UseIconNoText");
}
if (keyFile.has_group ("Crop Settings")) {
if (keyFile.has_key ("Crop Settings", "PPI")) cropPPI = keyFile.get_integer ("Crop Settings", "PPI");
}
@@ -703,7 +699,7 @@ if (keyFile.has_group ("Color Management")) {
if( keyFile.has_key ("Color Management", "ProtectRed")) rtSettings.protectred = keyFile.get_integer("Color Management", "ProtectRed");
if( keyFile.has_key ("Color Management", "ProtectRedH")) rtSettings.protectredh = keyFile.get_double("Color Management", "ProtectRedH");
// if( keyFile.has_key ("Color Management", "Ciebadpixgauss")) rtSettings.ciebadpixgauss = keyFile.get_boolean("Color Management", "Ciebadpixgauss");
}
if (keyFile.has_group ("Batch Processing")) {
@@ -764,9 +760,25 @@ if (keyFile.has_group ("Dialogs")) {
safeDirGet(keyFile, "Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir);
}
filterOutParsedExtensions ();
// --------------------------------------------------------------------------------------------------------
filterOutParsedExtensions ();
return 0;
}
}
catch (Glib::Error &err) {
if (options.rtSettings.verbose)
printf("Options::readFromFile / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str());
}
catch (...) {
if (options.rtSettings.verbose)
printf("Options::readFromFile / Unknown exception while trying to load \"%s\"!\n", fname.c_str());
}
return 1;
return 0;
}
bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section,
@@ -1015,8 +1027,11 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_string ("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir);
FILE *f = safe_g_fopen (fname, "wt");
if (f==NULL)
if (f==NULL) {
if (options.rtSettings.verbose)
printf("Options::saveToFile / Error: unable to open file \"\" with write access!\n", fname.c_str());
return 1;
}
else {
fprintf (f, "%s", keyFile.to_data().c_str());
fclose (f);

View File

@@ -168,11 +168,11 @@ void PreviewHandler::imageReady (CropParams cp) {
iaimgpar* iap = new iaimgpar;
iap->pih = pih;
iap->cp = cp;
g_idle_add (imageReadyUI, iap);
g_idle_add (imageReadyUI, iap);
}
Glib::RefPtr<Gdk::Pixbuf> PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) {
Glib::Mutex::Lock lock(previewImgMutex);
MyMutex::MyLock lock(previewImgMutex);
Glib::RefPtr<Gdk::Pixbuf> resPixbuf;
@@ -201,7 +201,7 @@ Glib::RefPtr<Gdk::Pixbuf> PreviewHandler::getRoughImage (int x, int y, int w, in
}
Glib::RefPtr<Gdk::Pixbuf> PreviewHandler::getRoughImage (int desiredW, int desiredH, double& zoom_) {
Glib::Mutex::Lock lock(previewImgMutex);
MyMutex::MyLock lock(previewImgMutex);
Glib::RefPtr<Gdk::Pixbuf> resPixbuf;

View File

@@ -20,6 +20,7 @@
#define _PREVIEWHANDLER_
#include "../rtengine/rtengine.h"
#include "threadutils.h"
#include <gtkmm.h>
#include <list>
@@ -49,10 +50,9 @@ class PreviewHandler : public rtengine::PreviewImageListener {
double previewScale;
PreviewHandlerIdleHelper* pih;
std::list<PreviewListener*> listeners;
Glib::Mutex previewImgMutex;
MyMutex previewImgMutex;
Glib::RefPtr<Gdk::Pixbuf> previewImg;
public:
PreviewHandler ();

View File

@@ -20,6 +20,7 @@
#include <set>
#include "previewloader.h"
#include "guiutils.h"
#include "threadutils.h"
#include "../rtengine/safegtk.h"
#ifdef _OPENMP
@@ -75,7 +76,7 @@ public:
}
Glib::ThreadPool* threadPool_;
Glib::Mutex mutex_;
MyMutex mutex_;
JobSet jobs_;
gint nConcurrentThreads;
@@ -83,7 +84,7 @@ public:
{
Job j;
{
Glib::Mutex::Lock lock(mutex_);
MyMutex::MyLock lock(mutex_);
// nothing to do; could be jobs have been removed
if ( jobs_.empty() )
@@ -137,8 +138,8 @@ PreviewLoader* PreviewLoader::getInstance(void)
static PreviewLoader* instance_ = NULL;
if ( instance_ == NULL )
{
static Glib::Mutex smutex_;
Glib::Mutex::Lock lock(smutex_);
static MyMutex smutex_;
MyMutex::MyLock lock(smutex_);
if ( instance_ == NULL ) instance_ = new PreviewLoader();
}
@@ -152,7 +153,7 @@ void PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoade
if ( l != 0 )
{
{
Glib::Mutex::Lock lock(impl_->mutex_);
MyMutex::MyLock lock(impl_->mutex_);
// create a new job and append to queue
DEBUG("saving job %s",dir_entry.c_str());
@@ -168,7 +169,7 @@ void PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoade
void PreviewLoader::removeAllJobs(void)
{
DEBUG("stop %d",impl_->nConcurrentThreads);
Glib::Mutex::Lock lock(impl_->mutex_);
MyMutex::MyLock lock(impl_->mutex_);
impl_->jobs_.clear();
}

View File

@@ -36,7 +36,7 @@ bool ProfileStore::init () {
return false;
if (storeState == STORESTATE_NOTINITIALIZED) {
storeState = STORESTATE_BEINGINITIALIZED;
parseMutex = new Glib::Mutex();
parseMutex = new MyMutex();
_parseProfiles ();
storeState = STORESTATE_INITIALIZED;
}
@@ -47,7 +47,7 @@ ProfileStore::~ProfileStore () {
// This lock prevent object's suppression while scanning the directories
storeState = STORESTATE_DELETED;
Glib::Mutex::Lock lock(*parseMutex);
MyMutex::MyLock lock(*parseMutex);
for (std::map<Glib::ustring,PartialProfile*>::iterator i = partProfiles.begin(); i!=partProfiles.end(); i++) {
if (i->second->pparams) delete i->second->pparams;
@@ -71,7 +71,7 @@ void ProfileStore::parseProfiles () {
if (!init())
// I don't even know if this situation can occur
return;
Glib::Mutex::Lock lock(*parseMutex);
MyMutex::MyLock lock(*parseMutex);
_parseProfiles ();
}
@@ -148,7 +148,7 @@ const PartialProfile* ProfileStore::getProfile (const Glib::ustring& profname) {
if (!init())
// I don't even know if this situation can occur
return NULL;
Glib::Mutex::Lock lock(*parseMutex);
MyMutex::MyLock lock(*parseMutex);
if (partProfiles.find(profname) != partProfiles.end()) {
return partProfiles[profname];
@@ -165,7 +165,7 @@ std::vector<Glib::ustring> ProfileStore::getProfileNames () {
if (!init())
// I don't even know if this situation can occur
return ret;
Glib::Mutex::Lock lock(*parseMutex);
MyMutex::MyLock lock(*parseMutex);
for (std::map<Glib::ustring,PartialProfile*>::iterator i = partProfiles.begin(); i!=partProfiles.end(); i++)
ret.push_back (i->first);

View File

@@ -22,6 +22,7 @@
#include <map>
#include <vector>
#include "../rtengine/rtengine.h"
#include "threadutils.h"
#include "paramsedited.h"
#include <glibmm.h>
@@ -34,7 +35,7 @@ class ProfileStore {
STORESTATE_DELETED
} StoreState;
Glib::Mutex *parseMutex;
MyMutex *parseMutex;
StoreState storeState;
std::map<Glib::ustring, rtengine::procparams::PartialProfile*> partProfiles;
void parseDir (const Glib::ustring& pdir);

View File

@@ -100,13 +100,23 @@ void RTImage::setPaths(Options &opt) {
else {
configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", Glib::ustring::format(opt.theme, ".iconset")));
}
if (!safe_file_test(configFilename, Glib::FILE_TEST_EXISTS) || !keyFile.load_from_file (configFilename)) {
// ...otherwise fallback to the iconset set in default.iconset
configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "Default.iconset"));
if (!keyFile.load_from_file (configFilename)) {
hasKeyFile = false;
try {
if (!safe_file_test(configFilename, Glib::FILE_TEST_EXISTS) || !keyFile.load_from_file (configFilename)) {
// ...otherwise fallback to the iconset set in default.iconset
configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "Default.iconset"));
if (!keyFile.load_from_file (configFilename)) {
hasKeyFile = false;
}
}
}
catch (Glib::Error &err) {
if (options.rtSettings.verbose)
printf("RTImage::setPaths / Error code %d while reading values from \"%s\":\n%s\n", err.code(), configFilename.c_str(), err.what().c_str());
}
catch (...) {
if (options.rtSettings.verbose)
printf("RTImage::setPaths / Unknown exception while trying to load \"%s\"!\n", configFilename.c_str());
}
if (hasKeyFile && keyFile.has_group ("General")) {
Glib::ustring iSet;

619
rtgui/threadutils.h Normal file
View File

@@ -0,0 +1,619 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _THREADUTILS_
#define _THREADUTILS_
#include <glibmm.h>
#include <csignal> // for raise()
#include <cstdio>
#ifdef WIN32
#include <windows.h>
#endif
#ifdef NDEBUG
// We don't trace mutex
#undef TRACE_MYRWMUTEX
#define TRACE_MYRWMUTEX 0
#endif
// Uncomment this if you want to bypass the CMakeList options and force the values
// Of course, DO NOT COMMIT!
//#undef PROTECT_VECTORS
//#define PROTECT_VECTORS 1
//#undef TRACE_MYRWMUTEX
//#define TRACE_MYRWMUTEX 1
//#undef STRICT_MUTEX
//#define STRICT_MUTEX 1
/**
* @brief Custom Mutex to replace Glib::Threads::Mutex, which behave differently on windows (recursive) and linux (non-recursive), by a recursive and "debugable" one
*
* This implementation will behave like a Glib::Threads::RecMutex (STRICT_MUTEX=0) or a Glib::Threads::Mutex (STRICT_MUTEX=1), but in this case, the application will
* crash instead of freezing.
*
* In Debug builds, a printf will let you know that the MyMutex was already locked
*
* The default and recommended mode is STRICT_MUTEX=1
*/
#ifdef WIN32
class MyMutex : public Glib::RecMutex {
#else
class MyMutex : public Glib::Threads::RecMutex {
#endif
#if STRICT_MUTEX || !defined(NDEBUG)
private:
bool alreadyLocked;
#endif
public:
class MyLock;
#if STRICT_MUTEX || !defined(NDEBUG)
MyMutex() : alreadyLocked(false) {}
#else
MyMutex() {}
#endif
void lock() {
#ifdef WIN32
Glib::RecMutex::lock();
#else
Glib::Threads::RecMutex::lock();
#endif
#if STRICT_MUTEX || !defined(NDEBUG)
if (alreadyLocked) {
#ifndef NDEBUG
printf("Warning: MyMutex already locked!\n"); // breakpoint
#endif
#if STRICT_MUTEX
#ifndef NDEBUG
#ifdef WIN32
DebugBreak();
#else
raise(SIGTRAP);
#endif
#else
raise(SIGINT);
#endif
#endif
}
alreadyLocked = true;
#endif
}
bool trylock() {
#ifdef WIN32
if (Glib::RecMutex::trylock())
#else
if (Glib::Threads::RecMutex::trylock())
#endif
{
#if STRICT_MUTEX || !defined(NDEBUG)
if (alreadyLocked) {
#ifndef NDEBUG
printf("Warning: MyMutex already locked!\n"); // breakpoint
#endif
#if STRICT_MUTEX
#ifndef NDEBUG
#ifdef WIN32
DebugBreak();
#else
raise(SIGTRAP);
#endif
#else
raise(SIGINT);
#endif
#endif
}
alreadyLocked = true;
#endif
return true;
}
return false;
}
// Warning: the base class of MyMutex is RecMutex, but the mutex is said "unlocked" on first occurrence of "unlock", to avoid overhead.
void unlock() {
#if STRICT_MUTEX || !defined(NDEBUG)
alreadyLocked = false;
#endif
#ifdef WIN32
Glib::RecMutex::unlock();
#else
Glib::Threads::RecMutex::unlock();
#endif
}
};
// Class copied from the Glibmm source code, to provide a workaround of the behavior's difference between Linux and Windows
class MyMutex::MyLock {
public:
explicit inline MyLock(MyMutex& mutex) : mutex_ (mutex), locked_ (true) { mutex_.lock(); }
#ifdef WIN32
inline MyLock(MyMutex& mutex, Glib::NotLock) : mutex_ (mutex), locked_ (false) {}
inline MyLock(MyMutex& mutex, Glib::TryLock) : mutex_ (mutex), locked_ (mutex.trylock()) {}
#else
inline MyLock(MyMutex& mutex, Glib::Threads::NotLock) : mutex_ (mutex), locked_ (false) {}
inline MyLock(MyMutex& mutex, Glib::Threads::TryLock) : mutex_ (mutex), locked_ (mutex.trylock()) {}
#endif
inline ~MyLock() { if(locked_) mutex_.unlock(); }
inline void acquire() { mutex_.lock(); locked_ = true; }
inline bool try_acquire() { locked_ = mutex_.trylock(); return locked_; }
inline void release() { mutex_.unlock(); locked_ = false; }
inline bool locked() const { return locked_; }
private:
MyMutex& mutex_;
bool locked_;
// noncopyable
MyLock(const MyMutex::Lock&);
MyMutex::Lock& operator=(const MyMutex::Lock&);
};
/**
* @brief Custom RWLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
* It may be slower, but thread safe!
*/
class MyRWMutex {
public:
#ifdef WIN32
Glib::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Mutex
Glib::Cond access;
#else
Glib::Threads::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Threads::Mutex
Glib::Threads::Cond access;
#endif
size_t writerCount;
size_t readerCount;
#if TRACE_MYRWMUTEX
Glib::ustring lastWriterFile;
int lastWriterLine;
// Unfortunately, ownerThread may not be the culprit of a deadlock, it can be another concurrent Reader...
void* ownerThread;
MyRWMutex() : writerCount(0), readerCount(0), lastWriterLine(0), ownerThread(NULL) {}
#else
MyRWMutex() : writerCount(0), readerCount(0) {}
#endif
};
/**
* @brief Custom ReaderLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
*/
class MyReaderLock {
MyRWMutex& rwMutex;
bool locked;
#if TRACE_MYRWMUTEX
static unsigned int readerLockCounter;
int locknumber;
public:
inline MyReaderLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
#else
public:
inline MyReaderLock(MyRWMutex& mutex) : rwMutex(mutex)
#endif
{
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
locknumber = readerLockCounter++;
void* thread = Glib::Thread::self();
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R";
#endif
if (!rwMutex.writerCount) {
// There's no writer operating, we can increment the writer count which will lock writers
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << " ++ new owner";
#endif
}
else {
// The writer count is non null, but we can be the owner of the writer lock
// It will be the case if the reader count is non null too.
if (!rwMutex.readerCount) {
// the mutex is in real write mode, we're waiting to see it null
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R ++ new owner";
#endif
}
}
// then we can increment the reader count
++rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire(const char* file, const int line)
#else
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (!locked) {
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock)";
#endif
if (!rwMutex.writerCount) {
// There's no writer operating, we can increment the writer count which will lock writers
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << " ++ new owner";
#endif
}
else {
// The writer count is non null, but a reader can be the owner of the writer lock,
// it will be the case if the reader count is non null too.
if (!rwMutex.readerCount) {
// the mutex is in real write mode, we're waiting to see it null
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock) ++ new owner";
#endif
}
}
// then we can increment the reader count
++rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already locked by this object - R (lock)" << std::endl;
#endif
}
inline ~MyReaderLock() {
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - R - ReaderCount: " << rwMutex.readerCount;
#endif
if (!rwMutex.readerCount) {
// no more reader, so we decrement the writer count
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
#endif
// and signal the next waiting reader/writer that it's free
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << std::endl;
#endif
rwMutex.handlerMutex.unlock();
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - R" << std::endl;
#endif
}
#if TRACE_MYRWMUTEX
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release(const char* file, const int line)
#else
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.readerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - R (release) - ReaderCount: " << rwMutex.readerCount;
#endif
if (!rwMutex.readerCount) {
// no more reader, so we decrement the writer count
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount;
#endif
// and signal the next waiting reader/writer that it's free
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = false;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked - R (release)" << std::endl;
#endif
}
};
/**
* @brief Custom WriterLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!)
*
*/
class MyWriterLock {
MyRWMutex& rwMutex;
bool locked;
#if TRACE_MYRWMUTEX
static unsigned int writerLockCounter;
int locknumber;
public:
inline MyWriterLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0)
#else
public:
inline MyWriterLock(MyRWMutex& mutex) : rwMutex(mutex)
#endif
{
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
locknumber = writerLockCounter++;
void* thread = Glib::Thread::self();
std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - W";
#endif
if (rwMutex.writerCount) {
// The writer count is non null, so we have to wait for it to be null again
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W";
#endif
}
// then we can increment the writer count
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire(const char* file, const int line)
#else
// locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely
inline void acquire()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (!locked) {
// to operate safely
rwMutex.handlerMutex.lock();
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
#endif
if (rwMutex.writerCount) {
// The writer count is non null, so we have to wait for it to be null again
#if TRACE_MYRWMUTEX
std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl;
#endif
while (rwMutex.writerCount)
rwMutex.access.wait(rwMutex.handlerMutex);
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)";
#endif
}
// then we can increment the reader count
++rwMutex.writerCount;
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = file;
rwMutex.lastWriterLine = line;
rwMutex.ownerThread = thread;
std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = true;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already locked by this object - W (lock)" << std::endl;
#endif
}
inline ~MyWriterLock() {
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - W";
#endif
if (!rwMutex.writerCount) {
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!";
#endif
// The writer count is null again, so we can wake up the next writer or reader
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W" << std::endl;
#endif
}
#if TRACE_MYRWMUTEX
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release(const char* file, const int line)
#else
// releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely
inline void release()
#endif
{
#if TRACE_MYRWMUTEX
void* thread = Glib::Thread::self();
#endif
if (locked) {
// to operate safely
rwMutex.handlerMutex.lock();
// decrement the writer number first
--rwMutex.writerCount;
#if TRACE_MYRWMUTEX
std::cout << thread << "/" << locknumber << " / unlocking - W (release)";
#endif
if (!rwMutex.writerCount) {
#if TRACE_MYRWMUTEX
rwMutex.lastWriterFile = "";
rwMutex.lastWriterLine = 0;
rwMutex.ownerThread = NULL;
std::cout << " -- new owner possible!";
#endif
// The writer count is null again, so we can wake up the next writer or reader
rwMutex.access.broadcast();
}
#if TRACE_MYRWMUTEX
std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl;
#endif
rwMutex.handlerMutex.unlock();
locked = false;
}
#if TRACE_MYRWMUTEX
else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W (release)" << std::endl;
#endif
}
};
#if TRACE_MYRWMUTEX
#define MYREADERLOCK(ln, e) MyReaderLock ln(e, #e, __FILE__, __LINE__);
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e, #e, __FILE__, __LINE__);
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire(__FILE__, __LINE__);
#define MYREADERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
#define MYWRITERLOCK_RELEASE(ln) ln.release(__FILE__, __LINE__);
#else
#define MYREADERLOCK(ln, e) MyReaderLock ln(e);
#define MYWRITERLOCK(ln, e) MyWriterLock ln(e);
#define MYREADERLOCK_ACQUIRE(ln) ln.acquire();
#define MYWRITERLOCK_ACQUIRE(ln) ln.acquire();
#define MYREADERLOCK_RELEASE(ln) ln.release();
#define MYWRITERLOCK_RELEASE(ln) ln.release();
#endif
#endif /* _THREADUTILS_ */

View File

@@ -22,7 +22,7 @@
#include <gtkmm.h>
#include "lwbuttonset.h"
#include "thumbnail.h"
#include "guiutils.h"
#include "threadutils.h"
class ThumbBrowserBase;
class ThumbBrowserEntryBase {

View File

@@ -21,6 +21,7 @@
#include "thumbimageupdater.h"
#include <gtkmm.h>
#include "guiutils.h"
#include "threadutils.h"
#ifdef _OPENMP
#include <omp.h>
@@ -77,7 +78,13 @@ public:
Glib::ThreadPool* threadPool_;
// Need to be a Glib::Threads::Mutex because used in a Glib::Threads::Cond object...
// This is the only exceptions in RT so far, MyMutex is used everywhere else
#ifdef WIN32
Glib::Mutex mutex_;
#else
Glib::Threads::Mutex mutex_;
#endif
JobList jobs_;
@@ -85,7 +92,11 @@ public:
bool inactive_waiting_;
#ifdef WIN32
Glib::Cond inactive_;
#else
Glib::Threads::Cond inactive_;
#endif
void
processNextJob()
@@ -93,7 +104,11 @@ public:
Job j;
{
#ifdef WIN32
Glib::Mutex::Lock lock(mutex_);
#else
Glib::Threads::Mutex::Lock lock(mutex_);
#endif
// nothing to do; could be jobs have been removed
if ( jobs_.empty() )
@@ -168,7 +183,12 @@ public:
}
{
#ifdef WIN32
Glib::Mutex::Lock lock(mutex_);
#else
Glib::Threads::Mutex::Lock lock(mutex_);
#endif
if ( --active_ == 0 &&
inactive_waiting_ )
@@ -206,7 +226,11 @@ ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade,
return;
}
#ifdef WIN32
Glib::Mutex::Lock lock(impl_->mutex_);
#else
Glib::Threads::Mutex::Lock lock(impl_->mutex_);
#endif
// look up if an older version is in the queue
Impl::JobList::iterator i(impl_->jobs_.begin());
@@ -239,7 +263,11 @@ ThumbImageUpdater::removeJobs(ThumbImageUpdateListener* listener)
{
DEBUG("removeJobs(%p)",listener);
#ifdef WIN32
Glib::Mutex::Lock lock(impl_->mutex_);
#else
Glib::Threads::Mutex::Lock lock(impl_->mutex_);
#endif
for( Impl::JobList::iterator i(impl_->jobs_.begin()); i != impl_->jobs_.end(); )
{
@@ -271,8 +299,11 @@ ThumbImageUpdater::removeAllJobs(void)
{
DEBUG("stop");
#ifdef WIN32
Glib::Mutex::Lock lock(impl_->mutex_);
#else
Glib::Threads::Mutex::Lock lock(impl_->mutex_);
#endif
impl_->jobs_.clear();

View File

@@ -45,6 +45,8 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageDa
}
else
loadProcParams ();
// should be safe to use the unprotected version of loadThumbnail, since we are in the constructor
_loadThumbnail ();
generateExifDateTimeStrings ();
@@ -165,11 +167,12 @@ bool Thumbnail::isSupported () {
}
const ProcParams& Thumbnail::getProcParams () {
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
MyMutex::MyLock lock(mutex);
return getProcParamsU();
}
// Unprotected version of getProcParams, when
const ProcParams& Thumbnail::getProcParamsU () {
if (pparamsValid)
return pparams;
else {
@@ -239,10 +242,7 @@ void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt){
* ProcParams (sidecar or cache file).
*/
void Thumbnail::loadProcParams () {
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
MyMutex::MyLock lock(mutex);
pparamsValid = false;
pparams.setDefaults();
@@ -278,11 +278,9 @@ void Thumbnail::clearProcParams (int whoClearedIt) {
the "clear profile" will lead to execution of ProcParams::setDefaults
(the CPB is NOT called) to set the params values and will preserve
rank/colorlabel/inTrash in the param file. */
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
{
MyMutex::MyLock lock(mutex);
// preserve rank, colorlabel and inTrash across clear
int rank = getRank();
@@ -326,6 +324,8 @@ void Thumbnail::clearProcParams (int whoClearedIt) {
safe_g_remove (fname_);
}
} // end of mutex lock
for (size_t i=0; i<listeners.size(); i++)
listeners[i]->procParamsChanged (this, whoClearedIt);
}
@@ -336,15 +336,14 @@ bool Thumbnail::hasProcParams () {
}
void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoChangedIt, bool updateCacheNow) {
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
if (pparams.sharpening.threshold.isDouble() != pp.sharpening.threshold.isDouble())
printf("WARNING: Sharpening different!\n");
if (pparams.vibrance.psthreshold.isDouble() != pp.vibrance.psthreshold.isDouble())
printf("WARNING: Vibrance different!\n");
{
MyMutex::MyLock lock(mutex);
if (pparams.sharpening.threshold.isDouble() != pp.sharpening.threshold.isDouble())
printf("WARNING: Sharpening different!\n");
if (pparams.vibrance.psthreshold.isDouble() != pp.vibrance.psthreshold.isDouble())
printf("WARNING: Vibrance different!\n");
if (pparams!=pp)
cfs.recentlySaved = false;
@@ -368,6 +367,8 @@ void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoCh
if (updateCacheNow)
updateCache ();
} // end of mutex lock
for (size_t i=0; i<listeners.size(); i++)
listeners[i]->procParamsChanged (this, whoChangedIt);
}
@@ -401,14 +402,14 @@ bool Thumbnail::isEnqueued () {
void Thumbnail::increaseRef ()
{
Glib::Mutex::Lock lock(mutex);
++ref;
MyMutex::MyLock lock(mutex);
++ref;
}
void Thumbnail::decreaseRef ()
{
{
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
if ( ref == 0 )
{
return;
@@ -429,10 +430,7 @@ void Thumbnail::getThumbnailSize (int &w, int &h) {
}
void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h) {
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
MyMutex::MyLock lock(mutex);
// WARNING: When downscaled, the ratio have loosed a lot of precision, so we can't get back the exact initial dimensions
double fw = lastW*lastScale;
@@ -455,40 +453,35 @@ void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& pparams, i
rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) {
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
if ( tpp == 0 )
{
_loadThumbnail();
if ( tpp == 0 )
{
return 0;
}
}
rtengine::IImage8* image = 0;
if ( tpp == 0 ) {
_loadThumbnail();
if ( tpp == 0 )
return 0;
}
if ( cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL )
{
// RAW internal thumbnail, no profile yet: just do some rotation etc.
image = tpp->quickProcessImage (pparams, h, rtengine::TI_Nearest, scale);
}
else
{
// Full thumbnail: apply profile
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
}
rtengine::IImage8* image = 0;
if ( cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL ) {
// RAW internal thumbnail, no profile yet: just do some rotation etc.
image = tpp->quickProcessImage (pparams, h, rtengine::TI_Nearest, scale);
}
else {
// Full thumbnail: apply profile
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
}
tpp->getDimensions(lastW,lastH,lastScale);
delete tpp;
tpp = 0;
return image;
delete tpp;
tpp = 0;
return image;
}
rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) {
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
if ( cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL )
{
@@ -678,7 +671,7 @@ void Thumbnail::_loadThumbnail(bool firstTrial) {
tpp->init ();
}
if (!initial_ && tpp) tw = tpp->getImageWidth (getProcParams(), th, imgRatio); // this might return 0 if image was just building
if (!initial_ && tpp) tw = tpp->getImageWidth (getProcParamsU(), th, imgRatio); // this might return 0 if image was just building
}
/*
@@ -690,7 +683,7 @@ void Thumbnail::_loadThumbnail(bool firstTrial) {
* - LiveThumbData section of the data file
*/
void Thumbnail::loadThumbnail (bool firstTrial) {
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
_loadThumbnail(firstTrial);
}
@@ -737,7 +730,7 @@ void Thumbnail::_saveThumbnail () {
*/
void Thumbnail::saveThumbnail ()
{
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
_saveThumbnail();
}
@@ -760,13 +753,11 @@ void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData) {
}
Thumbnail::~Thumbnail () {
// TODO: Check for Linux
#ifdef WIN32
Glib::Mutex::Lock lock(mutex);
#endif
mutex.lock();
delete [] lastImg;
delete tpp;
mutex.unlock();
}
Glib::ustring Thumbnail::getCacheFileName (Glib::ustring subdir) {
@@ -860,7 +851,7 @@ bool Thumbnail::openDefaultViewer(int destination) {
bool Thumbnail::imageLoad(bool loading)
{
Glib::Mutex::Lock lock(mutex);
MyMutex::MyLock lock(mutex);
bool previous = imageLoading;
if( loading && !previous ){
imageLoading = true;

View File

@@ -27,11 +27,12 @@
#include "../rtengine/rtthumbnail.h"
#include "cacheimagedata.h"
#include "thumbnaillistener.h"
#include "threadutils.h"
class CacheManager;
class Thumbnail {
Glib::Mutex mutex;
MyMutex mutex;
Glib::ustring fname; // file name corresponding to the thumbnail
CacheImageData cfs; // cache entry corresponding to the thumbnail
@@ -82,6 +83,7 @@ class Thumbnail {
bool hasProcParams ();
const rtengine::procparams::ProcParams& getProcParams ();
const rtengine::procparams::ProcParams& getProcParamsU (); // Unprotected version
// Use this to create params on demand for update
rtengine::procparams::ProcParams* createProcParamsForUpdate (bool returnParams, bool forceCPB);