QUnicodeTools: fix data race in initialization of libthai symbols
The facilities of qunicodetools.cpp are not limited to the GUI thread, so initialization must be thread-safe. The old code wasn't, though, and contained several data races - non-atomic initialized was read while another thead may write it - th_brk and th_next_cell were read while another thead may write them Fix by using Double-Checked Locking. This also prepares the code for an eventual port to th_brk_find_breaks() (th_brk is deprecated). The function pointers don't need to be atomic, because all reads from them are guaranteed to happen-after the writes to them (as long as all users call init_libthai() and don't proceeed if it returns false; this could be ensured by returning a struct with the function pointers from init_libthai() instead of maintaining them as statically-visible globals, but that's outsize the scope of this patch). As a drive-by, remove a pointless static_cast<int>(~~int expression~~). Fixes: QTBUG-105543 Pick-to: 6.4 6.3 6.2 Change-Id: I492acd7e9a257e5c4b91f576e9bc448b6bb96ad1 Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> Reviewed-by: Lars Knoll <lars.knoll@gmail.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
50d1a8a377
commit
7d021e3173
@ -3,12 +3,15 @@
|
||||
|
||||
#include "qunicodetools_p.h"
|
||||
|
||||
#include "qmutex.h"
|
||||
#include "qunicodetables_p.h"
|
||||
#include "qvarlengtharray.h"
|
||||
#if QT_CONFIG(library)
|
||||
#include "qlibrary.h"
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#define FLAG(x) (1 << (x))
|
||||
@ -1405,11 +1408,15 @@ Q_CONSTINIT static th_next_cell_def th_next_cell = nullptr;
|
||||
|
||||
static int init_libthai() {
|
||||
#if QT_CONFIG(library)
|
||||
Q_CONSTINIT static bool initialized = false;
|
||||
if (!initialized && (!th_brk || !th_next_cell)) {
|
||||
th_brk = reinterpret_cast<th_brk_def>(QLibrary::resolve("thai"_L1, static_cast<int>(LIBTHAI_MAJOR), "th_brk"));
|
||||
th_next_cell = (th_next_cell_def)QLibrary::resolve("thai"_L1, LIBTHAI_MAJOR, "th_next_cell");
|
||||
initialized = true;
|
||||
Q_CONSTINIT static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false);
|
||||
Q_CONSTINIT static QBasicMutex mutex;
|
||||
if (!initialized.loadAcquire()) {
|
||||
const auto locker = std::scoped_lock(mutex);
|
||||
if (!initialized.loadAcquire()) {
|
||||
th_brk = reinterpret_cast<th_brk_def>(QLibrary::resolve("thai"_L1, LIBTHAI_MAJOR, "th_brk"));
|
||||
th_next_cell = (th_next_cell_def)QLibrary::resolve("thai"_L1, LIBTHAI_MAJOR, "th_next_cell");
|
||||
initialized.storeRelease(true);
|
||||
}
|
||||
}
|
||||
if (th_brk && th_next_cell)
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user