diff --git a/uppsrc/Core/App.cpp b/uppsrc/Core/App.cpp index 28abb8920..e1bb6f64f 100644 --- a/uppsrc/Core/App.cpp +++ b/uppsrc/Core/App.cpp @@ -431,11 +431,7 @@ void AppInit__(int argc, const char **argv) void AppExit__() { -#ifdef _MULTITHREADED -#ifndef COWORK2 Thread::ShutdownThreads(); -#endif -#endif sMainRunning = false; #ifdef PLATFORM_POSIX MemoryIgnoreLeaksBegin(); // Qt leaks on app exit... diff --git a/uppsrc/Core/Atomic.h b/uppsrc/Core/Atomic.h index 9578b2ef9..25909dd35 100644 --- a/uppsrc/Core/Atomic.h +++ b/uppsrc/Core/Atomic.h @@ -1,15 +1,4 @@ -#ifdef _MULTITHREADED - typedef std::atomic Atomic; inline int AtomicInc(volatile Atomic& t) { return ++t; } inline int AtomicDec(volatile Atomic& t) { return --t; } - -#else - -typedef int Atomic; - -inline int AtomicInc(volatile Atomic& t) { ++t; return t; } -inline int AtomicDec(volatile Atomic& t) { --t; return t; } - -#endif diff --git a/uppsrc/Core/CoWork.cpp b/uppsrc/Core/CoWork.cpp index 1c3ceb3fd..b9dff56e6 100644 --- a/uppsrc/Core/CoWork.cpp +++ b/uppsrc/Core/CoWork.cpp @@ -2,8 +2,6 @@ namespace Upp { -#ifdef _MULTITHREADED - #define LLOG(x) // RLOG(x) #define LDUMP(x) // DDUMP(x) @@ -382,6 +380,4 @@ CoWork::~CoWork() noexcept(false) LLOG("~CoWork " << FormatIntHex(this)); } -#endif - } diff --git a/uppsrc/Core/CoWork.h b/uppsrc/Core/CoWork.h index b6cdfabd1..56b2450ef 100644 --- a/uppsrc/Core/CoWork.h +++ b/uppsrc/Core/CoWork.h @@ -1,5 +1,3 @@ -#ifdef _MULTITHREADED - class CoWork : NoCopy { struct MJob : Moveable, Link { Function fn; @@ -223,21 +221,3 @@ Async(Function&& f, Args&&... args) h.Do(f, args...); return pick(h); } - -#else - -class CoWork : NoCopy { -public: - void Do(Event<> cb) { cb(); } - CoWork& operator&(Event<> cb) { cb(); return *this; } - void Finish() {} - bool IsFinished() { return true; } - - static void FinLock() {} - - static bool IsWorker() { return false; } - static void StartPool(int n) {} - static void ShutdownPool() {} -}; - -#endif diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index db185c00a..19b36c7a7 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -7,12 +7,10 @@ #define flagMT // MT is now always on #endif -#if defined(flagMT) - #define _MULTITHREADED - #define MULTITHREADED - #ifdef flagDLL - #define flagUSEMALLOC - #endif +#define _MULTITHREADED +#define MULTITHREADED +#ifdef flagDLL + #define flagUSEMALLOC #endif #ifdef flagDLL diff --git a/uppsrc/Core/SSL/InitExit.cpp b/uppsrc/Core/SSL/InitExit.cpp index b823614d6..d4788939b 100644 --- a/uppsrc/Core/SSL/InitExit.cpp +++ b/uppsrc/Core/SSL/InitExit.cpp @@ -96,7 +96,7 @@ EXITBLOCK ERR_free_strings(); } -#if defined(_MULTITHREADED) && OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L static thread_local bool sThreadInit; static thread_local void (*sPrevExit)(); diff --git a/uppsrc/Core/TimeDate.cpp b/uppsrc/Core/TimeDate.cpp index f45408812..3289f2349 100644 --- a/uppsrc/Core/TimeDate.cpp +++ b/uppsrc/Core/TimeDate.cpp @@ -74,9 +74,7 @@ static char s_date_format_main[64] = "%2:02d/%3:02d/%1:4d"; void SetDateFormat(const char *fmt) { strncpy(s_date_format_thread, fmt, 63); -#ifdef _MULTITHREADED if(Thread::IsMain()) -#endif strncpy(s_date_format_main, fmt, 63); } @@ -93,10 +91,8 @@ static char s_date_scan_main[64] = "mdy"; void SetDateScan(const char *scan) { strncpy(s_date_scan_thread, scan, 63); -#ifdef _MULTITHREADED if(Thread::IsMain()) -#endif - strncpy(s_date_scan_main, scan, 63); + strncpy(s_date_scan_main, scan, 63); } const char *StrToDate(Date& d, const char *s, Date def) @@ -192,9 +188,7 @@ static char s_date_seps_main[64] = "A/\a .-"; void SetDateFilter(const char *seps) { strncpy(s_date_seps_thread, seps, 63); -#ifdef _MULTITHREADED if(Thread::IsMain()) -#endif strncpy(s_date_seps_main, seps, 63); } diff --git a/uppsrc/Core/t.cpp b/uppsrc/Core/t.cpp index 25c066d0b..2904b833f 100644 --- a/uppsrc/Core/t.cpp +++ b/uppsrc/Core/t.cpp @@ -250,9 +250,7 @@ void SetCurrentLanguage(int lang) int ii = sLangIndex().FindAdd(lang); sCurrentLangMapPtr = &sLangMap().At(ii); sCurrentSLangMapPtr = &sSLangMap().At(ii); - #ifdef _MULTITHREADED if(Thread::IsMain()) - #endif { main_current_lang = lang; sMainCurrentSLangMapPtr = sCurrentSLangMapPtr; diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index a9b17f935..44525174f 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -52,7 +52,6 @@ namespace Upp { INITIALIZE(CtrlCore) -#ifdef _MULTITHREADED void EnterGuiMutex(); bool TryEnterGuiMutex(); void LeaveGuiMutex(); @@ -62,15 +61,6 @@ void EnterGuiMutex(int n); bool ThreadHasGuiLock(); int GetGuiLockLevel(); -#else -inline void EnterGuiMutex() {} -inline void LeaveGuiMutex() {} -inline bool TryEnterGuiMutex() { return true; } - -inline int LeaveGuiMutexAll() { return 0; } -inline void EnterGuiMutex(int) {} -inline bool ThreadHasGuiLock() { return true; } -#endif struct GuiLock { GuiLock() { EnterGuiMutex(); } @@ -1285,10 +1275,8 @@ public: static void Call(Function cb); -#ifdef _MULTITHREADED static bool IsShutdownThreads() { return Thread::IsShutdownThreads(); } static void ShutdownThreads(); -#endif static int64 GetEventId() { return eventid; } diff --git a/uppsrc/CtrlCore/CtrlMt.cpp b/uppsrc/CtrlCore/CtrlMt.cpp index 85365aac5..0b36432e9 100644 --- a/uppsrc/CtrlCore/CtrlMt.cpp +++ b/uppsrc/CtrlCore/CtrlMt.cpp @@ -4,8 +4,6 @@ namespace Upp { -#ifdef _MULTITHREADED - static StaticMutex sGLock; static thread_local int sGLockLevel = 0; @@ -107,13 +105,4 @@ void Ctrl::ShutdownThreads() Thread::EndShutdownThreads(); } -#else - -void Ctrl::Call(Function cb) -{ - cb(); -} - -#endif - } diff --git a/uppsrc/CtrlCore/GtkApp.cpp b/uppsrc/CtrlCore/GtkApp.cpp index dfff39c7f..3bf497a03 100644 --- a/uppsrc/CtrlCore/GtkApp.cpp +++ b/uppsrc/CtrlCore/GtkApp.cpp @@ -77,9 +77,7 @@ void InitGtkApp(int argc, char **argv, const char **envptr) void ExitGtkApp() { -#ifdef _MULTITHREADED LeaveGuiMutex(); -#endif } } diff --git a/uppsrc/CtrlCore/srcdoc.tpp/GuiMT_en-us.tpp b/uppsrc/CtrlCore/srcdoc.tpp/GuiMT_en-us.tpp new file mode 100644 index 000000000..035a9e4ed --- /dev/null +++ b/uppsrc/CtrlCore/srcdoc.tpp/GuiMT_en-us.tpp @@ -0,0 +1,41 @@ +topic "GUI programming and multithreading"; +[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] +[l288;2 $$2,2#27521748481378242620020725143825:desc] +[0 $$3,0#96390100711032703541132217272105:end] +[H6;0 $$4,0#05600065144404261032431302351956:begin] +[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:item] +[l288;a4;*@5;1 $$6,6#70004532496200323422659154056402:requirement] +[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] +[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] +[b42;2 $$9,9#13035079074754324216151401829390:normal] +[a83;*R6 $$10,0#31310162474203024125188417583966:caption] +[2 $$0,0#00000000000000000000000000000000:Default] +[{_}%EN-US +[s10; GUI programming and multithreading&] +[s0; Multithreading in GUI programming model has to follow target +platform limitations, where most target platforms have a notion +of `"main thread`" and limit GUI actions allowed in non`-main +threads.&] +[s0; &] +[s0; Everything that is manipulating the status of top`-level windows +(TopWindow or popups) and everything related to event loop must +run on the main thread. The only non`-const operation allowed +to non`-main thread on top`-level windows is Refresh.&] +[s0; &] +[s0; Non`-main threads are in general allowed to alter the status +of widgets, as long as they serialize access with single global +GUI mutex, either with EnterGuiMutex/LeaveGuiMutex or with GuiLock +helper guard class (it calls EnterGuiMutex in constructor, LeaveGuiMutex +in destructor). GuiLock is reentrant and is optimized for great +reentrant performance. It is NOT required to use GuiLock in the +even processing methods (like MouseLeft or Key) as U`+`+ locks +it in this case itself.&] +[s0; &] +[s0; Other means of communication of non`-main threads with main +thread is PostCallback, which posts an Event to timer queue for +immediate processing, but does not wait for it to finish and +Ctrl`::Call, which passes event to main thread to be processed +and returns when the event is executed by the main thread. Both +of these methods have quite high latency, GuiLock and direct +access should be preferred if possible.&] +[s0; ]] \ No newline at end of file diff --git a/uppsrc/CtrlLib/Ch.cpp b/uppsrc/CtrlLib/Ch.cpp index 7068eada1..599f96a43 100644 --- a/uppsrc/CtrlLib/Ch.cpp +++ b/uppsrc/CtrlLib/Ch.cpp @@ -142,7 +142,7 @@ Image MakeElement(Size sz, double radius, const Image& face, double border_width Image MakeButton(int radius, const Image& face, double border_width, Color border_color, dword corner) { double q = radius + border_width + DPI(16); - return MakeElement(Size(q, q), radius, face, border_width, border_color, [&](Painter& w, const Rectf& r) { + return MakeElement(Size((int)q, (int)q), radius, face, border_width, border_color, [&](Painter& w, const Rectf& r) { RoundedRect(w, r, radius, radius, corner); }); } diff --git a/uppsrc/CtrlLib/FileSel.cpp b/uppsrc/CtrlLib/FileSel.cpp index 672010586..c44523897 100644 --- a/uppsrc/CtrlLib/FileSel.cpp +++ b/uppsrc/CtrlLib/FileSel.cpp @@ -863,8 +863,6 @@ void FileSel::SearchLoad() StartLI(); } -#ifdef _MULTITHREADED - StaticMutex FileSel::li_mutex; void (*FileSel::li_current)(const String& path, Image& result); String FileSel::li_path; @@ -961,8 +959,6 @@ void FileSel::StartLI() } } -#endif - String TrimDot(String f) { int i = f.Find('.'); if(i >= 0 && i == f.GetLength() - 1) diff --git a/uppsrc/CtrlLib/FileSel.h b/uppsrc/CtrlLib/FileSel.h index 204e93855..18abfabda 100644 --- a/uppsrc/CtrlLib/FileSel.h +++ b/uppsrc/CtrlLib/FileSel.h @@ -224,7 +224,6 @@ protected: Ctrl *file_ctrl = NULL; int file_ctrl_cx; -#ifdef _MULTITHREADED static StaticMutex li_mutex; static void (*li_current)(const String& path, Image& result); static String li_path; @@ -238,7 +237,6 @@ protected: void StartLI(); void DoLI(); void ScheduleLI() { li_tm.KillSet(0, THISBACK(DoLI)); } -#endif void LoadNet(); void SelectNet(); diff --git a/uppsrc/IconDes/List.cpp b/uppsrc/IconDes/List.cpp index f99f3381b..fdd31b993 100644 --- a/uppsrc/IconDes/List.cpp +++ b/uppsrc/IconDes/List.cpp @@ -282,7 +282,6 @@ struct ImgPreview : Display { } }; -#ifdef _MULTITHREADED static void sLoadImage(const String& path, Image& result) { if(findarg(ToLower(GetFileExt(path)), ".png", ".gif", ".jpeg", ".jpg") < 0) @@ -298,7 +297,6 @@ static void sLoadImage(const String& path, Image& result) return; result = r->GetImage(); } -#endif FileSel& IconDes::ImgFile() { @@ -307,9 +305,7 @@ FileSel& IconDes::ImgFile() sel.Type("Image files", "*.png *.bmp *.jpg *.jpeg *.gif *.ico"); sel.AllFilesType(); sel.Multi(); -#ifdef _MULTITHREADED sel.WhenIconLazy = sLoadImage; -#endif sel.Preview(Single()); } return sel; diff --git a/uppsrc/plugin/lz4/Compress.cpp b/uppsrc/plugin/lz4/Compress.cpp index ff8a09cde..12c3158f2 100644 --- a/uppsrc/plugin/lz4/Compress.cpp +++ b/uppsrc/plugin/lz4/Compress.cpp @@ -30,14 +30,12 @@ void LZ4CompressStream::Alloc() ptr = ~buffer; } -#ifdef _MULTITHREADED void LZ4CompressStream::Co(bool b) { FlushOut(); concurrent = b; Alloc(); } -#endif void LZ4CompressStream::FlushOut() { @@ -51,13 +49,11 @@ void LZ4CompressStream::FlushOut() int ii = 0; for(byte *s = ~buffer; s < ptr; s += BLOCK_BYTES) { int origsize = min((int)BLOCK_BYTES, int(ptr - s)); -#ifdef _MULTITHREADED if(concurrent) co & [=] { outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); }; else -#endif outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); ii++; t += osz; diff --git a/uppsrc/plugin/lz4/Decompress.cpp b/uppsrc/plugin/lz4/Decompress.cpp index cef0fc9be..6431f559a 100644 --- a/uppsrc/plugin/lz4/Decompress.cpp +++ b/uppsrc/plugin/lz4/Decompress.cpp @@ -84,9 +84,7 @@ void LZ4DecompressStream::Fetch() return; if(eof) return; -#ifdef _MULTITHREADED CoWork co; -#endif bool error = false; bool last = false; ii = 0; @@ -120,7 +118,6 @@ void LZ4DecompressStream::Fetch() SetError(); return; } -#ifdef _MULTITHREADED if(concurrent) co & [=, &error] { Workblock& t = wb[i]; @@ -129,9 +126,7 @@ void LZ4DecompressStream::Fetch() if(t.dlen < 0) error = true; }; - else -#endif - { + else { t.dlen = LZ4_decompress_safe(~t.c, ~t.d, t.clen, maxblock); if(t.dlen < 0) error = true; @@ -140,10 +135,8 @@ void LZ4DecompressStream::Fetch() if(lz4hdr & LZ4F_BLOCKCHECKSUM) in->Get32le(); // just skip it } -#ifdef _MULTITHREADED if(concurrent) co.Finish(); -#endif if(error) SetError(); else { diff --git a/uppsrc/plugin/lz4/lz4.h b/uppsrc/plugin/lz4/lz4.h index 78726ed83..16649e291 100644 --- a/uppsrc/plugin/lz4/lz4.h +++ b/uppsrc/plugin/lz4/lz4.h @@ -50,9 +50,7 @@ protected: void FlushOut(); public: -#ifdef _MULTITHREADED void Co(bool b = true); -#endif void Open(Stream& out_); LZ4CompressStream(); @@ -102,9 +100,7 @@ private: public: bool Open(Stream& in); -#ifdef _MULTITHREADED void Co(bool b = true) { concurrent = b; } -#endif LZ4DecompressStream(); LZ4DecompressStream(Stream& in) : LZ4DecompressStream() { Open(in); } @@ -120,7 +116,6 @@ String LZ4Compress(const String& s, Gate progress = Null); String LZ4Decompress(const void *data, int64 len, Gate progress = Null); String LZ4Decompress(const String& s, Gate progress = Null); -#ifdef _MULTITHREADED int64 CoLZ4Compress(Stream& out, Stream& in, Gate progress = Null); int64 CoLZ4Decompress(Stream& out, Stream& in, Gate progress = Null); String CoLZ4Compress(Stream& in, Gate progress = Null); @@ -129,7 +124,6 @@ String CoLZ4Compress(const void *data, int64 len, Gate progress = String CoLZ4Compress(const String& s, Gate progress = Null); String CoLZ4Decompress(const void *data, int64 len, Gate progress = Null); String CoLZ4Decompress(const String& s, Gate progress = Null); -#endif bool IsLZ4(Stream& s); diff --git a/uppsrc/plugin/lz4/util.cpp b/uppsrc/plugin/lz4/util.cpp index 8ea80df59..351cdeabe 100644 --- a/uppsrc/plugin/lz4/util.cpp +++ b/uppsrc/plugin/lz4/util.cpp @@ -7,10 +7,8 @@ void sCompressStreamCopy_(Stream& out, Stream& in, Gate progress, static int64 sLZ4Compress(Stream& out, Stream& in, int64 size, Gate progress, bool co) { LZ4CompressStream outs(out); -#ifdef _MULTITHREADED if(co) outs.Co(); -#endif sCompressStreamCopy_(outs, in, progress, in, size); outs.Close(); if(!out.IsError() && !outs.IsError()) @@ -21,10 +19,8 @@ static int64 sLZ4Compress(Stream& out, Stream& in, int64 size, Gate progress, bool co) { LZ4DecompressStream ins(in); -#ifdef _MULTITHREADED if(co) ins.Co(); -#endif sCompressStreamCopy_(out, ins, progress, in, size); ins.Close(); if(!out.IsError() && !ins.IsError()) @@ -76,8 +72,6 @@ String LZ4Decompress(const String& s, Gate progress) return LZ4Decompress(~s, s.GetLength(), progress); } -#ifdef _MULTITHREADED - int64 CoLZ4Compress(Stream& out, Stream& in, Gate progress) { return sLZ4Compress(out, in, in.GetLeft(), progress, true); @@ -124,6 +118,4 @@ String CoLZ4Decompress(const String& s, Gate progress) return CoLZ4Decompress(~s, s.GetLength(), progress); } -#endif - }; \ No newline at end of file diff --git a/uppsrc/plugin/zstd/Util.cpp b/uppsrc/plugin/zstd/Util.cpp index 95a7a92b9..b682ee188 100644 --- a/uppsrc/plugin/zstd/Util.cpp +++ b/uppsrc/plugin/zstd/Util.cpp @@ -7,10 +7,8 @@ void sCompressStreamCopy_(Stream& out, Stream& in, Gate progress, static int64 sZstdCompress(Stream& out, Stream& in, int64 size, Gate progress, bool co) { ZstdCompressStream outs(out); -#ifdef _MULTITHREADED if(co) outs.Co(); -#endif sCompressStreamCopy_(outs, in, progress, in, size); outs.Close(); if(!out.IsError() && !outs.IsError()) @@ -21,10 +19,8 @@ static int64 sZstdCompress(Stream& out, Stream& in, int64 size, Gate progress, bool co) { ZstdDecompressStream ins(in); -#ifdef _MULTITHREADED if(co) ins.Co(); -#endif sCompressStreamCopy_(out, ins, progress, in, size); ins.Close(); if(!out.IsError() && !ins.IsError()) @@ -66,8 +62,6 @@ String ZstdDecompress(const String& s, Gate progress) return ZstdDecompress(~s, s.GetLength(), progress); } -#ifdef _MULTITHREADED - int64 CoZstdCompress(Stream& out, Stream& in, Gate progress) { return sZstdCompress(out, in, in.GetLeft(), progress, true); @@ -102,6 +96,4 @@ String CoZstdDecompress(const String& s, Gate progress) return CoZstdDecompress(~s, s.GetLength(), progress); } -#endif - }; \ No newline at end of file diff --git a/uppsrc/plugin/zstd/zstd.h b/uppsrc/plugin/zstd/zstd.h index dc4efd89a..e7d5ce6d4 100644 --- a/uppsrc/plugin/zstd/zstd.h +++ b/uppsrc/plugin/zstd/zstd.h @@ -34,9 +34,7 @@ protected: void FlushOut(); public: -#ifdef _MULTITHREADED void Co(bool b = true); -#endif void Open(Stream& out, int level = 1); ZstdCompressStream(); @@ -92,10 +90,7 @@ private: public: bool Open(Stream& in); - -#ifdef _MULTITHREADED void Co(bool b = true) { concurrent = b; } -#endif ZstdDecompressStream(); ZstdDecompressStream(Stream& in) : ZstdDecompressStream() { Open(in); } @@ -109,14 +104,12 @@ String ZstdCompress(const String& s, Gate progress = Null); String ZstdDecompress(const void *data, int64 len, Gate progress = Null); String ZstdDecompress(const String& s, Gate progress = Null); -#ifdef _MULTITHREADED int64 CoZstdCompress(Stream& out, Stream& in, Gate progress = Null); int64 CoZstdDecompress(Stream& out, Stream& in, Gate progress = Null); String CoZstdCompress(const void *data, int64 len, Gate progress = Null); String CoZstdCompress(const String& s, Gate progress = Null); String CoZstdDecompress(const void *data, int64 len, Gate progress = Null); String CoZstdDecompress(const String& s, Gate progress = Null); -#endif bool IsZstd(Stream& s);