summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 16:47:21 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 16:47:21 +0200
commitca64896d49b70fc0ffec711a079167c972fe635e (patch)
tree0059c36336378c886b750860aa5343b847c3609a /library
parent1.3 (diff)
downloadFreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.tar.gz
FreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.tar.bz2
FreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.zip
1.4
Diffstat (limited to 'library')
-rw-r--r--library/CustomGrid.cpp2
-rw-r--r--library/GMP/include/gmp.h9
-rw-r--r--library/GMP/include/gmpxx.h98
-rw-r--r--library/GMP/lib/libgmp.abin392834 -> 393164 bytes
-rw-r--r--library/GMP/lib/libgmp.la2
-rw-r--r--library/GMP/lib/libgmpxx.abin24784 -> 24784 bytes
-rw-r--r--library/GMP/lib/libgmpxx.la2
-rw-r--r--library/globalFunctions.cpp48
-rw-r--r--library/globalFunctions.h6
-rw-r--r--library/multithreading.cpp148
-rw-r--r--library/multithreading.h64
11 files changed, 316 insertions, 63 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index 876ad8f9..eea2a0d4 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -166,7 +166,7 @@ public:
{
if (currentUI_ViewPtr->size() > unsigned(row))
{
- if ((*currentUI_ViewPtr)[row].cmpResult == ConstFilteredOut)
+ if ((*currentUI_ViewPtr)[row].cmpResult == constFilteredOut)
return true;
}
}
diff --git a/library/GMP/include/gmp.h b/library/GMP/include/gmp.h
index 1268c74d..fa86f2dc 100644
--- a/library/GMP/include/gmp.h
+++ b/library/GMP/include/gmp.h
@@ -421,7 +421,7 @@ typedef __mpq_struct *mpq_ptr;
GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
inline semantics, unless -fgnu89-inline is used. */
#ifdef __GNUC__
-#ifdef __GNUC_STDC_INLINE__
+#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__))
#else
#define __GMP_EXTERN_INLINE extern __inline__
@@ -518,6 +518,7 @@ typedef __mpq_struct *mpq_ptr;
#if defined (__cplusplus)
extern "C"
{
+#include <cstdio>
#ifdef _GMP_H_HAVE_FILE
using std::FILE;
#endif
@@ -2173,10 +2174,14 @@ enum
GMP_ERROR_INVALID_ARGUMENT = 8
};
+/* Define CC and CFLAGS which were used to build this version of GMP */
+#define __GMP_CC "gcc"
+#define __GMP_CFLAGS "-m32 -O2 -fomit-frame-pointer -mtune=k8 -march=k8 -mno-cygwin"
+
/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */
#define __GNU_MP_VERSION 4
#define __GNU_MP_VERSION_MINOR 2
-#define __GNU_MP_VERSION_PATCHLEVEL 2
+#define __GNU_MP_VERSION_PATCHLEVEL 3
#define __GMP_H__
#endif /* __GMP_H__ */
diff --git a/library/GMP/include/gmpxx.h b/library/GMP/include/gmpxx.h
index 76a72678..6472707a 100644
--- a/library/GMP/include/gmpxx.h
+++ b/library/GMP/include/gmpxx.h
@@ -1,6 +1,6 @@
/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*-
-Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+Copyright 2001, 2002, 2003, 2006, 2008 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -37,6 +37,7 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
#include <cstring> /* for strlen */
#include <string>
#include <stdexcept>
+#include <cfloat>
#include <gmp.h>
@@ -655,22 +656,83 @@ struct __gmp_binary_modulus
}
};
+// Max allocations for plain types when converted to mpz_t
+// FIXME: how do we get the proper max "double" exponent?
+#define __GMP_DBL_LIMBS (2 + DBL_MAX_EXP / GMP_NUMB_BITS)
+#define __GMP_ULI_LIMBS (1 + (8 * sizeof (long) - 1) / GMP_NUMB_BITS)
+
+#define __GMPXX_TMP_UI \
+ mpz_t temp; \
+ mp_limb_t limbs[__GMP_ULI_LIMBS]; \
+ temp->_mp_d = limbs; \
+ temp->_mp_alloc = __GMP_ULI_LIMBS; \
+ mpz_set_ui (temp, l)
+#define __GMPXX_TMP_SI \
+ mpz_t temp; \
+ mp_limb_t limbs[__GMP_ULI_LIMBS]; \
+ temp->_mp_d = limbs; \
+ temp->_mp_alloc = __GMP_ULI_LIMBS; \
+ mpz_set_si (temp, l)
+#define __GMPXX_TMP_D \
+ mpz_t temp; \
+ mp_limb_t limbs[__GMP_DBL_LIMBS]; \
+ temp->_mp_d = limbs; \
+ temp->_mp_alloc = __GMP_DBL_LIMBS; \
+ mpz_set_d (temp, d)
+
struct __gmp_binary_and
{
static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
{ mpz_and(z, w, v); }
+
+ static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
+ { __GMPXX_TMP_UI; mpz_and (z, w, temp); }
+ static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
+ { __GMPXX_TMP_UI; mpz_and (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
+ { __GMPXX_TMP_SI; mpz_and (z, w, temp); }
+ static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
+ { __GMPXX_TMP_SI; mpz_and (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, double d)
+ { __GMPXX_TMP_D; mpz_and (z, w, temp); }
+ static void eval(mpz_ptr z, double d, mpz_srcptr w)
+ { __GMPXX_TMP_D; mpz_and (z, w, temp); }
};
struct __gmp_binary_ior
{
static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
{ mpz_ior(z, w, v); }
+ static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
+ { __GMPXX_TMP_UI; mpz_ior (z, w, temp); }
+ static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
+ { __GMPXX_TMP_UI; mpz_ior (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
+ { __GMPXX_TMP_SI; mpz_ior (z, w, temp); }
+ static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
+ { __GMPXX_TMP_SI; mpz_ior (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, double d)
+ { __GMPXX_TMP_D; mpz_ior (z, w, temp); }
+ static void eval(mpz_ptr z, double d, mpz_srcptr w)
+ { __GMPXX_TMP_D; mpz_ior (z, w, temp); }
};
struct __gmp_binary_xor
{
static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v)
{ mpz_xor(z, w, v); }
+ static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
+ { __GMPXX_TMP_UI; mpz_xor (z, w, temp); }
+ static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w)
+ { __GMPXX_TMP_UI; mpz_xor (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, signed long int l)
+ { __GMPXX_TMP_SI; mpz_xor (z, w, temp); }
+ static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
+ { __GMPXX_TMP_SI; mpz_xor (z, w, temp); }
+ static void eval(mpz_ptr z, mpz_srcptr w, double d)
+ { __GMPXX_TMP_D; mpz_xor (z, w, temp); }
+ static void eval(mpz_ptr z, double d, mpz_srcptr w)
+ { __GMPXX_TMP_D; mpz_xor (z, w, temp); }
};
struct __gmp_binary_lshift
@@ -686,7 +748,7 @@ struct __gmp_binary_lshift
struct __gmp_binary_rshift
{
static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l)
- { mpz_tdiv_q_2exp(z, w, l); }
+ { mpz_fdiv_q_2exp(z, w, l); }
static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l)
{ mpq_div_2exp(q, r, l); }
static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l)
@@ -1291,13 +1353,17 @@ struct __gmp_rand_function
/* this is much the same as gmp_allocated_string in gmp-impl.h
since gmp-impl.h is not publicly available, I redefine it here
I use a different name to avoid possible clashes */
+
+extern "C" {
+ typedef void (*__gmp_freefunc_t) (void *, size_t);
+}
struct __gmp_alloc_cstring
{
char *str;
__gmp_alloc_cstring(char *s) { str = s; }
~__gmp_alloc_cstring()
{
- void (*freefunc) (void *, size_t);
+ __gmp_freefunc_t freefunc;
mp_get_memory_functions (NULL, NULL, &freefunc);
(*freefunc) (str, std::strlen(str)+1);
}
@@ -1616,9 +1682,9 @@ public:
__GMP_DECLARE_COMPOUND_OPERATOR(operator/=)
__GMP_DECLARE_COMPOUND_OPERATOR(operator%=)
- __GMPP_DECLARE_COMPOUND_OPERATOR(operator&=)
- __GMPP_DECLARE_COMPOUND_OPERATOR(operator|=)
- __GMPP_DECLARE_COMPOUND_OPERATOR(operator^=)
+ __GMP_DECLARE_COMPOUND_OPERATOR(operator&=)
+ __GMP_DECLARE_COMPOUND_OPERATOR(operator|=)
+ __GMP_DECLARE_COMPOUND_OPERATOR(operator^=)
__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=)
__GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=)
@@ -3006,9 +3072,6 @@ __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun)
#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
-#define __GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
-__GMPP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun)
-
#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \
__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun)
@@ -3109,9 +3172,9 @@ __GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies)
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides)
__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus)
-__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
-__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
-__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
+__GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and)
+__GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior)
+__GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor)
__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift)
__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift)
@@ -3269,7 +3332,6 @@ public:
#undef __GMP_DECLARE_INCREMENT_OPERATOR
#undef __GMPZQ_DEFINE_EXPR
-#undef __GMP_DEFINE_TERNARY_EXPR
#undef __GMP_DEFINE_UNARY_FUNCTION
#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION
@@ -3294,15 +3356,7 @@ public:
#undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION
#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION
-#undef __GMPP_DECLARE_COMPOUND_OPERATOR
-#undef __GMPN_DECLARE_COMPOUND_OPERATOR
-#undef __GMP_DECLARE_COMPOUND_OPERATOR
-
-#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI
-#undef __GMP_DECLARE_INCREMENT_OPERATOR
-
#undef __GMPZ_DEFINE_COMPOUND_OPERATOR
-#undef __GMPZZ_DEFINE_COMPOUND_OPERATOR
#undef __GMPZN_DEFINE_COMPOUND_OPERATOR
#undef __GMPZNN_DEFINE_COMPOUND_OPERATOR
#undef __GMPZNS_DEFINE_COMPOUND_OPERATOR
@@ -3319,8 +3373,6 @@ public:
#undef __GMPN_DEFINE_COMPOUND_OPERATOR
#undef __GMP_DEFINE_COMPOUND_OPERATOR
-#undef __GMPZ_DEFINE_COMPOUND_OPERATOR
-#undef __GMPZZ_DEFINE_COMPOUND_OPERATOR
#undef __GMPQ_DEFINE_COMPOUND_OPERATOR
#undef __GMPF_DEFINE_COMPOUND_OPERATOR
diff --git a/library/GMP/lib/libgmp.a b/library/GMP/lib/libgmp.a
index 041ee6c7..e53850ec 100644
--- a/library/GMP/lib/libgmp.a
+++ b/library/GMP/lib/libgmp.a
Binary files differ
diff --git a/library/GMP/lib/libgmp.la b/library/GMP/lib/libgmp.la
index ee6e9a74..a0e34d40 100644
--- a/library/GMP/lib/libgmp.la
+++ b/library/GMP/lib/libgmp.la
@@ -19,7 +19,7 @@ dependency_libs=''
# Version information for libgmp.
current=7
age=4
-revision=2
+revision=3
# Is this an already installed library?
installed=yes
diff --git a/library/GMP/lib/libgmpxx.a b/library/GMP/lib/libgmpxx.a
index 90ca1d40..3c4452d3 100644
--- a/library/GMP/lib/libgmpxx.a
+++ b/library/GMP/lib/libgmpxx.a
Binary files differ
diff --git a/library/GMP/lib/libgmpxx.la b/library/GMP/lib/libgmpxx.la
index e608eba7..dbb77dd0 100644
--- a/library/GMP/lib/libgmpxx.la
+++ b/library/GMP/lib/libgmpxx.la
@@ -19,7 +19,7 @@ dependency_libs=' /c/gmp/lib/libgmp.la'
# Version information for libgmpxx.
current=4
age=0
-revision=2
+revision=3
# Is this an already installed library?
installed=yes
diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp
index 70a5abaf..d0aad7a4 100644
--- a/library/globalFunctions.cpp
+++ b/library/globalFunctions.cpp
@@ -1,98 +1,86 @@
#include "globalFunctions.h"
-#include <wx/intl.h>
-
-#ifdef FFS_WIN
-const wxChar FileNameSeparator = '\\';
-#endif // FFS_WIN
-
-#ifdef FFS_LINUX
-const wxChar FileNameSeparator = '/';
-#endif // FFS_LINUX
-
-const wxChar* FloatingPointSeparator = _(".");
-const wxChar* NumberSeparator = _(",");
-
+#include "../ui/resources.h"
inline
-int GlobalFunctions::round(const double d)
+int globalFunctions::round(const double d)
{
return static_cast<int>(d<0?d-.5:d+.5);
}
inline
-int GlobalFunctions::abs(const int d)
+int globalFunctions::abs(const int d)
{
return(d<0?-d:d);
}
inline
-unsigned int GlobalFunctions::abs(const unsigned int d)
+unsigned int globalFunctions::abs(const unsigned int d)
{
return(d<0?-d:d);
}
inline
-float GlobalFunctions::abs(const float d)
+float globalFunctions::abs(const float d)
{
return(d<0?-d:d);
};
inline
-double GlobalFunctions::abs(const double d)
+double globalFunctions::abs(const double d)
{
return(d<0?-d:d);
}
-string GlobalFunctions::numberToString(const unsigned int number)
+string globalFunctions::numberToString(const unsigned int number)
{
char result[100];
sprintf( result, "%u", number);
return string(result);
}
-string GlobalFunctions::numberToString(const int number)
+string globalFunctions::numberToString(const int number)
{
char result[100];
sprintf( result, "%d", number);
return string(result);
}
-string GlobalFunctions::numberToString(const float number)
+string globalFunctions::numberToString(const float number)
{
char result[100];
sprintf( result, "%f", number);
return string(result);
}
-wxString GlobalFunctions::numberToWxString(const unsigned int number)
+wxString globalFunctions::numberToWxString(const unsigned int number)
{
return wxString::Format(wxT("%u"), number);
}
-wxString GlobalFunctions::numberToWxString(const int number)
+wxString globalFunctions::numberToWxString(const int number)
{
return wxString::Format(wxT("%i"), number);
}
-wxString GlobalFunctions::numberToWxString(const float number)
+wxString globalFunctions::numberToWxString(const float number)
{
return wxString::Format(wxT("%f"), number);
}
inline
-int GlobalFunctions::stringToInt(const string& number)
+int globalFunctions::stringToInt(const string& number)
{
return atoi(number.c_str());
}
inline
-double GlobalFunctions::stringToDouble(const string& number)
+double globalFunctions::stringToDouble(const string& number)
{
return atof(number.c_str());
}
inline
-int GlobalFunctions::wxStringToInt(const wxString& number)
+int globalFunctions::wxStringToInt(const wxString& number)
{
long result = 0;
if (number.ToLong(&result))
@@ -102,7 +90,7 @@ int GlobalFunctions::wxStringToInt(const wxString& number)
}
inline
-double GlobalFunctions::wxStringToDouble(const wxString& number)
+double globalFunctions::wxStringToDouble(const wxString& number)
{
double result = 0;
if (number.ToDouble(&result))
@@ -111,9 +99,9 @@ double GlobalFunctions::wxStringToDouble(const wxString& number)
throw std::runtime_error("Error when converting number to double");
}
-wxString& GlobalFunctions::includeNumberSeparator(wxString& number)
+wxString& globalFunctions::includeNumberSeparator(wxString& number)
{
for (int i = number.size() - 3; i > 0; i-= 3)
- number.insert(i, NumberSeparator);
+ number.insert(i, GlobalResources::numberSeparator);
return number;
}
diff --git a/library/globalFunctions.h b/library/globalFunctions.h
index b766a097..5fe576e1 100644
--- a/library/globalFunctions.h
+++ b/library/globalFunctions.h
@@ -8,11 +8,7 @@
using namespace std;
-extern const wxChar FileNameSeparator;
-extern const wxChar* FloatingPointSeparator;
-extern const wxChar* NumberSeparator;
-
-namespace GlobalFunctions
+namespace globalFunctions
{
int round(double d); //little rounding function
diff --git a/library/multithreading.cpp b/library/multithreading.cpp
new file mode 100644
index 00000000..dd96eaf4
--- /dev/null
+++ b/library/multithreading.cpp
@@ -0,0 +1,148 @@
+#include "multithreading.h"
+#include <wx/utils.h>
+//#include "windows.h"
+//MessageBox(0, "hi", "", 0);
+
+/*choreography:
+
+ ------------- ---------------
+ |main thread| |worker thread|
+ ------------- ---------------
+
+1. Instantiation (Constructor)
+-------------------------------
+ create thread
+ enter waiting state
+2. waitUntilReady
+-------------------------------
+ wait until thread is ready
+
+3. Call execAndUpdate
+-------------------------------
+ send signal to start
+ start processing
+ update UI while thread works
+ finish processing
+ wait until main thread is ready to receive signal
+ receive signal
+ enter waiting state
+4. Termination (Destructor)
+-------------------------------
+ wait until thread is in wait state
+ set exit flag
+ signal thread to continue (and exit)
+*/
+class WorkerThread : public wxThread
+{
+public:
+ WorkerThread(UpdateWhileExecuting* handler) :
+ readyToBeginProcessing(),
+ beginProcessing(readyToBeginProcessing),
+ threadIsInitialized(false),
+ threadExitIsRequested(false),
+ threadHandler(handler)
+ { }
+
+ ~WorkerThread() {}
+
+ ExitCode Entry()
+ {
+ readyToBeginProcessing.Lock(); //this lock needs to be called IN the thread => calling it from constructor(Main thread) would be useless
+ sharedData.Enter();
+ threadIsInitialized = true;
+ sharedData.Leave();
+
+ while (true)
+ {
+ beginProcessing.Wait();
+
+ //no mutex needed in this context
+ if (threadExitIsRequested)
+ return 0;
+
+ //actual (long running) work is done in this method
+ threadHandler->longRunner();
+
+ threadHandler->readyToReceiveResult.Lock();
+ threadHandler->receivingResult.Signal();
+ threadHandler->readyToReceiveResult.Unlock();
+ }
+
+ return 0;
+ }
+
+
+ wxMutex readyToBeginProcessing;
+ wxCondition beginProcessing;
+
+ //shared data
+ wxCriticalSection sharedData;
+ bool threadIsInitialized;
+ bool threadExitIsRequested;
+
+
+private:
+ UpdateWhileExecuting* threadHandler;
+};
+
+
+UpdateWhileExecuting::UpdateWhileExecuting() :
+ readyToReceiveResult(),
+ receivingResult(readyToReceiveResult)
+{
+ //mutex needs to be initially locked for condition receivingResult to work properly
+ readyToReceiveResult.Lock();
+
+
+ theWorkerThread = new WorkerThread(this);
+
+ theWorkerThread->Create();
+ theWorkerThread->Run();
+
+ //wait until the thread has locked readyToBeginProcessing
+ bool threadInitialized = false;
+ while (!threadInitialized)
+ {
+ theWorkerThread->sharedData.Enter();
+ threadInitialized = theWorkerThread->threadIsInitialized;
+ theWorkerThread->sharedData.Leave();
+ wxMilliSleep(5);
+ } //-> it's not nice, but works and is no issue
+}
+
+
+UpdateWhileExecuting::~UpdateWhileExecuting()
+{
+ //wait until thread is ready, then start and exit immediately
+ readyToReceiveResult.Unlock(); //avoid possible deadlock, when thread might be waiting to send the signal
+
+ theWorkerThread->readyToBeginProcessing.Lock();
+ //set flag to exit thread
+ theWorkerThread->threadExitIsRequested = true;
+ theWorkerThread->beginProcessing.Signal();
+
+ theWorkerThread->readyToBeginProcessing.Unlock();
+
+ //theWorkerThread deletes itself!
+}
+
+
+void UpdateWhileExecuting::waitUntilReady()
+{
+ readyToReceiveResult.Unlock(); //avoid possible deadlock, when thread might be waiting to send the signal (if abort was pressed)
+
+ theWorkerThread->readyToBeginProcessing.Lock();
+}
+// /|\ \|/ must be called directly after each other
+
+void UpdateWhileExecuting::execAndUpdate(StatusUpdater* statusUpdater)
+{
+ readyToReceiveResult.Lock();
+
+ theWorkerThread->beginProcessing.Signal();
+ theWorkerThread->readyToBeginProcessing.Unlock();
+
+ while (receivingResult.WaitTimeout(uiUpdateInterval) == wxCOND_TIMEOUT)
+ statusUpdater->triggerUI_Refresh(); //ATTENTION: Exception "AbortThisProcess" may be thrown here!!!
+}
+
diff --git a/library/multithreading.h b/library/multithreading.h
new file mode 100644
index 00000000..8466bb01
--- /dev/null
+++ b/library/multithreading.h
@@ -0,0 +1,64 @@
+#ifndef MULTITHREADING_H_INCLUDED
+#define MULTITHREADING_H_INCLUDED
+
+#include <wx/string.h>
+#include <wx/thread.h>
+
+//interface for status updates (can be implemented by UI or commandline)
+//overwrite virtual methods for respective functionality
+class StatusUpdater
+{
+public:
+ StatusUpdater() : abortionRequested(false) {}
+ virtual ~StatusUpdater() {}
+
+ //these four methods have to be implemented in the derived classes to handle error and status information
+ virtual void updateStatusText(const wxString& text) = 0;
+ virtual void initNewProcess(int objectsTotal, double dataTotal, int processID) = 0; //informs about the total amount of data that will be processed from now on
+ virtual void updateProcessedData(int objectsProcessed, double dataProcessed) = 0; //called periodically after data was processed
+ virtual int reportError(const wxString& text) = 0;
+
+ //this method is triggered repeatedly and can be used to refresh the ui by dispatching pending events
+ virtual void triggerUI_Refresh() {}
+
+ void requestAbortion() //opportunity to abort must be implemented in the three virtual status and error methods (for example in triggerUI_Refresh())
+ { //currently used by the UI status information screen, when button "Abort is pressed"
+ abortionRequested = true;
+ }
+ static const int continueNext = -1;
+ static const int retry = -2;
+
+protected:
+ bool abortionRequested;
+};
+
+
+const int uiUpdateInterval = 100; //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss
+
+class WorkerThread;
+
+
+//class handling execution of a method while updating the UI
+class UpdateWhileExecuting
+{
+ friend class WorkerThread;
+
+public:
+ UpdateWhileExecuting();
+ virtual ~UpdateWhileExecuting();
+
+ void waitUntilReady();
+ void execAndUpdate(StatusUpdater* statusUpdater);
+
+
+private:
+ //implement a longrunning method without dependencies (e.g. copy file function) returning "true" on success
+ virtual void longRunner() = 0;
+
+ WorkerThread* theWorkerThread;
+
+ wxMutex readyToReceiveResult;
+ wxCondition receivingResult;
+};
+
+#endif // MULTITHREADING_H_INCLUDED
bgstack15