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:
parent
987e4dcd89
commit
f512d74323
@ -73,6 +73,7 @@ option (WITH_BZIP "Build with Bzip2 support" ON)
|
||||
option (WITH_MYFILE_MMAP "Build using memory mapped file" ON)
|
||||
option (OPTION_OMP "Build with OpenMP support" ON)
|
||||
option (PROTECT_VECTORS "Protect critical vectors by custom R/W Mutex, recommanded even if your std::vector is thread safe" ON)
|
||||
option (STRICT_MUTEX "True (recommended): MyMutex will behave like POSIX Mutex; False: MyMutex will behave like POSIX RecMutex; Note: forced to ON for Debug builds" ON)
|
||||
option (TRACE_MYRWMUTEX "Trace RT's custom R/W Mutex (Debug builds only); redirecting std::out to a file is strongly recommended!" OFF)
|
||||
option (AUTO_GDK_FLUSH "Use gdk_flush on all gdk_thread_leave other than the GUI thread; set it ON if you experience X Server warning/errors" OFF)
|
||||
|
||||
@ -162,6 +163,13 @@ if (NOT BUILD_BUNDLE AND
|
||||
message (FATAL_ERROR "The paths has to be absolute or use -DBUILD_BUNDLE=ON")
|
||||
endif ()
|
||||
|
||||
# MyMutex
|
||||
if (STRICT_MUTEX OR UPPER_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
add_definitions (-DSTRICT_MUTEX=1)
|
||||
else (STRICT_MUTEX OR UPPER_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
add_definitions (-DSTRICT_MUTEX=0)
|
||||
endif (STRICT_MUTEX OR UPPER_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
|
||||
# MyRWMutex
|
||||
if (PROTECT_VECTORS)
|
||||
add_definitions (-DPROTECT_VECTORS=1)
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <fftw3.h>
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
//#include "bilateral2.h"
|
||||
#include "gauss.h"
|
||||
@ -87,8 +88,8 @@ namespace rtengine {
|
||||
|
||||
void ImProcFunctions::RGB_denoise(Imagefloat * src, Imagefloat * dst, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp)
|
||||
{
|
||||
static Glib::Mutex FftwMutex;
|
||||
Glib::Mutex::Lock lock(FftwMutex);
|
||||
static MyMutex FftwMutex;
|
||||
MyMutex::MyLock lock(FftwMutex);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <glibmm.h>
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
// Aligned buffer that should be faster
|
||||
template <class T> class AlignedBuffer {
|
||||
@ -107,7 +108,7 @@ public:
|
||||
// Multi processor version, use with OpenMP
|
||||
template <class T> class AlignedBufferMP {
|
||||
private:
|
||||
Glib::Mutex mtx;
|
||||
MyMutex mtx;
|
||||
std::vector<AlignedBuffer<T>*> buffers;
|
||||
size_t size;
|
||||
|
||||
@ -121,7 +122,7 @@ public:
|
||||
}
|
||||
|
||||
AlignedBuffer<T>* acquire() {
|
||||
Glib::Mutex::Lock lock(mtx);
|
||||
MyMutex::MyLock lock(mtx);
|
||||
|
||||
// Find available buffer
|
||||
for (int i;i<buffers.size();i++) {
|
||||
@ -139,7 +140,7 @@ public:
|
||||
}
|
||||
|
||||
void release(AlignedBuffer<T>* buffer) {
|
||||
Glib::Mutex::Lock lock(mtx);
|
||||
MyMutex::MyLock lock(mtx);
|
||||
|
||||
buffer->inUse=false;
|
||||
}
|
||||
|
@ -556,17 +556,17 @@ namespace rtengine {
|
||||
for (int i=0; i<m_h2; i++) {
|
||||
|
||||
if (subsamp_out) {
|
||||
SynthesisFilterSubsamp (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, bufferLo, bufferHi, \
|
||||
SynthesisFilterSubsamp (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, bufferLo, bufferHi,
|
||||
filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
SynthesisFilterSubsamp (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, bufferLo, bufferHi, \
|
||||
SynthesisFilterSubsamp (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, bufferLo, bufferHi,
|
||||
filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
//SynthesisFilterSubsampHaar (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, 1, m_w);//TODO: this is buggy
|
||||
//SynthesisFilterSubsampHaar (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, 1, m_w);
|
||||
} else {
|
||||
//SynthesisFilter (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, bufferLo, bufferHi, \
|
||||
filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
//SynthesisFilter (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, bufferLo, bufferHi, \
|
||||
filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
//SynthesisFilter (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, bufferLo, bufferHi,
|
||||
// filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
//SynthesisFilter (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, bufferLo, bufferHi,
|
||||
// filterH, filterH+taps, taps, offset, 1/*pitch*/, m_w/*dstlen*/);
|
||||
SynthesisFilterHaar (wavcoeffs[0]+i*m_w2, wavcoeffs[1]+i*m_w2, tmpLo+i*m_w, bufferLo, bufferHi, 1, m_w);
|
||||
SynthesisFilterHaar (wavcoeffs[2]+i*m_w2, wavcoeffs[3]+i*m_w2, tmpHi+i*m_w, bufferLo, bufferHi, 1, m_w);
|
||||
}
|
||||
@ -576,12 +576,12 @@ namespace rtengine {
|
||||
//OpenMP here
|
||||
for (int j=0; j<m_w; j++) {
|
||||
if (subsamp_out) {
|
||||
SynthesisFilterSubsamp (tmpLo+j, tmpHi+j, dst+j, bufferLo, bufferHi, \
|
||||
SynthesisFilterSubsamp (tmpLo+j, tmpHi+j, dst+j, bufferLo, bufferHi,
|
||||
filterV, filterV+taps, taps, offset, m_w/*pitch*/, m_h/*dstlen*/);
|
||||
//SynthesisFilterSubsampHaar (tmpLo+j, tmpHi+j, dst+j, m_w, m_h);
|
||||
} else {
|
||||
//SynthesisFilter (tmpLo+j, tmpHi+j, dst+j, bufferLo, bufferHi, \
|
||||
filterV, filterV+taps, taps, offset, m_w/*pitch*/, m_h/*dstlen*/);
|
||||
//SynthesisFilter (tmpLo+j, tmpHi+j, dst+j, bufferLo, bufferHi,
|
||||
// filterV, filterV+taps, taps, offset, m_w/*pitch*/, m_h/*dstlen*/);
|
||||
SynthesisFilterHaar (tmpLo+j, tmpHi+j, dst+j, bufferLo, bufferHi, m_w, m_h);
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) {
|
||||
|
||||
TagDirectory *tagDir=ExifManager::parseTIFF(pFile, false);
|
||||
|
||||
Tag* tag = tagDir->getTag(TagCalibrationIlluminant1); iLightSource1 = (tag!=NULL ? tag->toInt(0,SHORT) : -1);
|
||||
tag = tagDir->getTag(TagCalibrationIlluminant2); iLightSource2 = (tag!=NULL ? tag->toInt(0,SHORT) : -1);
|
||||
Tag* tag = tagDir->getTag(TagCalibrationIlluminant1); iLightSource1 = (tag!=NULL ? tag->toInt(0,rtexif::SHORT) : -1);
|
||||
tag = tagDir->getTag(TagCalibrationIlluminant2); iLightSource2 = (tag!=NULL ? tag->toInt(0,rtexif::SHORT) : -1);
|
||||
|
||||
bool hasSecondHueSat = tagDir->getTag(TagProfileHueSatMapData2)!=NULL; // some profiles have two matrices, but just one huesat
|
||||
|
||||
@ -495,8 +495,8 @@ DCPStore* DCPStore::getInstance()
|
||||
static DCPStore* 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 DCPStore();
|
||||
@ -507,7 +507,7 @@ DCPStore* DCPStore::getInstance()
|
||||
|
||||
// Reads all profiles from the given profiles dir
|
||||
void DCPStore::init (Glib::ustring rtProfileDir) {
|
||||
Glib::Mutex::Lock lock(mtx);
|
||||
MyMutex::MyLock lock(mtx);
|
||||
|
||||
fileStdProfiles.clear();
|
||||
|
||||
@ -550,7 +550,7 @@ void DCPStore::init (Glib::ustring rtProfileDir) {
|
||||
}
|
||||
|
||||
DCPProfile* DCPStore::getProfile (Glib::ustring filename, bool isRTProfile) {
|
||||
Glib::Mutex::Lock lock(mtx);
|
||||
MyMutex::MyLock lock(mtx);
|
||||
|
||||
std::map<Glib::ustring, DCPProfile*>::iterator r = profileCache.find (filename);
|
||||
if (r!=profileCache.end()) return r->second;
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "imagefloat.h"
|
||||
#include "curves.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
#include <glibmm.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -65,7 +66,7 @@ namespace rtengine {
|
||||
};
|
||||
|
||||
class DCPStore {
|
||||
Glib::Mutex mtx;
|
||||
MyMutex mtx;
|
||||
|
||||
// these contain standard profiles from RT. keys are all in uppercase, file path is value
|
||||
std::map<Glib::ustring, Glib::ustring> fileStdProfiles;
|
||||
|
@ -1,4 +1,3 @@
|
||||
/*
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
@ -53,15 +52,15 @@ Crop::~Crop () {
|
||||
}
|
||||
|
||||
void Crop::setListener (DetailedCropListener* il) {
|
||||
// We can make reads in the IF, because the mProcessing lock is only needed for change
|
||||
if (cropImageListener!=il) {
|
||||
Glib::Mutex::Lock lock(cropMutex);
|
||||
cropImageListener = il;
|
||||
}
|
||||
}
|
||||
// We can make reads in the IF, because the mProcessing lock is only needed for change
|
||||
if (cropImageListener!=il) {
|
||||
MyMutex::MyLock lock(cropMutex);
|
||||
cropImageListener = il;
|
||||
}
|
||||
}
|
||||
|
||||
void Crop::update (int todo) {
|
||||
Glib::Mutex::Lock lock(cropMutex);
|
||||
MyMutex::MyLock lock(cropMutex);
|
||||
|
||||
ProcParams& params = parent->params;
|
||||
|
||||
@ -89,7 +88,7 @@ void Crop::update (int todo) {
|
||||
bool needstransform = parent->ipf.needsTransform();
|
||||
|
||||
if (todo & (M_INIT|M_LINDENOISE)) {
|
||||
Glib::Mutex::Lock lock(parent->minit); // Also used in improccoord
|
||||
MyMutex::MyLock lock(parent->minit); // Also used in improccoord
|
||||
|
||||
int tr = TR_NONE;
|
||||
if (params.coarse.rotate==90) tr |= TR_R90;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "image16.h"
|
||||
#include "imagesource.h"
|
||||
#include "procevents.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@ -36,11 +37,11 @@ class ImProcCoordinator;
|
||||
class Crop : public DetailedCrop {
|
||||
|
||||
protected:
|
||||
Imagefloat* origCrop, *baseCrop;
|
||||
Imagefloat* origCrop, *baseCrop;
|
||||
Imagefloat* *resizeCrop, *transCrop;
|
||||
LabImage *laboCrop, *labnCrop;
|
||||
Image8 *cropImg; // permanently allocated in RAM and only renewed on size changes
|
||||
CieImage *cieCrop;
|
||||
CieImage *cieCrop;
|
||||
float** cbuffer;
|
||||
float * cbuf_real;
|
||||
SHMap* cshmap;
|
||||
@ -51,28 +52,27 @@ class Crop : public DetailedCrop {
|
||||
int trafx, trafy, trafw, trafh; // the size and position to get from the imagesource that is transformed to the requested crop area
|
||||
int rqcropx, rqcropy, rqcropw, rqcroph; // size of the requested detail crop image (the image might be smaller) (without border)
|
||||
int borderRequested, upperBorder, leftBorder;
|
||||
|
||||
|
||||
bool cropAllocated;
|
||||
DetailedCropListener* cropImageListener;
|
||||
|
||||
Glib::Mutex cropMutex;
|
||||
|
||||
MyMutex cropMutex;
|
||||
ImProcCoordinator* parent;
|
||||
|
||||
bool setCropSizes (int cx, int cy, int cw, int ch, int skip, bool internal);
|
||||
void freeAll ();
|
||||
|
||||
|
||||
public:
|
||||
Crop (ImProcCoordinator* parent);
|
||||
virtual ~Crop ();
|
||||
Crop (ImProcCoordinator* parent);
|
||||
virtual ~Crop ();
|
||||
|
||||
bool hasListener () { return cropImageListener; }
|
||||
void update (int todo);
|
||||
void setWindow (int cx, int cy, int cw, int ch, int skip) { setCropSizes (cx, cy, cw, ch, skip, false); }
|
||||
|
||||
bool tryUpdate (); // First try, only make fullUpdate if this returns false
|
||||
void fullUpdate (); // called via thread
|
||||
|
||||
|
||||
bool tryUpdate (); // First try, only make fullUpdate if this returns false
|
||||
void fullUpdate (); // called via thread
|
||||
|
||||
void setListener (DetailedCropListener* il);
|
||||
void destroy () {}
|
||||
int get_skip () { return skip;}
|
||||
|
@ -16,12 +16,12 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "iccstore.h"
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include "iccstore.h"
|
||||
#include "iccmatrices.h"
|
||||
#include <glib/gstdio.h>
|
||||
#include "safegtk.h"
|
||||
@ -62,7 +62,7 @@ std::vector<std::string> getWorkingProfiles () {
|
||||
|
||||
std::vector<std::string> ICCStore::getOutputProfiles () {
|
||||
|
||||
Glib::Mutex::Lock lock(mutex_);
|
||||
MyMutex::MyLock lock(mutex_);
|
||||
|
||||
std::vector<std::string> res;
|
||||
for (std::map<std::string, cmsHPROFILE>::iterator i=fileProfiles.begin(); i!=fileProfiles.end(); i++){
|
||||
@ -83,8 +83,8 @@ ICCStore::getInstance(void)
|
||||
static ICCStore* 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 ICCStore();
|
||||
@ -153,7 +153,7 @@ cmsHPROFILE ICCStore::workingSpaceGamma (Glib::ustring name) {
|
||||
|
||||
cmsHPROFILE ICCStore::getProfile (Glib::ustring name) {
|
||||
|
||||
Glib::Mutex::Lock lock(mutex_);
|
||||
MyMutex::MyLock lock(mutex_);
|
||||
|
||||
std::map<std::string, cmsHPROFILE>::iterator r = fileProfiles.find (name);
|
||||
if (r!=fileProfiles.end())
|
||||
@ -176,7 +176,7 @@ cmsHPROFILE ICCStore::getProfile (Glib::ustring name) {
|
||||
|
||||
cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) {
|
||||
|
||||
Glib::Mutex::Lock lock(mutex_);
|
||||
MyMutex::MyLock lock(mutex_);
|
||||
|
||||
|
||||
std::map<std::string, cmsHPROFILE>::iterator r = fileStdProfiles.find (name.uppercase());
|
||||
@ -187,7 +187,7 @@ cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) {
|
||||
|
||||
ProfileContent ICCStore::getContent (Glib::ustring name) {
|
||||
|
||||
Glib::Mutex::Lock lock(mutex_);
|
||||
MyMutex::MyLock lock(mutex_);
|
||||
|
||||
return fileProfileContents[name];
|
||||
}
|
||||
@ -195,7 +195,7 @@ ProfileContent ICCStore::getContent (Glib::ustring name) {
|
||||
// Reads all profiles from the given profiles dir
|
||||
void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring rtICCDir) {
|
||||
|
||||
Glib::Mutex::Lock lock(mutex_);
|
||||
MyMutex::MyLock lock(mutex_);
|
||||
|
||||
//
|
||||
fileProfiles.clear();
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <glibmm.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@ -61,7 +62,7 @@ class ICCStore {
|
||||
cmsHPROFILE xyz;
|
||||
cmsHPROFILE srgb;
|
||||
|
||||
Glib::Mutex mutex_;
|
||||
MyMutex mutex_;
|
||||
|
||||
ICCStore ();
|
||||
void loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map<std::string, cmsHPROFILE>& resultProfiles, std::map<std::string, ProfileContent> &resultProfileContents);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <glib/gstdio.h>
|
||||
#include <glibmm.h>
|
||||
#include <vector>
|
||||
#include "../rtgui/threadutils.h"
|
||||
#include "rt_math.h"
|
||||
#include "alignedbuffer.h"
|
||||
#include "imagedimensions.h"
|
||||
@ -1021,7 +1022,7 @@ namespace rtengine {
|
||||
virtual ~IImage() {}
|
||||
/** Returns a mutex that can is useful in many situations. No image operations shuold be performed without locking this mutex.
|
||||
* @return The mutex */
|
||||
virtual Glib::Mutex& getMutex ()=0;
|
||||
virtual MyMutex& getMutex ()=0;
|
||||
virtual cmsHPROFILE getProfile ()=0;
|
||||
/** Returns the bits per pixel of the image.
|
||||
* @return The bits per pixel of the image */
|
||||
|
@ -51,7 +51,7 @@ class Image16 : public IImage16, public ImageIO {
|
||||
virtual void setScanline (int row, unsigned char* buffer, int bps, float *minValue=NULL, float *maxValue=NULL);
|
||||
|
||||
// functions inherited from IImage16:
|
||||
virtual Glib::Mutex& getMutex () { return mutex (); }
|
||||
virtual MyMutex& getMutex () { return mutex (); }
|
||||
virtual cmsHPROFILE getProfile () { return getEmbeddedProfile (); }
|
||||
virtual int getBitsPerPixel () { return 8*sizeof(unsigned short); }
|
||||
virtual int saveToFile (Glib::ustring fname) { return save (fname); }
|
||||
|
@ -46,7 +46,7 @@ class Image8 : public IImage8, public ImageIO {
|
||||
virtual void setScanline (int row, unsigned char* buffer, int bps, float *minValue=NULL, float *maxValue=NULL);
|
||||
|
||||
// functions inherited from IImage*:
|
||||
virtual Glib::Mutex& getMutex () { return mutex (); }
|
||||
virtual MyMutex& getMutex () { return mutex (); }
|
||||
virtual cmsHPROFILE getProfile () { return getEmbeddedProfile (); }
|
||||
virtual int getBitsPerPixel () { return 8*sizeof(unsigned char); }
|
||||
virtual int saveToFile (Glib::ustring fname) { return save (fname); }
|
||||
|
@ -55,7 +55,7 @@ class Imagefloat : public IImagefloat, public ImageIO {
|
||||
virtual void setScanline (int row, unsigned char* buffer, int bps, float *minValue=NULL, float *maxValue=NULL);
|
||||
|
||||
// functions inherited from IImagefloat:
|
||||
virtual Glib::Mutex& getMutex () { return mutex (); }
|
||||
virtual MyMutex& getMutex () { return mutex (); }
|
||||
virtual cmsHPROFILE getProfile () { return getEmbeddedProfile (); }
|
||||
virtual int getBitsPerPixel () { return 8*sizeof(float); }
|
||||
virtual int saveToFile (Glib::ustring fname) { return save (fname); }
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "../rtexif/rtexif.h"
|
||||
#include "imagedimensions.h"
|
||||
#include "iimage.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@ -69,7 +70,7 @@ class ImageIO : virtual public ImageDatas {
|
||||
procparams::ExifPairs exifChange;
|
||||
IptcData* iptc;
|
||||
const rtexif::TagDirectory* exifRoot;
|
||||
Glib::Mutex imutex;
|
||||
MyMutex imutex;
|
||||
IIOSampleFormat sampleFormat;
|
||||
IIOSampleArrangement sampleArrangement;
|
||||
|
||||
@ -122,7 +123,7 @@ class ImageIO : virtual public ImageDatas {
|
||||
void setMetadata (const rtexif::TagDirectory* eroot);
|
||||
void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc);
|
||||
void setOutputProfile (char* pdata, int plen);
|
||||
Glib::Mutex& mutex () { return imutex; }
|
||||
MyMutex& mutex () { return imutex; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
||||
|
||||
|
||||
if (todo & (M_INIT|M_LINDENOISE)) {
|
||||
Glib::Mutex::Lock lock(minit); // Also used in crop window
|
||||
MyMutex::MyLock lock(minit); // Also used in crop window
|
||||
|
||||
imgsrc->HLRecovery_Global( params.hlrecovery ); // this handles Color HLRecovery
|
||||
|
||||
@ -623,7 +623,7 @@ bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal) {
|
||||
|
||||
if (imgsrc) {
|
||||
if (lastAwbEqual != equal) {
|
||||
Glib::Mutex::Lock lock(minit); // Also used in crop window
|
||||
MyMutex::MyLock lock(minit); // Also used in crop window
|
||||
double rm, gm, bm;
|
||||
imgsrc->getAutoWBMultipliers(rm, gm, bm);
|
||||
if (rm != -1) {
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "procevents.h"
|
||||
#include "dcrop.h"
|
||||
#include "LUT.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@ -123,7 +124,7 @@ class ImProcCoordinator : public StagedImageProcessor {
|
||||
|
||||
bool resultValid;
|
||||
|
||||
Glib::Mutex minit;
|
||||
MyMutex minit;
|
||||
|
||||
void progress (Glib::ustring str, int pr);
|
||||
void reallocAll ();
|
||||
@ -131,13 +132,13 @@ class ImProcCoordinator : public StagedImageProcessor {
|
||||
void setScale (int prevscale);
|
||||
void updatePreviewImage (int todo, Crop* cropCall= NULL);
|
||||
|
||||
Glib::Mutex mProcessing;
|
||||
MyMutex mProcessing;
|
||||
ProcParams params;
|
||||
|
||||
// members of the updater:
|
||||
Glib::Thread* thread;
|
||||
Glib::Mutex updaterThreadStart;
|
||||
Glib::Mutex paramsUpdateMutex;
|
||||
MyMutex updaterThreadStart;
|
||||
MyMutex paramsUpdateMutex;
|
||||
int changeSinceLast;
|
||||
bool updaterRunning;
|
||||
ProcParams nextParams;
|
||||
|
@ -25,12 +25,13 @@
|
||||
#include "ffmanager.h"
|
||||
#include "rtthumbnail.h"
|
||||
#include "../rtgui/profilestore.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
const Settings* settings;
|
||||
|
||||
Glib::Mutex* lcmsMutex = NULL;
|
||||
MyMutex* lcmsMutex = NULL;
|
||||
|
||||
int init (const Settings* s, Glib::ustring baseDir) {
|
||||
|
||||
@ -46,7 +47,7 @@ int init (const Settings* s, Glib::ustring baseDir) {
|
||||
ImProcFunctions::initCache ();
|
||||
Thumbnail::initGamma ();
|
||||
delete lcmsMutex;
|
||||
lcmsMutex = new Glib::Mutex;
|
||||
lcmsMutex = new MyMutex;
|
||||
dfm.init( s->darkFramesPath );
|
||||
ffm.init( s->flatFieldsPath );
|
||||
return 0;
|
||||
|
@ -629,8 +629,8 @@ LCPStore* LCPStore::getInstance()
|
||||
static LCPStore* 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 LCPStore();
|
||||
@ -642,7 +642,7 @@ LCPStore* LCPStore::getInstance()
|
||||
LCPProfile* LCPStore::getProfile (Glib::ustring filename) {
|
||||
if (filename.length()==0 || !isValidLCPFileName(filename)) return NULL;
|
||||
|
||||
Glib::Mutex::Lock lock(mtx);
|
||||
MyMutex::MyLock lock(mtx);
|
||||
|
||||
std::map<Glib::ustring, LCPProfile*>::iterator r = profileCache.find (filename);
|
||||
if (r!=profileCache.end()) return r->second;
|
||||
@ -676,4 +676,4 @@ Glib::ustring LCPStore::getDefaultCommonDirectory() const {
|
||||
// TODO: Add Mac paths here
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define _LCP_
|
||||
|
||||
#include "imagefloat.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
#include <glibmm.h>
|
||||
#include <map>
|
||||
#include <list>
|
||||
@ -92,7 +93,7 @@ namespace rtengine {
|
||||
};
|
||||
|
||||
class LCPStore {
|
||||
Glib::Mutex mtx;
|
||||
MyMutex mtx;
|
||||
|
||||
// Maps file name to profile as cache
|
||||
std::map<Glib::ustring, LCPProfile*> profileCache;
|
||||
|
@ -205,7 +205,7 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s
|
||||
|
||||
void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw )
|
||||
{
|
||||
Glib::Mutex::Lock lock(getImageMutex);
|
||||
MyMutex::MyLock lock(getImageMutex);
|
||||
|
||||
tran = defTransform (tran);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "color.h"
|
||||
#include "iimage.h"
|
||||
#include "../rtgui/cacheimagedata.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
#define HR_SCALE 2
|
||||
|
||||
@ -68,7 +69,7 @@ class RawImageSource : public ImageSource {
|
||||
static void colorSpaceConversion (Imagefloat* im, ColorManagementParams &cmp, float rawWhitePoint, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName);
|
||||
|
||||
protected:
|
||||
Glib::Mutex getImageMutex; // locks getImage
|
||||
MyMutex getImageMutex; // locks getImage
|
||||
|
||||
int W, H;
|
||||
ColorTemp wb;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "rawmetadatalocation.h"
|
||||
#include "iimage.h"
|
||||
#include "utils.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
#include "settings.h"
|
||||
#include "LUT.h"
|
||||
/**
|
||||
@ -417,7 +418,7 @@ namespace rtengine {
|
||||
void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData);
|
||||
|
||||
|
||||
extern Glib::Mutex* lcmsMutex;
|
||||
extern MyMutex* lcmsMutex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
#include "rtengine.h"
|
||||
#include "rtthumbnail.h"
|
||||
#include "../rtgui/options.h"
|
||||
#include "image8.h"
|
||||
#include <lcms2.h>
|
||||
#include "curves.h"
|
||||
@ -38,6 +39,8 @@
|
||||
#include "jpeg.h"
|
||||
#include "../rtgui/ppversion.h"
|
||||
|
||||
extern Options options;
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq) {
|
||||
@ -1280,7 +1283,7 @@ bool Thumbnail::readData (const Glib::ustring& fname) {
|
||||
SafeKeyFile keyFile;
|
||||
|
||||
try {
|
||||
Glib::Mutex::Lock thmbLock(thumbMutex);
|
||||
MyMutex::MyLock thmbLock(thumbMutex);
|
||||
if (!keyFile.load_from_file (fname))
|
||||
return false;
|
||||
|
||||
@ -1309,7 +1312,14 @@ bool Thumbnail::readData (const Glib::ustring& fname) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Glib::Error &err) {}
|
||||
catch (Glib::Error &err) {
|
||||
if (options.rtSettings.verbose)
|
||||
printf("Thumbnail::readData / 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("Thumbnail::readData / Unknown exception while trying to load \"%s\"!\n", fname.c_str());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1318,12 +1328,20 @@ bool Thumbnail::writeData (const Glib::ustring& fname) {
|
||||
|
||||
SafeKeyFile keyFile;
|
||||
|
||||
Glib::Mutex::Lock thmbLock(thumbMutex);
|
||||
MyMutex::MyLock thmbLock(thumbMutex);
|
||||
|
||||
try {
|
||||
if( safe_file_test(fname,Glib::FILE_TEST_EXISTS) )
|
||||
keyFile.load_from_file (fname);
|
||||
} catch (...) {}
|
||||
if( safe_file_test(fname,Glib::FILE_TEST_EXISTS) )
|
||||
keyFile.load_from_file (fname);
|
||||
}
|
||||
catch (Glib::Error &err) {
|
||||
if (options.rtSettings.verbose)
|
||||
printf("Thumbnail::writeData / 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("Thumbnail::writeData / Unknown exception while trying to save \"%s\"!\n", fname.c_str());
|
||||
}
|
||||
|
||||
keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed);
|
||||
keyFile.set_double ("LiveThumbData", "CamWBGreen", camwbGreen);
|
||||
@ -1343,8 +1361,11 @@ bool Thumbnail::writeData (const Glib::ustring& fname) {
|
||||
keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm);
|
||||
|
||||
FILE *f = safe_g_fopen (fname, "wt");
|
||||
if (!f)
|
||||
if (!f) {
|
||||
if (options.rtSettings.verbose)
|
||||
printf("Thumbnail::writeData / Error: unable to open file \"\" with write access!\n", fname.c_str());
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
fprintf (f, "%s", keyFile.to_data().c_str());
|
||||
fclose (f);
|
||||
|
@ -26,12 +26,13 @@
|
||||
#include "image8.h"
|
||||
#include "image16.h"
|
||||
#include "imagefloat.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
class Thumbnail {
|
||||
|
||||
Glib::Mutex thumbMutex;
|
||||
MyMutex thumbMutex;
|
||||
|
||||
cmsHPROFILE camProfile;
|
||||
double iColorMatrix[3][3];
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user