Files
tubestation/intl/icu-patches/bug-1706949-wasi-workaround.diff
Alexandru Marc 52a93f69fa Backed out 19 changesets (bug 1927706) for causing reftest failures @ space-cluster-2.html
Backed out changeset 3877f1fa62f5 (bug 1927706)
Backed out changeset 233c6ebf84a2 (bug 1927706)
Backed out changeset 07e5871d5fa3 (bug 1927706)
Backed out changeset 84ef75087931 (bug 1927706)
Backed out changeset f89b916619e1 (bug 1927706)
Backed out changeset b82d9d622315 (bug 1927706)
Backed out changeset b0d2c5711865 (bug 1927706)
Backed out changeset 9529dda25bd9 (bug 1927706)
Backed out changeset 40b7907d7fc8 (bug 1927706)
Backed out changeset c549655dbd73 (bug 1927706)
Backed out changeset c5cc289771b3 (bug 1927706)
Backed out changeset 8ef66f7822c4 (bug 1927706)
Backed out changeset dff6d37fb2fe (bug 1927706)
Backed out changeset 083a0b3da643 (bug 1927706)
Backed out changeset 06649ac72a19 (bug 1927706)
Backed out changeset 019f7533abbc (bug 1927706)
Backed out changeset f1539604c459 (bug 1927706)
Backed out changeset 578667f1f0d4 (bug 1927706)
Backed out changeset 8ed1e7e7d4ab (bug 1927706)
2024-10-30 11:19:58 +02:00

770 lines
23 KiB
Diff

# Handle WASI lack of support for <thread> and <atomic>.
#
# WASI issue: https://github.com/WebAssembly/wasi-sdk/issues/180
diff --git a/intl/icu/source/common/putilimp.h b/intl/icu/source/common/putilimp.h
index 5b95a68..7097232 100644
--- a/intl/icu/source/common/putilimp.h
+++ b/intl/icu/source/common/putilimp.h
@@ -103,6 +103,8 @@ typedef size_t uintptr_t;
#endif
#elif U_PLATFORM == U_PF_OS400
/* not defined */
+#elif defined(__wasi__)
+ /* not defined */
#else
# define U_TZSET tzset
#endif
@@ -128,6 +130,8 @@ typedef size_t uintptr_t;
/* not defined */
#elif U_PLATFORM == U_PF_IPHONE
/* not defined */
+#elif defined(__wasi__)
+ /* not defined */
#else
# define U_TIMEZONE timezone
#endif
@@ -141,6 +145,8 @@ typedef size_t uintptr_t;
#endif
#elif U_PLATFORM == U_PF_OS400
/* not defined */
+#elif defined(__wasi__)
+ /* not defined */
#else
# define U_TZNAME tzname
#endif
diff --git a/intl/icu/source/common/umapfile.h b/intl/icu/source/common/umapfile.h
index 92bd567..4ed1112 100644
--- a/intl/icu/source/common/umapfile.h
+++ b/intl/icu/source/common/umapfile.h
@@ -41,6 +41,8 @@ U_CFUNC void uprv_unmapFile(UDataMemory *pData);
#if UCONFIG_NO_FILE_IO
# define MAP_IMPLEMENTATION MAP_NONE
+#elif defined(__wasi__)
+# define MAP_IMPLEMENTATION MAP_STDIO
#elif U_PLATFORM_USES_ONLY_WIN32_API
# define MAP_IMPLEMENTATION MAP_WIN32
#elif U_HAVE_MMAP || U_PLATFORM == U_PF_OS390
diff --git a/intl/icu/source/common/umutex.cpp b/intl/icu/source/common/umutex.cpp
index ccbee99..6c3452c 100644
--- a/intl/icu/source/common/umutex.cpp
+++ b/intl/icu/source/common/umutex.cpp
@@ -43,6 +43,7 @@ U_NAMESPACE_BEGIN
*
*************************************************************************************************/
+#ifndef __wasi__
namespace {
std::mutex *initMutex;
std::condition_variable *initCondition;
@@ -55,9 +56,11 @@ std::once_flag initFlag;
std::once_flag *pInitFlag = &initFlag;
} // Anonymous namespace
+#endif
U_CDECL_BEGIN
static UBool U_CALLCONV umtx_cleanup() {
+#ifndef __wasi__
initMutex->~mutex();
initCondition->~condition_variable();
UMutex::cleanup();
@@ -66,17 +69,21 @@ static UBool U_CALLCONV umtx_cleanup() {
// Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once().
pInitFlag->~once_flag();
pInitFlag = new(&initFlag) std::once_flag();
+#endif
return true;
}
static void U_CALLCONV umtx_init() {
+#ifndef __wasi__
initMutex = STATIC_NEW(std::mutex);
initCondition = STATIC_NEW(std::condition_variable);
ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup);
+#endif
}
U_CDECL_END
+#ifndef __wasi__
std::mutex *UMutex::getMutex() {
std::mutex *retPtr = fMutex.load(std::memory_order_acquire);
if (retPtr == nullptr) {
@@ -93,14 +100,17 @@ std::mutex *UMutex::getMutex() {
U_ASSERT(retPtr != nullptr);
return retPtr;
}
+#endif
UMutex *UMutex::gListHead = nullptr;
void UMutex::cleanup() {
UMutex *next = nullptr;
for (UMutex *m = gListHead; m != nullptr; m = next) {
+#ifndef __wasi__
(*m->fMutex).~mutex();
m->fMutex = nullptr;
+#endif
next = m->fListLink;
m->fListLink = nullptr;
}
@@ -110,20 +120,24 @@ void UMutex::cleanup() {
U_CAPI void U_EXPORT2
umtx_lock(UMutex *mutex) {
+#ifndef __wasi__
if (mutex == nullptr) {
mutex = &globalMutex;
}
mutex->lock();
+#endif
}
U_CAPI void U_EXPORT2
umtx_unlock(UMutex* mutex)
{
+#ifndef __wasi__
if (mutex == nullptr) {
mutex = &globalMutex;
}
mutex->unlock();
+#endif
}
@@ -143,18 +157,22 @@ umtx_unlock(UMutex* mutex)
//
U_COMMON_API UBool U_EXPORT2
umtx_initImplPreInit(UInitOnce &uio) {
+#ifndef __wasi__
std::call_once(*pInitFlag, umtx_init);
std::unique_lock<std::mutex> lock(*initMutex);
+#endif
if (umtx_loadAcquire(uio.fState) == 0) {
umtx_storeRelease(uio.fState, 1);
return true; // Caller will next call the init function.
} else {
+#ifndef __wasi__
while (umtx_loadAcquire(uio.fState) == 1) {
// Another thread is currently running the initialization.
// Wait until it completes.
initCondition->wait(lock);
}
U_ASSERT(uio.fState == 2);
+#endif
return false;
}
}
@@ -168,11 +186,13 @@ umtx_initImplPreInit(UInitOnce &uio) {
U_COMMON_API void U_EXPORT2
umtx_initImplPostInit(UInitOnce &uio) {
+#ifndef __wasi__
{
std::unique_lock<std::mutex> lock(*initMutex);
umtx_storeRelease(uio.fState, 2);
}
initCondition->notify_all();
+#endif
}
U_NAMESPACE_END
diff --git a/intl/icu/source/common/umutex.h b/intl/icu/source/common/umutex.h
index 8d76b3f..c1a58db 100644
--- a/intl/icu/source/common/umutex.h
+++ b/intl/icu/source/common/umutex.h
@@ -20,9 +20,12 @@
#ifndef UMUTEX_H
#define UMUTEX_H
+#ifndef __wasi__
#include <atomic>
#include <condition_variable>
#include <mutex>
+#endif
+
#include <type_traits>
#include "unicode/utypes.h"
@@ -37,6 +40,8 @@
#error U_USER_ATOMICS and U_USER_MUTEX_H are not supported
#endif
+#ifndef __wasi__
+
// Export an explicit template instantiation of std::atomic<int32_t>.
// When building DLLs for Windows this is required as it is used as a data member of the exported SharedObject class.
// See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples.
@@ -61,6 +66,7 @@ template struct std::atomic<std::mutex *>;
#endif
#endif
+#endif
U_NAMESPACE_BEGIN
@@ -70,6 +76,8 @@ U_NAMESPACE_BEGIN
*
****************************************************************************/
+#ifndef __wasi__
+
typedef std::atomic<int32_t> u_atomic_int32_t;
#define ATOMIC_INT32_T_INITIALIZER(val) ATOMIC_VAR_INIT(val)
@@ -89,6 +97,28 @@ inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
return var->fetch_sub(1) - 1;
}
+#else
+
+typedef int32_t u_atomic_int32_t;
+#define ATOMIC_INT32_T_INITIALIZER(val) val
+
+inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
+ return var;
+}
+
+inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
+ var = val;
+}
+
+inline int32_t umtx_atomic_inc(u_atomic_int32_t *var) {
+ return ++(*var);
+}
+
+inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
+ return --(*var);
+}
+
+#endif
/*************************************************************************************************
*
@@ -231,17 +261,25 @@ class U_COMMON_API UMutex {
// requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard
void lock() {
+#ifndef __wasi__
std::mutex *m = fMutex.load(std::memory_order_acquire);
if (m == nullptr) { m = getMutex(); }
m->lock();
+#endif
+ }
+ void unlock() {
+#ifndef __wasi__
+ fMutex.load(std::memory_order_relaxed)->unlock();
+#endif
}
- void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); }
static void cleanup();
private:
+#ifndef __wasi__
alignas(std::mutex) char fStorage[sizeof(std::mutex)] {};
std::atomic<std::mutex *> fMutex { nullptr };
+#endif
/** All initialized UMutexes are kept in a linked list, so that they can be found,
* and the underlying std::mutex destructed, by u_cleanup().
@@ -253,7 +291,9 @@ class U_COMMON_API UMutex {
* Initial fast check is inline, in lock(). The returned value may never
* be nullptr.
*/
+#ifndef __wasi__
std::mutex *getMutex();
+#endif
};
diff --git a/intl/icu/source/common/unifiedcache.cpp b/intl/icu/source/common/unifiedcache.cpp
--- a/intl/icu/source/common/unifiedcache.cpp
+++ b/intl/icu/source/common/unifiedcache.cpp
@@ -11,19 +11,23 @@
*/
#include "unifiedcache.h"
#include <algorithm> // For std::max()
-#include <mutex>
+#ifndef __wasi__
+ #include <mutex>
+#endif
#include "uassert.h"
#include "uhash.h"
#include "ucln_cmn.h"
static icu::UnifiedCache *gCache = nullptr;
+#ifndef __wasi__
static std::mutex *gCacheMutex = nullptr;
static std::condition_variable *gInProgressValueAddedCond;
+#endif
static icu::UInitOnce gCacheInitOnce {};
static const int32_t MAX_EVICT_ITERATIONS = 10;
static const int32_t DEFAULT_MAX_UNUSED = 1000;
static const int32_t DEFAULT_PERCENTAGE_OF_IN_USE = 100;
@@ -32,14 +36,16 @@ static const int32_t DEFAULT_PERCENTAGE_OF_IN_USE = 100;
U_CDECL_BEGIN
static UBool U_CALLCONV unifiedcache_cleanup() {
gCacheInitOnce.reset();
delete gCache;
gCache = nullptr;
+#ifndef __wasi__
gCacheMutex->~mutex();
gCacheMutex = nullptr;
gInProgressValueAddedCond->~condition_variable();
gInProgressValueAddedCond = nullptr;
+#endif
return true;
}
U_CDECL_END
@@ -70,12 +76,14 @@ CacheKeyBase::~CacheKeyBase() {
static void U_CALLCONV cacheInit(UErrorCode &status) {
U_ASSERT(gCache == nullptr);
ucln_common_registerCleanup(
UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup);
+#ifndef __wasi__
gCacheMutex = STATIC_NEW(std::mutex);
gInProgressValueAddedCond = STATIC_NEW(std::condition_variable);
+#endif
gCache = new UnifiedCache(status);
if (gCache == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) {
@@ -133,41 +141,53 @@ void UnifiedCache::setEvictionPolicy(
}
if (count < 0 || percentageOfInUseItems < 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
fMaxUnused = count;
fMaxPercentageOfInUse = percentageOfInUseItems;
}
int32_t UnifiedCache::unusedCount() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
return uhash_count(fHashtable) - fNumValuesInUse;
}
int64_t UnifiedCache::autoEvictedCount() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
return fAutoEvictedCount;
}
int32_t UnifiedCache::keyCount() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
return uhash_count(fHashtable);
}
void UnifiedCache::flush() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
// Use a loop in case cache items that are flushed held hard references to
// other cache items making those additional cache items eligible for
// flushing.
while (_flush(false));
}
void UnifiedCache::handleUnreferencedObject() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
--fNumValuesInUse;
_runEvictionSlice();
}
#ifdef UNIFIED_CACHE_DEBUG
@@ -182,11 +202,13 @@ void UnifiedCache::dump() {
}
cache->dumpContents();
}
void UnifiedCache::dumpContents() const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
_dumpContents();
}
// Dumps content of cache.
// On entry, gCacheMutex must be held.
@@ -222,11 +244,13 @@ UnifiedCache::~UnifiedCache() {
flush();
{
// Now all that should be left in the cache are entries that refer to
// each other and entries with hard references from outside the cache.
// Nothing we can do about these so proceed to wipe out the cache.
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
_flush(true);
}
uhash_close(fHashtable);
fHashtable = nullptr;
delete fNoValue;
@@ -323,11 +347,13 @@ void UnifiedCache::_putNew(
void UnifiedCache::_putIfAbsentAndGet(
const CacheKeyBase &key,
const SharedObject *&value,
UErrorCode &status) const {
+#ifndef __wasi__
std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
const UHashElement *element = uhash_find(fHashtable, &key);
if (element != nullptr && !_inProgress(element)) {
_fetch(element, value, status);
return;
}
@@ -348,18 +374,22 @@ UBool UnifiedCache::_poll(
const CacheKeyBase &key,
const SharedObject *&value,
UErrorCode &status) const {
U_ASSERT(value == nullptr);
U_ASSERT(status == U_ZERO_ERROR);
+#ifndef __wasi__
std::unique_lock<std::mutex> lock(*gCacheMutex);
+#endif
const UHashElement *element = uhash_find(fHashtable, &key);
// If the hash table contains an inProgress placeholder entry for this key,
// this means that another thread is currently constructing the value object.
// Loop, waiting for that construction to complete.
while (element != nullptr && _inProgress(element)) {
+#ifndef __wasi__
gInProgressValueAddedCond->wait(lock);
+#endif
element = uhash_find(fHashtable, &key);
}
// If the hash table contains an entry for the key,
// fetch out the contents and return them.
@@ -426,13 +456,15 @@ void UnifiedCache::_put(
UHashElement *ptr = const_cast<UHashElement *>(element);
ptr->value.pointer = (void *) value;
U_ASSERT(oldValue == fNoValue);
removeSoftRef(oldValue);
+#ifndef __wasi__
// Tell waiting threads that we replace in-progress status with
// an error.
gInProgressValueAddedCond->notify_all();
+#endif
}
void UnifiedCache::_fetch(
const UHashElement *element,
const SharedObject *&value,
diff --git a/intl/icu/source/i18n/decContext.h b/intl/icu/source/i18n/decContext.h
index 59ab65e..20f3526 100644
--- a/intl/icu/source/i18n/decContext.h
+++ b/intl/icu/source/i18n/decContext.h
@@ -61,7 +61,9 @@
/* #include <stdint.h> */ /* C99 standard integers */
#endif
#include <stdio.h> /* for printf, etc. */
+#ifndef __wasi__
#include <signal.h> /* for traps */
+#endif
/* Extended flags setting -- set this to 0 to use only IEEE flags */
#if !defined(DECEXTFLAG)
diff --git a/intl/icu/source/i18n/decimfmt.cpp b/intl/icu/source/i18n/decimfmt.cpp
index daa1129..c8f1eda 100644
--- a/intl/icu/source/i18n/decimfmt.cpp
+++ b/intl/icu/source/i18n/decimfmt.cpp
@@ -480,8 +480,13 @@ DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {
DecimalFormat::~DecimalFormat() {
if (fields == nullptr) { return; }
+#ifndef __wasi__
delete fields->atomicParser.exchange(nullptr);
delete fields->atomicCurrencyParser.exchange(nullptr);
+#else
+ delete fields->atomicParser;
+ delete fields->atomicCurrencyParser;
+#endif
delete fields;
}
@@ -1626,8 +1631,13 @@ void DecimalFormat::touch(UErrorCode& status) {
setupFastFormat();
// Delete the parsers if they were made previously
+#ifndef __wasi__
delete fields->atomicParser.exchange(nullptr);
delete fields->atomicCurrencyParser.exchange(nullptr);
+#else
+ delete fields->atomicParser;
+ delete fields->atomicCurrencyParser;
+#endif
// In order for the getters to work, we need to populate some fields in NumberFormat.
NumberFormat::setCurrency(fields->exportedProperties.currency.get(status).getISOCurrency(), status);
@@ -1662,7 +1672,11 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
}
// First try to get the pre-computed parser
+#ifndef __wasi__
auto* ptr = fields->atomicParser.load();
+#else
+ auto* ptr = fields->atomicParser;
+#endif
if (ptr != nullptr) {
return ptr;
}
@@ -1681,6 +1695,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
// it is set to what is actually stored in the atomic
// if another thread beat us to computing the parser object.
auto* nonConstThis = const_cast<DecimalFormat*>(this);
+#ifndef __wasi__
if (!nonConstThis->fields->atomicParser.compare_exchange_strong(ptr, temp)) {
// Another thread beat us to computing the parser
delete temp;
@@ -1689,13 +1704,21 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
// Our copy of the parser got stored in the atomic
return temp;
}
+#else
+ nonConstThis->fields->atomicParser = temp;
+ return temp;
+#endif
}
const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorCode& status) const {
if (U_FAILURE(status)) { return nullptr; }
// First try to get the pre-computed parser
+#ifndef __wasi__
auto* ptr = fields->atomicCurrencyParser.load();
+#else
+ auto* ptr = fields->atomicCurrencyParser;
+#endif
if (ptr != nullptr) {
return ptr;
}
@@ -1710,6 +1733,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
// Note: ptr starts as nullptr; during compare_exchange, it is set to what is actually stored in the
// atomic if another thread beat us to computing the parser object.
auto* nonConstThis = const_cast<DecimalFormat*>(this);
+#ifndef __wasi__
if (!nonConstThis->fields->atomicCurrencyParser.compare_exchange_strong(ptr, temp)) {
// Another thread beat us to computing the parser
delete temp;
@@ -1718,6 +1742,10 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
// Our copy of the parser got stored in the atomic
return temp;
}
+#else
+ nonConstThis->fields->atomicCurrencyParser = temp;
+ return temp;
+#endif
}
void
diff --git a/intl/icu/source/i18n/number_mapper.h b/intl/icu/source/i18n/number_mapper.h
index 9ecd776..d094289 100644
--- a/intl/icu/source/i18n/number_mapper.h
+++ b/intl/icu/source/i18n/number_mapper.h
@@ -7,7 +7,6 @@
#ifndef __NUMBER_MAPPER_H__
#define __NUMBER_MAPPER_H__
-#include <atomic>
#include "number_types.h"
#include "unicode/currpinf.h"
#include "standardplural.h"
@@ -15,6 +14,10 @@
#include "number_currencysymbols.h"
#include "numparse_impl.h"
+#ifndef __wasi__
+#include <atomic>
+#endif
+
U_NAMESPACE_BEGIN
namespace number {
namespace impl {
@@ -193,10 +196,18 @@ struct DecimalFormatFields : public UMemory {
LocalizedNumberFormatter formatter;
/** The lazy-computed parser for .parse() */
+#ifndef __wasi__
std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
+#else
+ ::icu::numparse::impl::NumberParserImpl* atomicParser = nullptr;
+#endif
/** The lazy-computed parser for .parseCurrency() */
+#ifndef __wasi__
std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {};
+#else
+ ::icu::numparse::impl::NumberParserImpl* atomicCurrencyParser = {};
+#endif
/** Small object ownership warehouse for the formatter and parser */
DecimalFormatWarehouse warehouse;
diff --git a/intl/icu/source/i18n/numrange_fluent.cpp b/intl/icu/source/i18n/numrange_fluent.cpp
--- a/intl/icu/source/i18n/numrange_fluent.cpp
+++ b/intl/icu/source/i18n/numrange_fluent.cpp
@@ -238,33 +238,53 @@ LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRang
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(NFS<LNF>&& src) noexcept
: NFS<LNF>(std::move(src)) {
// Steal the compiled formatter
LNF&& _src = static_cast<LNF&&>(src);
+#ifndef __wasi__
auto* stolen = _src.fAtomicFormatter.exchange(nullptr);
delete fAtomicFormatter.exchange(stolen);
+#else
+ delete fAtomicFormatter;
+ fAtomicFormatter = _src.fAtomicFormatter;
+ _src.fAtomicFormatter = nullptr;
+#endif
}
LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(const LNF& other) {
if (this == &other) { return *this; } // self-assignment: no-op
NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
// Do not steal; just clear
+#ifndef __wasi__
delete fAtomicFormatter.exchange(nullptr);
+#else
+ delete fAtomicFormatter;
+#endif
return *this;
}
LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(LNF&& src) noexcept {
NFS<LNF>::operator=(static_cast<NFS<LNF>&&>(src));
// Steal the compiled formatter
+#ifndef __wasi__
auto* stolen = src.fAtomicFormatter.exchange(nullptr);
delete fAtomicFormatter.exchange(stolen);
+#else
+ delete fAtomicFormatter;
+ fAtomicFormatter = src.fAtomicFormatter;
+ src.fAtomicFormatter = nullptr;
+#endif
return *this;
}
LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter() {
+#ifndef __wasi__
delete fAtomicFormatter.exchange(nullptr);
+#else
+ delete fAtomicFormatter;
+#endif
}
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const RangeMacroProps& macros, const Locale& locale) {
fMacros = macros;
fMacros.locale = locale;
@@ -344,11 +364,15 @@ LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const {
if (U_FAILURE(status)) {
return nullptr;
}
// First try to get the pre-computed formatter
+#ifndef __wasi__
auto* ptr = fAtomicFormatter.load();
+#else
+ auto* ptr = fAtomicFormatter;
+#endif
if (ptr != nullptr) {
return ptr;
}
// Try computing the formatter on our own
@@ -364,18 +388,23 @@ LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const {
// Note: ptr starts as nullptr; during compare_exchange,
// it is set to what is actually stored in the atomic
// if another thread beat us to computing the formatter object.
auto* nonConstThis = const_cast<LocalizedNumberRangeFormatter*>(this);
+#ifndef __wasi__
if (!nonConstThis->fAtomicFormatter.compare_exchange_strong(ptr, temp)) {
// Another thread beat us to computing the formatter
delete temp;
return ptr;
} else {
// Our copy of the formatter got stored in the atomic
return temp;
}
+#else
+ nonConstThis->fAtomicFormatter = temp;
+ return temp;
+#endif
}
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/intl/icu/source/i18n/unicode/numberrangeformatter.h b/intl/icu/source/i18n/unicode/numberrangeformatter.h
index b9a4600..0ba2fa0 100644
--- a/intl/icu/source/i18n/unicode/numberrangeformatter.h
+++ b/intl/icu/source/i18n/unicode/numberrangeformatter.h
@@ -10,7 +10,6 @@
#if !UCONFIG_NO_FORMATTING
-#include <atomic>
#include "unicode/appendable.h"
#include "unicode/fieldpos.h"
#include "unicode/formattedvalue.h"
@@ -18,6 +17,10 @@
#include "unicode/numberformatter.h"
#include "unicode/unumberrangeformatter.h"
+#ifndef __wasi__
+#include <atomic>
+#endif
+
/**
* \file
* \brief C++ API: Library for localized formatting of number, currency, and unit ranges.
@@ -77,7 +80,9 @@ struct UFormattedNumberRangeImpl;
} // namespace icu::number
U_NAMESPACE_END
+#ifndef __wasi__
template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>;
+#endif
U_NAMESPACE_BEGIN
namespace number { // icu::number
@@ -546,7 +551,11 @@ class U_I18N_API LocalizedNumberRangeFormatter
~LocalizedNumberRangeFormatter();
private:
+#ifndef __wasi__
std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {};
+#else
+ impl::NumberRangeFormatterImpl* fAtomicFormatter = nullptr;
+#endif
const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const;