include/AK/Tools/Win32/ThreadEmulation.h
説明を見る。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からはじめよう