include/AK/Tools/Win32/ThreadEmulation.h
Go to the documentation of this file.00001
00002
00003
00004
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #pragma once
00032
00033 namespace AK
00034 {
00035 namespace ThreadEmulation
00036 {
00037 HANDLE WINAPI CreateThread(__in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter, __in DWORD dwCreationFlags);
00038 DWORD WINAPI ResumeThread(__in HANDLE hThread);
00039 BOOL WINAPI SetThreadPriority(__in HANDLE hThread, __in int nPriority);
00040
00041 VOID WINAPI Sleep(__in DWORD dwMilliseconds);
00042 VOID WINAPI SleepEx(__in DWORD dwMilliseconds, BOOL in_bAlertable );
00043 }
00044 }
00045
00046 #ifdef AK_IMPLEMENT_THREAD_EMULATION
00047
00048 #include <assert.h>
00049 #include <vector>
00050 #include <set>
00051 #include <map>
00052 #include <mutex>
00053
00054 namespace AK
00055 {
00056 namespace ThreadEmulation
00057 {
00058
00059 struct PendingThreadInfo
00060 {
00061 LPTHREAD_START_ROUTINE lpStartAddress;
00062 LPVOID lpParameter;
00063 HANDLE completionEvent;
00064 int nPriority;
00065 };
00066
00067 static std::map<HANDLE, PendingThreadInfo> pendingThreads;
00068 static std::mutex pendingThreadsLock;
00069
00070
00071
00072 static Windows::System::Threading::WorkItemPriority GetWorkItemPriority(int nPriority)
00073 {
00074 if (nPriority < 0)
00075 return Windows::System::Threading::WorkItemPriority::Low;
00076 else if (nPriority > 0)
00077 return Windows::System::Threading::WorkItemPriority::High;
00078 else
00079 return Windows::System::Threading::WorkItemPriority::Normal;
00080 }
00081
00082
00083
00084 static void StartThread(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, HANDLE completionEvent, int nPriority)
00085 {
00086 auto workItemHandler = ref new Windows::System::Threading::WorkItemHandler([=](Windows::Foundation::IAsyncAction^)
00087 {
00088
00089 lpStartAddress(lpParameter);
00090
00091
00092 SetEvent(completionEvent);
00093 CloseHandle(completionEvent);
00094
00095 }, Platform::CallbackContext::Any);
00096
00097
00098 auto workItem = Windows::System::Threading::ThreadPool::RunAsync(workItemHandler, GetWorkItemPriority(nPriority), Windows::System::Threading::WorkItemOptions::TimeSliced );
00099
00100
00101 }
00102
00103
00104 HANDLE WINAPI CreateThread(__in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter, __in DWORD dwCreationFlags)
00105 {
00106
00107 assert((dwCreationFlags & ~CREATE_SUSPENDED) == 0);
00108
00109
00110 HANDLE threadHandle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, STANDARD_RIGHTS_ALL|EVENT_MODIFY_STATE);
00111
00112 if (!threadHandle)
00113 return nullptr;
00114
00115
00116
00117
00118 HANDLE completionEvent;
00119
00120 if (!DuplicateHandle(GetCurrentProcess(), threadHandle, GetCurrentProcess(), &completionEvent, 0, false, DUPLICATE_SAME_ACCESS))
00121 {
00122 CloseHandle(threadHandle);
00123 return nullptr;
00124 }
00125
00126 try
00127 {
00128 if (dwCreationFlags & CREATE_SUSPENDED)
00129 {
00130
00131 PendingThreadInfo info;
00132
00133 info.lpStartAddress = lpStartAddress;
00134 info.lpParameter = lpParameter;
00135 info.completionEvent = completionEvent;
00136 info.nPriority = 0;
00137
00138 std::lock_guard<std::mutex> lock(pendingThreadsLock);
00139
00140 pendingThreads[threadHandle] = info;
00141 }
00142 else
00143 {
00144
00145 StartThread(lpStartAddress, lpParameter, completionEvent, 0);
00146 }
00147
00148 return threadHandle;
00149 }
00150 catch (...)
00151 {
00152
00153 CloseHandle(threadHandle);
00154 CloseHandle(completionEvent);
00155
00156 return nullptr;
00157 }
00158 }
00159
00160
00161 DWORD WINAPI ResumeThread(__in HANDLE hThread)
00162 {
00163 std::lock_guard<std::mutex> lock(pendingThreadsLock);
00164
00165
00166 auto threadInfo = pendingThreads.find(hThread);
00167
00168 if (threadInfo == pendingThreads.end())
00169 {
00170
00171 assert(false);
00172 return (DWORD)-1;
00173 }
00174
00175 PendingThreadInfo& info = threadInfo->second;
00176
00177
00178 try
00179 {
00180 StartThread(info.lpStartAddress, info.lpParameter, info.completionEvent, info.nPriority);
00181 }
00182 catch (...)
00183 {
00184 return (DWORD)-1;
00185 }
00186
00187
00188 pendingThreads.erase(threadInfo);
00189
00190 return 0;
00191 }
00192
00193
00194 BOOL WINAPI SetThreadPriority(__in HANDLE hThread, __in int nPriority)
00195 {
00196 std::lock_guard<std::mutex> lock(pendingThreadsLock);
00197
00198
00199 auto threadInfo = pendingThreads.find(hThread);
00200
00201 if (threadInfo == pendingThreads.end())
00202 {
00203
00204 assert(false);
00205 return false;
00206 }
00207
00208
00209 threadInfo->second.nPriority = nPriority;
00210
00211 return true;
00212 }
00213
00214 VOID WINAPI Sleep(__in DWORD dwMilliseconds )
00215 {
00216 SleepEx( dwMilliseconds, FALSE );
00217 }
00218
00219 VOID WINAPI SleepEx(__in DWORD dwMilliseconds, BOOL in_bAlertable)
00220 {
00221 static HANDLE singletonEvent = nullptr;
00222
00223 HANDLE sleepEvent = singletonEvent;
00224
00225
00226 if (!sleepEvent)
00227 {
00228 sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, STANDARD_RIGHTS_ALL|EVENT_MODIFY_STATE);
00229
00230 if (!sleepEvent)
00231 return;
00232
00233 HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr);
00234
00235 if (previousEvent)
00236 {
00237
00238 CloseHandle(sleepEvent);
00239 sleepEvent = previousEvent;
00240 }
00241 }
00242
00243
00244 DWORD dwResult = WaitForSingleObjectEx(sleepEvent, dwMilliseconds, in_bAlertable);
00245 assert( dwResult != -1 );
00246 }
00247 }
00248 }
00249
00250 #endif
介绍一下自己的项目。我们会竭力为您提供帮助。
来注册自己的项目,我们帮您快速入门,不带任何附加条件!
开始 Wwise 之旅