thread/{Thread,Id}: use defaul-initialized pthread_t as "undefined" value
Use the "==" operator instead of pthread_equal(). This allows us to eliminate two boolean flags which are there to avoid race conditions, and made the thing so fragile that I got tons of (correct) thread sanitizer warnings.
This commit is contained in:
parent
8649ea3d6f
commit
354104f9a9
@ -52,13 +52,11 @@ public:
|
|||||||
constexpr ThreadId(pthread_t _id):id(_id) {}
|
constexpr ThreadId(pthread_t _id):id(_id) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gcc_const
|
static constexpr ThreadId Null() noexcept {
|
||||||
static ThreadId Null() noexcept {
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
static ThreadId null;
|
return pthread_t();
|
||||||
return null;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +79,13 @@ public:
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool operator==(const ThreadId &other) const noexcept {
|
bool operator==(const ThreadId &other) const noexcept {
|
||||||
#ifdef _WIN32
|
/* note: not using pthread_equal() because that
|
||||||
|
function "is undefined if either thread ID is not
|
||||||
|
valid so we can't safely use it on
|
||||||
|
default-constructed values" (comment from
|
||||||
|
libstdc++) - and if both libstdc++ and libc++ get
|
||||||
|
away with this, we can do it as well */
|
||||||
return id == other.id;
|
return id == other.id;
|
||||||
#else
|
|
||||||
return pthread_equal(id, other.id);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,23 +35,10 @@ Thread::Start()
|
|||||||
if (handle == nullptr)
|
if (handle == nullptr)
|
||||||
throw MakeLastError("Failed to create thread");
|
throw MakeLastError("Failed to create thread");
|
||||||
#else
|
#else
|
||||||
#ifndef NDEBUG
|
|
||||||
creating = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int e = pthread_create(&handle, nullptr, ThreadProc, this);
|
int e = pthread_create(&handle, nullptr, ThreadProc, this);
|
||||||
|
|
||||||
if (e != 0) {
|
if (e != 0)
|
||||||
#ifndef NDEBUG
|
|
||||||
creating = false;
|
|
||||||
#endif
|
|
||||||
throw MakeErrno(e, "Failed to create thread");
|
throw MakeErrno(e, "Failed to create thread");
|
||||||
}
|
|
||||||
|
|
||||||
defined = true;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
creating = false;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,23 +54,13 @@ Thread::Join()
|
|||||||
handle = nullptr;
|
handle = nullptr;
|
||||||
#else
|
#else
|
||||||
pthread_join(handle, nullptr);
|
pthread_join(handle, nullptr);
|
||||||
defined = false;
|
handle = pthread_t();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
Thread::Run()
|
Thread::Run()
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
|
||||||
#ifndef NDEBUG
|
|
||||||
/* this works around a race condition that causes an assertion
|
|
||||||
failure due to IsInside() spuriously returning false right
|
|
||||||
after the thread has been created, and the calling thread
|
|
||||||
hasn't initialised "defined" yet */
|
|
||||||
defined = true;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
f();
|
f();
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
@ -40,17 +40,7 @@ class Thread {
|
|||||||
HANDLE handle = nullptr;
|
HANDLE handle = nullptr;
|
||||||
DWORD id;
|
DWORD id;
|
||||||
#else
|
#else
|
||||||
pthread_t handle;
|
pthread_t handle = pthread_t();
|
||||||
bool defined = false;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
/**
|
|
||||||
* The thread is currently being created. This is a workaround for
|
|
||||||
* IsInside(), which may return false until pthread_create() has
|
|
||||||
* initialised the #handle.
|
|
||||||
*/
|
|
||||||
bool creating = false;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -70,7 +60,7 @@ public:
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return handle != nullptr;
|
return handle != nullptr;
|
||||||
#else
|
#else
|
||||||
return defined;
|
return handle != pthread_t();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,11 +72,13 @@ public:
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetCurrentThreadId() == id;
|
return GetCurrentThreadId() == id;
|
||||||
#else
|
#else
|
||||||
#ifdef NDEBUG
|
/* note: not using pthread_equal() because that
|
||||||
constexpr bool creating = false;
|
function "is undefined if either thread ID is not
|
||||||
#endif
|
valid so we can't safely use it on
|
||||||
return IsDefined() && (creating ||
|
default-constructed values" (comment from
|
||||||
pthread_equal(pthread_self(), handle));
|
libstdc++) - and if both libstdc++ and libc++ get
|
||||||
|
away with this, we can do it as well */
|
||||||
|
return pthread_self() == handle;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user