Threading primitives, in prep for removing Win32 from kernel/ and others.
This commit is contained in:
@@ -67,5 +67,130 @@ void Sleep(std::chrono::microseconds duration) {
|
||||
}
|
||||
}
|
||||
|
||||
class Win32Handle {
|
||||
public:
|
||||
Win32Handle(HANDLE handle) : handle_(handle) {}
|
||||
virtual ~Win32Handle() {
|
||||
CloseHandle(handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
HANDLE handle_ = nullptr;
|
||||
};
|
||||
|
||||
class Win32Event : public Event, public Win32Handle {
|
||||
public:
|
||||
Win32Event(HANDLE handle) : Win32Handle(handle) {}
|
||||
~Win32Event() = default;
|
||||
void Set() override { SetEvent(handle_); }
|
||||
void Reset() override { ResetEvent(handle_); }
|
||||
void Pulse() override { PulseEvent(handle_); }
|
||||
};
|
||||
|
||||
std::unique_ptr<Event> Event::CreateManualResetEvent(bool initial_state) {
|
||||
return std::make_unique<Win32Event>(
|
||||
CreateEvent(nullptr, TRUE, initial_state ? TRUE : FALSE, nullptr));
|
||||
}
|
||||
|
||||
std::unique_ptr<Event> Event::CreateAutoResetEvent(bool initial_state) {
|
||||
return std::make_unique<Win32Event>(
|
||||
CreateEvent(nullptr, FALSE, initial_state ? TRUE : FALSE, nullptr));
|
||||
}
|
||||
|
||||
class Win32Semaphore : public Semaphore, public Win32Handle {
|
||||
public:
|
||||
Win32Semaphore(HANDLE handle) : Win32Handle(handle) {}
|
||||
~Win32Semaphore() override = default;
|
||||
bool Release(int release_count, int* out_previous_count) override {
|
||||
return ReleaseSemaphore(handle_, release_count,
|
||||
reinterpret_cast<LPLONG>(out_previous_count))
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Semaphore> Semaphore::Create(int initial_count,
|
||||
int maximum_count) {
|
||||
return std::make_unique<Win32Semaphore>(
|
||||
CreateSemaphore(nullptr, initial_count, maximum_count, nullptr));
|
||||
}
|
||||
|
||||
class Win32Mutant : public Mutant, public Win32Handle {
|
||||
public:
|
||||
Win32Mutant(HANDLE handle) : Win32Handle(handle) {}
|
||||
~Win32Mutant() = default;
|
||||
bool Release() override { return ReleaseMutex(handle_) ? true : false; }
|
||||
};
|
||||
|
||||
std::unique_ptr<Mutant> Mutant::Create(bool initial_owner) {
|
||||
return std::make_unique<Win32Mutant>(
|
||||
CreateMutex(nullptr, initial_owner ? TRUE : FALSE, nullptr));
|
||||
}
|
||||
|
||||
class Win32Timer : public Timer, public Win32Handle {
|
||||
public:
|
||||
Win32Timer(HANDLE handle) : Win32Handle(handle) {}
|
||||
~Win32Timer() = default;
|
||||
bool SetOnce(std::chrono::nanoseconds due_time,
|
||||
std::function<void()> opt_callback) override {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
callback_ = std::move(opt_callback);
|
||||
LARGE_INTEGER due_time_li;
|
||||
due_time_li.QuadPart = due_time.count() / 100;
|
||||
auto completion_routine =
|
||||
opt_callback ? reinterpret_cast<PTIMERAPCROUTINE>(CompletionRoutine)
|
||||
: NULL;
|
||||
return SetWaitableTimer(handle_, &due_time_li, 0, completion_routine, this,
|
||||
FALSE)
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
bool SetRepeating(std::chrono::nanoseconds due_time,
|
||||
std::chrono::milliseconds period,
|
||||
std::function<void()> opt_callback) override {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
callback_ = std::move(opt_callback);
|
||||
LARGE_INTEGER due_time_li;
|
||||
due_time_li.QuadPart = due_time.count() / 100;
|
||||
auto completion_routine =
|
||||
opt_callback ? reinterpret_cast<PTIMERAPCROUTINE>(CompletionRoutine)
|
||||
: NULL;
|
||||
return SetWaitableTimer(handle_, &due_time_li, int32_t(period.count()),
|
||||
completion_routine, this, FALSE)
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
bool Cancel() override {
|
||||
// Reset the callback immediately so that any completions don't call it.
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
callback_ = nullptr;
|
||||
return CancelWaitableTimer(handle_) ? true : false;
|
||||
}
|
||||
|
||||
private:
|
||||
static void CompletionRoutine(Win32Timer* timer, DWORD timer_low,
|
||||
DWORD timer_high) {
|
||||
// As the callback may reset the timer, store local.
|
||||
std::function<void()> callback;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(timer->mutex_);
|
||||
callback = timer->callback_;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
std::mutex mutex_;
|
||||
std::function<void()> callback_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Timer> Timer::CreateManualResetTimer() {
|
||||
return std::make_unique<Win32Timer>(CreateWaitableTimer(NULL, TRUE, NULL));
|
||||
}
|
||||
|
||||
std::unique_ptr<Timer> Timer::CreateSynchronizationTimer() {
|
||||
return std::make_unique<Win32Timer>(CreateWaitableTimer(NULL, FALSE, NULL));
|
||||
}
|
||||
|
||||
} // namespace threading
|
||||
} // namespace xe
|
||||
|
||||
Reference in New Issue
Block a user