diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:47:21 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:47:21 +0200 |
commit | ca64896d49b70fc0ffec711a079167c972fe635e (patch) | |
tree | 0059c36336378c886b750860aa5343b847c3609a /library | |
parent | 1.3 (diff) | |
download | FreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.tar.gz FreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.tar.bz2 FreeFileSync-ca64896d49b70fc0ffec711a079167c972fe635e.zip |
1.4
Diffstat (limited to 'library')
-rw-r--r-- | library/CustomGrid.cpp | 2 | ||||
-rw-r--r-- | library/GMP/include/gmp.h | 9 | ||||
-rw-r--r-- | library/GMP/include/gmpxx.h | 98 | ||||
-rw-r--r-- | library/GMP/lib/libgmp.a | bin | 392834 -> 393164 bytes | |||
-rw-r--r-- | library/GMP/lib/libgmp.la | 2 | ||||
-rw-r--r-- | library/GMP/lib/libgmpxx.a | bin | 24784 -> 24784 bytes | |||
-rw-r--r-- | library/GMP/lib/libgmpxx.la | 2 | ||||
-rw-r--r-- | library/globalFunctions.cpp | 48 | ||||
-rw-r--r-- | library/globalFunctions.h | 6 | ||||
-rw-r--r-- | library/multithreading.cpp | 148 | ||||
-rw-r--r-- | library/multithreading.h | 64 |
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 Binary files differindex 041ee6c7..e53850ec 100644 --- a/library/GMP/lib/libgmp.a +++ b/library/GMP/lib/libgmp.a 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 Binary files differindex 90ca1d40..3c4452d3 100644 --- a/library/GMP/lib/libgmpxx.a +++ b/library/GMP/lib/libgmpxx.a 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 |