mirror of
https://github.com/ldematte/HostedPumpkin
synced 2026-06-08 15:25:15 +00:00
126 lines
3.4 KiB
C++
126 lines
3.4 KiB
C++
#include "Task.h"
|
|
|
|
#include "../HostContext.h"
|
|
#include "../Logger.h"
|
|
|
|
const int INVALID_THREAD_ID = 0;
|
|
|
|
// Standard functions
|
|
|
|
SHTask::SHTask(SHTaskManager *pTaskManager, DWORD nativeThreadId, HANDLE hThread) {
|
|
m_cRef = 0;
|
|
m_pTaskManager = pTaskManager;
|
|
m_pTaskManager->AddRef();
|
|
m_nativeId = nativeThreadId;
|
|
m_hThread = hThread;
|
|
m_pCLRTask = NULL;
|
|
}
|
|
|
|
// For the current thread
|
|
SHTask::SHTask(SHTaskManager *pTaskManager, DWORD nativeThreadId) {
|
|
m_cRef = 0;
|
|
m_pTaskManager = pTaskManager;
|
|
m_pTaskManager->AddRef();
|
|
m_nativeId = nativeThreadId;
|
|
// Get a real handle from the "current thread" pseudo-handle
|
|
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
m_pCLRTask = NULL;
|
|
}
|
|
|
|
SHTask::~SHTask() {
|
|
if (m_nativeId != INVALID_THREAD_ID) {
|
|
m_pTaskManager->RemoveTask(m_nativeId);
|
|
}
|
|
|
|
//TODO: shutdown thread?
|
|
|
|
if (m_hThread != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(m_hThread);
|
|
}
|
|
|
|
if (m_pTaskManager) m_pTaskManager->Release();
|
|
if (m_pCLRTask) m_pCLRTask->Release();
|
|
}
|
|
|
|
// IUnknown functions
|
|
|
|
STDMETHODIMP_(DWORD) SHTask::AddRef() {
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(DWORD) SHTask::Release() {
|
|
ULONG cRef = InterlockedDecrement(&m_cRef);
|
|
if (cRef == 0)
|
|
delete this;
|
|
return cRef;
|
|
}
|
|
|
|
STDMETHODIMP SHTask::QueryInterface(const IID &riid, void **ppvObject) {
|
|
if (riid == IID_IUnknown || riid == IID_IHostTask) {
|
|
*ppvObject = this;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
// IHostTask functions
|
|
|
|
STDMETHODIMP SHTask::Start() {
|
|
Logger::Info("In Task::Start");
|
|
if (!ResumeThread(m_hThread)) {
|
|
Logger::Error("Couldn't resume thread");
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
VOID WINAPI APCFunc(ULONG_PTR) {
|
|
//Nothing to do in here
|
|
}
|
|
|
|
STDMETHODIMP SHTask::Alert() {
|
|
Logger::Info("In Task::Alert");
|
|
QueueUserAPC(APCFunc, m_hThread, NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP SHTask::Join(/* in */ DWORD dwMilliseconds, /* in */ DWORD dwOption) {
|
|
Logger::Info("In Task::Join %d milliseconds, %d options", dwMilliseconds, dwOption);
|
|
return HostContext::HostWait(m_hThread, dwMilliseconds, dwOption);
|
|
}
|
|
|
|
STDMETHODIMP SHTask::SetPriority(/* in */ int newPriority) {
|
|
Logger::Debug("In Task::SetPriority %d", newPriority);
|
|
|
|
// Do not allow managed threads (any of them) to increase their priority
|
|
// From MSDN: "A host can define its own algorithms for thread priority assignment, and is free to ignore this request."
|
|
if (newPriority > THREAD_PRIORITY_NORMAL && m_pTaskManager->IsSnippetThread(m_nativeId)) {
|
|
Logger::Debug("Ignoring high priority (%d) for snippet thread %d", newPriority, m_nativeId);
|
|
return S_OK;
|
|
}
|
|
|
|
if (!SetThreadPriority(m_hThread, newPriority)) {
|
|
Logger::Error("Couldn't set thread-priority");
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP SHTask::GetPriority(/* out */ int *pPriority) {
|
|
Logger::Info("In Task::GetPriority");
|
|
*pPriority = GetThreadPriority(m_hThread);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP SHTask::SetCLRTask(/* in */ ICLRTask *pCLRTask) {
|
|
Logger::Debug("In Task::SetCLRTask for %d -- clr: %x, host: %x", m_nativeId, pCLRTask, this);
|
|
m_pTaskManager->AddManagedTask(this, pCLRTask, m_nativeId);
|
|
m_pCLRTask = pCLRTask;
|
|
return S_OK;
|
|
}
|