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:
@@ -19,6 +19,7 @@
|
||||
#define _BATCHQUEUE_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include "threadutils.h"
|
||||
#include "batchqueueentry.h"
|
||||
#include "../rtengine/rtengine.h"
|
||||
#include "options.h"
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cstring>
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "multilangmgr.h"
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 ();
|
||||
|
@@ -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);
|
||||
|
@@ -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");
|
||||
}
|
||||
|
@@ -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 ();
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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());
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include "../rtengine/dfmanager.h"
|
||||
#include "../rtengine/ffmanager.h"
|
||||
#include "rtimage.h"
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
|
||||
extern Options options;
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "cursormanager.h"
|
||||
#include <iomanip>
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
|
||||
#include <cstring>
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
450
rtgui/guiutils.h
450
rtgui/guiutils.h
@@ -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
|
||||
*/
|
||||
|
@@ -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 ();
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 ();
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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
619
rtgui/threadutils.h
Normal 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_ */
|
@@ -22,7 +22,7 @@
|
||||
#include <gtkmm.h>
|
||||
#include "lwbuttonset.h"
|
||||
#include "thumbnail.h"
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
|
||||
class ThumbBrowserBase;
|
||||
class ThumbBrowserEntryBase {
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user