-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
thread: add Windows implementation #5072
Changes from 4 commits
944dbea
d5b659a
da5e073
779530f
c4c2c4e
f78bdb9
2f95ad6
c6b0bec
2da255b
1138a93
fdfb693
0b13893
428dd06
91c440f
37c1832
cca7795
c7a1233
3d8d124
0d230f2
b0a5ab8
5b5cf22
e696f0d
a901bc0
f49b24f
70024c6
d37414b
d7e09c5
7d0acef
6313b4f
f6cb1ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "common/common/assert.h" | ||
#include "common/common/thread_impl.h" | ||
|
||
#ifdef __linux__ | ||
#include <sys/syscall.h> | ||
#elif defined(__APPLE__) | ||
#include <pthread.h> | ||
#endif | ||
|
||
namespace Envoy { | ||
namespace Thread { | ||
|
||
ThreadImplPosix::ThreadImplPosix(std::function<void()> thread_routine) | ||
: thread_routine_(thread_routine) { | ||
RELEASE_ASSERT(Logger::Registry::initialized(), ""); | ||
const int rc = pthread_create(&thread_handle_, nullptr, | ||
[](void* arg) -> void* { | ||
static_cast<ThreadImplPosix*>(arg)->thread_routine_(); | ||
return nullptr; | ||
}, | ||
this); | ||
RELEASE_ASSERT(rc == 0, ""); | ||
} | ||
|
||
void ThreadImplPosix::join() { | ||
const int rc = pthread_join(thread_handle_, nullptr); | ||
RELEASE_ASSERT(rc == 0, ""); | ||
} | ||
|
||
ThreadId currentThreadId() { | ||
#ifdef __linux__ | ||
return syscall(SYS_gettid); | ||
#elif defined(__APPLE__) | ||
uint64_t tid; | ||
pthread_threadid_np(NULL, &tid); | ||
return static_cast<int32_t>(tid); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is probably pre-existing, but IMO further evidence that I think we want an abstract base class for ThreadID. I could see also a subclass for Apple and a subclass for Linux I guess. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, this is pre-existing. We will probably hold off on splitting Apple from Linux, as we don't really have a set up for testing on OSX There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed; no need to add complexity here. |
||
#else | ||
#error "Enable and test pthread id retrieval code for you arch in pthread/thread_impl.cc" | ||
#endif | ||
} | ||
|
||
} // namespace Thread | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include <functional> | ||
|
||
#include "envoy/thread/thread.h" | ||
|
||
namespace Envoy { | ||
namespace Thread { | ||
|
||
/** | ||
* Wrapper for a pthread thread. We don't use std::thread because it eats exceptions and leads to | ||
* unusable stack traces. | ||
*/ | ||
class ThreadImplPosix : public Thread { | ||
public: | ||
ThreadImplPosix(std::function<void()> thread_routine); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW I suspect you don't need ThreadImplPosix to be exposed in the header -- it can be private to the ThreadFactoryImplPosix impl and in the cc file. This is not a big deal but I feel like it's nice to minimize what has to go into h files, for compile-speed and for human understanding of interfaces. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that we don't need ThreadImplPosix exposed in the header, but we do need ThreadImplWin32 exposed (so one of our Windows-specific classes can access data we don't want to put on the interface). It may be more consistent to have both exposed rather than one exposed and one placed in the cc file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK leave it exposed then, this is not a big deal, and if we do subclass Apple vs Linux in the future we'll need the shared posix impl exposed at least as a class declaration. |
||
|
||
/** | ||
* Join on thread exit. | ||
sesmith177 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
void join() override; | ||
|
||
private: | ||
std::function<void()> thread_routine_; | ||
pthread_t thread_handle_; | ||
}; | ||
|
||
/** | ||
* Implementation of ThreadFactory | ||
*/ | ||
class ThreadFactoryImplPosix : public ThreadFactory { | ||
public: | ||
ThreadFactoryImplPosix() {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. omit empty ctor. |
||
|
||
ThreadPtr createThread(std::function<void()> thread_routine) override { | ||
return std::make_unique<ThreadImplPosix>(thread_routine); | ||
} | ||
}; | ||
|
||
} // namespace Thread | ||
} // namespace Envoy |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#include <process.h> | ||
|
||
#include "common/common/assert.h" | ||
#include "common/common/thread_impl.h" | ||
|
||
namespace Envoy { | ||
namespace Thread { | ||
|
||
ThreadImplWin32::ThreadImplWin32(std::function<void()> thread_routine) | ||
: thread_routine_(thread_routine) { | ||
RELEASE_ASSERT(Logger::Registry::initialized(), ""); | ||
thread_handle_ = reinterpret_cast<HANDLE>( | ||
::_beginthreadex(nullptr, 0, | ||
[](void* arg) -> unsigned int { | ||
static_cast<ThreadImplWin32*>(arg)->thread_routine_(); | ||
return 0; | ||
}, | ||
this, 0, nullptr)); | ||
RELEASE_ASSERT(thread_handle_ != 0, ""); | ||
} | ||
|
||
ThreadImplWin32::~ThreadImplWin32() { ::CloseHandle(thread_handle_); } | ||
|
||
void ThreadImplWin32::join() { | ||
const DWORD rc = ::WaitForSingleObject(thread_handle_, INFINITE); | ||
RELEASE_ASSERT(rc == WAIT_OBJECT_0, ""); | ||
} | ||
|
||
ThreadId currentThreadId() { return ::GetCurrentThreadId(); } | ||
|
||
} // namespace Thread | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#pragma once | ||
|
||
#include <functional> | ||
|
||
#include "envoy/thread/thread.h" | ||
|
||
namespace Envoy { | ||
namespace Thread { | ||
|
||
/** | ||
* Wrapper for a win32 thread. We don't use std::thread because it eats exceptions and leads to | ||
* unusable stack traces. | ||
*/ | ||
class ThreadImplWin32 : public Thread { | ||
public: | ||
ThreadImplWin32(std::function<void()> thread_routine); | ||
~ThreadImplWin32(); | ||
|
||
/** | ||
* Join on thread exit. | ||
*/ | ||
sesmith177 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
void join() override; | ||
|
||
private: | ||
std::function<void()> thread_routine_; | ||
HANDLE thread_handle_; | ||
}; | ||
|
||
/** | ||
* Implementation of ThreadFactory | ||
*/ | ||
class ThreadFactoryImplWin32 : public ThreadFactory { | ||
public: | ||
ThreadFactoryImplWin32() {} | ||
|
||
ThreadPtr createThread(std::function<void()> thread_routine) override { | ||
return std::make_unique<ThreadImplWin32>(thread_routine); | ||
} | ||
}; | ||
|
||
} // namespace Thread | ||
} // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can avoid ifdefs in the interface here and instead have ThreadId be an abstract base class, which I'd give two or three methods:
-- compare to another ThreadID
-- determine if it's the current thread
-- serialize to a string for debug purposes
in the past I've done this this way: https://github.com/apache/incubator-pagespeed-mod/blob/20fbc5575c8fc825a137f6f1b2015829a9768f81/pagespeed/kernel/base/thread_system.h#L117
Note referenced there: https://linux.die.net/man/3/pthread_self