mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-23 10:52:13 +00:00
libstrat: improve waitable manager cancelsync semantics
This commit is contained in:
parent
952ee4227d
commit
2894989eb7
1 changed files with 20 additions and 6 deletions
|
@ -60,6 +60,7 @@ class WaitableManager : public SessionManagerBase {
|
||||||
HosMutex process_lock;
|
HosMutex process_lock;
|
||||||
HosMutex signal_lock;
|
HosMutex signal_lock;
|
||||||
HosMutex add_lock;
|
HosMutex add_lock;
|
||||||
|
HosMutex cur_thread_lock;
|
||||||
bool has_new_waitables = false;
|
bool has_new_waitables = false;
|
||||||
|
|
||||||
IWaitable *next_signaled = nullptr;
|
IWaitable *next_signaled = nullptr;
|
||||||
|
@ -97,7 +98,7 @@ class WaitableManager : public SessionManagerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void CancelSynchronization() {
|
virtual void CancelSynchronization() {
|
||||||
svcCancelSynchronization(this->cur_thread_handle);
|
svcCancelSynchronization(GetProcessingThreadHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void NotifySignaled(IWaitable *w) override {
|
virtual void NotifySignaled(IWaitable *w) override {
|
||||||
|
@ -122,6 +123,16 @@ class WaitableManager : public SessionManagerBase {
|
||||||
ProcessLoop(this);
|
ProcessLoop(this);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
void SetProcessingThreadHandle(Handle h) {
|
||||||
|
std::scoped_lock<HosMutex> lk{this->cur_thread_lock};
|
||||||
|
this->cur_thread_handle = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle GetProcessingThreadHandle() {
|
||||||
|
std::scoped_lock<HosMutex> lk{this->cur_thread_lock};
|
||||||
|
return this->cur_thread_handle;
|
||||||
|
}
|
||||||
|
|
||||||
static void ProcessLoop(void *t) {
|
static void ProcessLoop(void *t) {
|
||||||
WaitableManager *this_ptr = (WaitableManager *)t;
|
WaitableManager *this_ptr = (WaitableManager *)t;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -141,17 +152,20 @@ class WaitableManager : public SessionManagerBase {
|
||||||
|
|
||||||
IWaitable *GetWaitable() {
|
IWaitable *GetWaitable() {
|
||||||
std::scoped_lock lk{this->process_lock};
|
std::scoped_lock lk{this->process_lock};
|
||||||
|
|
||||||
|
/* Set processing thread handle while in scope. */
|
||||||
|
SetProcessingThreadHandle(GetCurrentThreadHandle());
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
SetProcessingThreadHandle(INVALID_HANDLE);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Prepare variables for result. */
|
||||||
this->next_signaled = nullptr;
|
this->next_signaled = nullptr;
|
||||||
IWaitable *result = nullptr;
|
IWaitable *result = nullptr;
|
||||||
|
|
||||||
/* Add new waitables, if any. */
|
/* Add new waitables, if any. */
|
||||||
AddWaitablesInternal();
|
AddWaitablesInternal();
|
||||||
|
|
||||||
this->cur_thread_handle = GetCurrentThreadHandle();
|
|
||||||
ON_SCOPE_EXIT {
|
|
||||||
this->cur_thread_handle = INVALID_HANDLE;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* First, see if anything's already signaled. */
|
/* First, see if anything's already signaled. */
|
||||||
for (auto &w : this->waitables) {
|
for (auto &w : this->waitables) {
|
||||||
if (w->IsSignaled()) {
|
if (w->IsSignaled()) {
|
||||||
|
|
Loading…
Reference in a new issue