ICU-10183 Use std::mutex by default; clean up related dependency check issues.

This commit is contained in:
Andy Heninger 2018-11-12 10:20:49 -08:00
parent 74bbf9e381
commit 6c781b1428
5 changed files with 63 additions and 8 deletions

View File

@ -245,7 +245,7 @@ typedef size_t uintptr_t;
#ifdef U_HAVE_STD_MUTEX
/* Use the predefined value. */
#else
# define U_HAVE_STD_MUTEX 0
# define U_HAVE_STD_MUTEX 1
#endif
/*===========================================================================*/

View File

@ -64,6 +64,11 @@ umtx_unlock(UMutex* mutex)
mutex->fMutex.unlock();
}
UConditionVar::UConditionVar() : fCV() {
}
UConditionVar::~UConditionVar() {
}
U_CAPI void U_EXPORT2
umtx_condWait(UConditionVar *cond, UMutex *mutex) {

31
icu4c/source/common/umutex.h Normal file → Executable file
View File

@ -341,19 +341,42 @@ U_NAMESPACE_END
#include <mutex>
#include <condition_variable>
#include "unicode/uobject.h"
struct UMutex {
std::mutex fMutex;
struct UMutex : public icu::UMemory {
UMutex() = default;
~UMutex() = default;
UMutex(const UMutex &other) = delete;
UMutex &operator =(const UMutex &other) = delete;
std::mutex fMutex = {}; // Note: struct - pubic members - because most access is from
// // plain C style functions (umtx_lock(), etc.)
};
struct UConditionVar {
struct UConditionVar : public icu::UMemory {
U_COMMON_API UConditionVar();
U_COMMON_API ~UConditionVar();
UConditionVar(const UConditionVar &other) = delete;
UConditionVar &operator =(const UConditionVar &other) = delete;
std::condition_variable_any fCV;
};
#define U_MUTEX_INITIALIZER {}
#define U_CONDITION_INITIALIZER {}
// Implementation notes for UConditionVar:
//
// Use an out-of-line constructor to reduce problems with the ICU dependency checker.
// On Linux, the default constructor of std::condition_variable_any
// produces an in-line reference to global operator new(), which the
// dependency checker flags for any file that declares a UConditionVar. With
// an out-of-line constructor, the dependency is constrained to umutex.o
//
// Do not export (U_COMMON_API) the entire class, but only the constructor
// and destructor, to avoid Windows build problems with attempting to export the
// std::condition_variable_any.
#elif U_PLATFORM_USES_ONLY_WIN32_API

View File

@ -24,6 +24,7 @@ system_symbols:
stdio_input stdio_output file_io readlink_function dir_io mmap_functions dlfcn
# C++
cplusplus iostream
std_mutex
group: PIC
# Position-Independent Code (-fPIC) requires a Global Offset Table.
@ -38,6 +39,15 @@ group: system_debug
group: malloc_functions
free malloc realloc
group: std_mutex
std::condition_variable::notify_one()
std::condition_variable::wait(std::unique_lock<std::mutex>&)
std::condition_variable::notify_all()
std::condition_variable::condition_variable()
std::condition_variable::~condition_variable()
std::condition_variable_any::condition_variable_any()
std::condition_variable_any::~condition_variable_any()
group: ubsan
# UBSan=UndefinedBehaviorSanitizer, clang -fsanitize=bounds
__ubsan_handle_out_of_bounds
@ -819,6 +829,7 @@ group: platform
stdio_input readlink_function dir_io
dlfcn # Move related code into icuplug.c?
cplusplus
std_mutex
# ICU i18n library ----------------------------------------------------------- #

View File

@ -16,8 +16,11 @@ This probably works only on Linux.
The exit code is 0 if everything is fine, 1 for errors, 2 for only warnings.
Sample invocation:
~/svn.icu/trunk/src/source/test/depstest$ ./depstest.py ~/svn.icu/trunk/dbg
Sample invocation with an in-source build:
~/icu/icu4c/source/test/depstest$ ./depstest.py ../../
Sample invocation with an out-of-source build:
~/icu/icu4c/source/test/depstest$ ./depstest.py ~/build/
"""
__author__ = "Markus W. Scherer"
@ -87,6 +90,16 @@ def _ReadLibrary(root_path, library_name):
for path in obj_paths:
_ReadObjFile(root_path, library_name, os.path.basename(path))
# Dependencies that would otherwise be errors, but that are to be allowed
# in a limited (not transitive) context. List of (file_name, symbol)
# TODO: Move this data to dependencies.txt?
allowed_errors = (
("common/umutex.o", "operator new(unsigned long)"),
("common/umutex.o", "std::__throw_bad_alloc()"),
("common/umutex.o", "std::__throw_system_error(int)"),
("common/umutex.o", "std::uncaught_exception()"),
)
def _Resolve(name, parents):
global _ignored_symbols, _obj_files, _symbols_to_files, _return_value
item = dependencies.items[name]
@ -130,6 +143,9 @@ def _Resolve(name, parents):
imports -= exports | system_symbols
for symbol in imports:
for file_name in files:
if (file_name, symbol) in allowed_errors:
sys.stderr.write("Info: ignoring %s imports %s\n\n" % (file_name, symbol))
continue
if symbol in _obj_files[file_name]["imports"]:
neededFile = _symbols_to_files.get(symbol)
if neededFile in dependencies.file_to_item:
@ -138,7 +154,7 @@ def _Resolve(name, parents):
neededItem = "- is this a new system symbol?"
sys.stderr.write("Error: in %s %s: %s imports %s %s\n" %
(item_type, name, file_name, symbol, neededItem))
_return_value = 1
_return_value = 1
del parents[-1]
return item