Switching std::thread to XThread and hosting in object_refs.

This commit is contained in:
Ben Vanik
2015-05-24 20:22:06 -07:00
parent 1104f8e687
commit fff1a7c132
7 changed files with 152 additions and 28 deletions

View File

@@ -45,7 +45,6 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
pcr_address_(0),
thread_state_address_(0),
thread_state_(0),
event_(NULL),
irql_(0) {
creation_params_.stack_size = stack_size;
creation_params_.xapi_thread_startup = xapi_thread_startup;
@@ -63,7 +62,7 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
apc_list_ = new NativeList(kernel_state->memory());
event_ = new XEvent(kernel_state);
event_ = object_ref<XEvent>(new XEvent(kernel_state));
event_->Initialize(true, false);
// The kernel does not take a reference. We must unregister in the dtor.
@@ -76,7 +75,7 @@ XThread::~XThread() {
delete apc_list_;
event_->Release();
event_.reset();
PlatformDestroy();
@@ -294,13 +293,12 @@ X_STATUS XThread::Exit(int exit_code) {
#if XE_PLATFORM_WIN32
static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
XThread* thread = reinterpret_cast<XThread*>(param);
auto thread = object_ref<XThread>(reinterpret_cast<XThread*>(param));
thread->set_name(thread->name());
xe::Profiler::ThreadEnter(thread->name().c_str());
current_thread_tls = thread;
current_thread_tls = thread.get();
thread->Execute();
current_thread_tls = nullptr;
thread->Release();
xe::Profiler::ThreadExit();
return 0;
}
@@ -339,12 +337,11 @@ X_STATUS XThread::PlatformExit(int exit_code) {
#else
static void* XThreadStartCallbackPthreads(void* param) {
XThread* thread = reinterpret_cast<XThread*>(param);
auto thread = object_ref<XThread>(reinterpret_cast<XThread*>(param));
xe::Profiler::ThreadEnter(thread->name().c_str());
current_thread_tls = thread;
current_thread_tls = thread.get();
thread->Execute();
current_thread_tls = nullptr;
thread->Release();
xe::Profiler::ThreadExit();
return 0;
}

View File

@@ -100,7 +100,7 @@ class XThread : public XObject {
std::mutex apc_lock_;
NativeList* apc_list_;
XEvent* event_;
object_ref<XEvent> event_;
};
class XHostThread : public XThread {

View File

@@ -24,6 +24,9 @@ namespace kernel {
class KernelState;
template <typename T>
class object_ref;
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
typedef struct {
xe::be<uint32_t> type_flags;
@@ -99,6 +102,124 @@ class XObject {
std::string name_; // May be zero length.
};
template <typename T>
class object_ref {
public:
object_ref() noexcept : value_(nullptr) {}
object_ref(nullptr_t) noexcept : value_(nullptr) {}
object_ref& operator=(nullptr_t) noexcept {
reset();
return (*this);
}
explicit object_ref(T* value) noexcept : value_(value) {
// Assumes retained on call.
}
explicit object_ref(const object_ref& right) noexcept {
reset(right.get());
if (value_) value_->Retain();
}
template <class V, class = typename std::enable_if<
std::is_convertible<V*, T*>::value, void>::type>
object_ref(const object_ref<V>& right) noexcept {
reset(right.get());
if (value_) value_->Retain();
}
object_ref(object_ref&& right) noexcept : value_(right.release()) {}
object_ref& operator=(object_ref&& right) noexcept {
object_ref(std::move(right)).swap(*this);
return (*this);
}
template <typename V>
object_ref& operator=(object_ref<V>&& right) noexcept {
object_ref(std::move(right)).swap(*this);
return (*this);
}
object_ref& operator=(const object_ref& right) noexcept {
object_ref(right).swap(*this);
return (*this);
}
template <typename V>
object_ref& operator=(const object_ref<V>& right) noexcept {
object_ref(right).swap(*this);
return (*this);
}
void swap(object_ref& right) noexcept {
std::_Swap_adl(value_, right.value_);
}
~object_ref() noexcept {
if (value_) {
value_->Release();
value_ = nullptr;
}
}
typename std::add_lvalue_reference<T>::type operator*() const {
return (*get());
}
T* operator->() const noexcept {
return std::pointer_traits<T*>::pointer_to(**this);
}
T* get() const noexcept { return value_; }
template <typename V>
V* get() const noexcept {
return reinterpret_cast<V*>(value_);
}
explicit operator bool() const noexcept { return value_ != nullptr; }
T* release() noexcept {
T* value = value_;
value_ = nullptr;
return value;
}
static void accept(T* value) {
reset(value);
value->Release();
}
void reset() noexcept { object_ref().swap(*this); }
void reset(T* value) noexcept { object_ref(value).swap(*this); }
private:
T* value_ = nullptr;
};
template <class _Ty>
bool operator==(const object_ref<_Ty>& _Left, nullptr_t) noexcept {
return (_Left.get() == (_Ty*)0);
}
template <class _Ty>
bool operator==(nullptr_t, const object_ref<_Ty>& _Right) noexcept {
return ((_Ty*)0 == _Right.get());
}
template <class _Ty>
bool operator!=(const object_ref<_Ty>& _Left, nullptr_t _Right) noexcept {
return (!(_Left == _Right));
}
template <class _Ty>
bool operator!=(nullptr_t _Left, const object_ref<_Ty>& _Right) noexcept {
return (!(_Left == _Right));
}
template <typename T>
object_ref<T> retain_object(T* ptr) {
if (ptr) ptr->Retain();
return object_ref<T>(ptr);
}
} // namespace kernel
} // namespace xe