實例化C++實現類的對象
線程安全性
由於解釋器並沒有提供線程的調度功能,而是藉助宿主語言使用系統機制。而解釋器從一開始實現並不是線程安全,所以,所以呢?給線程的執行加了一個限制:線程函數除了可以訪問當前thread對象的數據外,不能訪問引擎當前變量池中的其他變量。
線程的邏輯,要保存到一個文件裏,有一個新的解析器對象去執行。與主線程中的解析器是隔離開的,做到互補干擾。缺點也一目瞭然:需要訪問的已有的全局變量,訪問不到。要想訪問:重新賦值,或者把數據塞給thread對象。
c++類
//thread.h
#pragma once
#include "varobject.h"
/**
腳本內部的變量存取,都是非線程安全的
*/
class CScript;
namespace os
{
class thread : public varobject
{
public:
//在腳本中展現的類名
static const char* get_script_classname() {return "thread";}
typedef struct st_thread_startup
{
HANDLE hEvent;
thread* pThread;
CStringA toRunFile;
}*lp_st_thread_startup;
thread(std::tr1::shared_ptr<_variant_>* pParams, DWORD dwParams);
~thread();
int QueryMethod(LPCSTR lpszMethodName);
BOOL CallMethod(int nMethodId, std::tr1::shared_ptr<_variant_>* pParams, DWORD dwParamN, std::tr1::shared_ptr<_variant_>& varR, std::tr1::shared_ptr<_variant_>* arrVarValue, DWORD dwCount);
protected:
unsigned start(const char* torunfile, unsigned stacksize, unsigned initflag);
protected:
static unsigned __stdcall thread_proc(void* lp);
std::tr1::shared_ptr<CScript> m_script;
};
}
//thead.cpp
#include "stdafx.h"
#include "thread.h"
#include "script.h"
#include "scriptinc.h"
namespace os
{
#define THREAD_METHOD_START 1
#define THREAD_METHOD_PAUSE 2
#define THREAD_METHOD_RESUME 3
#define THREAD_METHOD_STOP 4
#define THREAD_METHOD_WAIT 5
#define THREAD_METHOD_KILL 6
#define VARIANT_ID_NAME "id"
#define VARIANT_HANDLE_NAME "handle"
thread::thread(std::tr1::shared_ptr<_variant_>* pParams, DWORD dwParams)
{
append(VARIANT_ID_NAME, std::tr1::shared_ptr<_variant_>(new (std::nothrow)_variant_(0)));
append(VARIANT_HANDLE_NAME, std::tr1::shared_ptr<_variant_>(new (std::nothrow)_variant_(0)));
m_script.reset(new (std::nothrow) CScript());
}
thread::~thread()
{
m_script.reset();
}
int thread::QueryMethod(LPCSTR lpszMethodName)
{
if(_stricmp(lpszMethodName, "start") == 0)
return THREAD_METHOD_START;
if(_stricmp(lpszMethodName, "pause") == 0)
return THREAD_METHOD_PAUSE;
if(_stricmp(lpszMethodName, "resume") == 0)
return THREAD_METHOD_RESUME;
if(_stricmp(lpszMethodName, "wait") == 0)
return THREAD_METHOD_WAIT;
if(_stricmp(lpszMethodName, "kill") == 0)
return THREAD_METHOD_KILL;
return 0;
}
BOOL thread::CallMethod(int nMethodId, std::tr1::shared_ptr<_variant_>* pParams, DWORD dwParamN, std::tr1::shared_ptr<_variant_>& varR, std::tr1::shared_ptr<_variant_>* arrVarValue, DWORD dwCount)
{
BOOL lr = TRUE;
if(nMethodId == THREAD_METHOD_START)
{
unsigned id = 0;
if(dwParamN >= 1)
{
unsigned stack_size = 0;
unsigned initflag = 0;
if(dwParamN >= 2)
stack_size = (*(pParams + 1))->asUInt64();
if(dwParamN >= 3)
initflag = (*(pParams + 2))->asUInt64();
unsigned id = start((*pParams)->asCString(), stack_size, initflag);
}
varR.reset(new (std::nothrow) _variant_(id));
}
else if(nMethodId == THREAD_METHOD_PAUSE)
{
#ifdef _DEBUG
CStringA strLog;
strLog.Format("[script][thread][pause] 警告警告:掛起線程時,如果線程正在分配堆中的內存,線程將鎖定堆;腳本的臨時變量會new申請堆,造成卡死,不建議調用");
OutputDebugStringA(strLog);
ATLASSERT(FALSE);
#endif
DWORD dwRet = 0;
const std::tr1::shared_ptr<_variant_>& varHandle = find(VARIANT_HANDLE_NAME);
if(varHandle && varHandle->is_ui8())
{
HANDLE handle = (HANDLE)varHandle->asUInt64();
if(handle)
{
dwRet = ::SuspendThread(handle);
}
}
varR.reset(new (std::nothrow) _variant_(dwRet));
}
else if(nMethodId == THREAD_METHOD_RESUME)
{
DWORD dwRet = 0;
const std::tr1::shared_ptr<_variant_>& varHandle = find(VARIANT_HANDLE_NAME);
if(varHandle && varHandle->is_ui8())
{
HANDLE handle = (HANDLE)varHandle->asUInt64();
if(handle)
{
dwRet = ::ResumeThread(handle);
}
}
varR.reset(new (std::nothrow) _variant_(dwRet));
}
else if(nMethodId == THREAD_METHOD_WAIT)
{
DWORD ret = -1;
const std::tr1::shared_ptr<_variant_>& varHandle = find(VARIANT_HANDLE_NAME);
if(varHandle && varHandle->is_ui8())
{
HANDLE handle = (HANDLE)varHandle->asUInt64();
if(handle)
{
DWORD dwWait = 0;
if(dwParamN > 0)
dwWait = (*pParams)->asUInt64();
ret = ::WaitForSingleObject(handle, dwWait);
}
}
varR.reset(new (std::nothrow) _variant_(ret));
}
else if(nMethodId == THREAD_METHOD_KILL)
{
BOOL ret = FALSE;
const std::tr1::shared_ptr<_variant_>& varHandle = find(VARIANT_HANDLE_NAME);
if(varHandle && varHandle->is_ui8())
{
HANDLE handle = (HANDLE)varHandle->asUInt64();
if(handle)
{
#ifdef _DEBUG
CStringA strLog;
strLog.Format("[script][thread][kill] 警告警告:TerminateThread 不建議調用");
OutputDebugStringA(strLog);
ATLASSERT(FALSE);
#endif
DWORD exitcode = 0;
if(dwParamN >= 1)
exitcode = (*pParams)->asUInt64();
ret = ::TerminateThread(handle, exitcode);
}
}
varR.reset(new (std::nothrow) _variant_(ret));
}
else
lr = FALSE;
return lr;
}
unsigned thread::start(const char* torunfile, unsigned stacksize, unsigned initflag)
{
ATLASSERT(torunfile != NULL && strlen(torunfile) > 0);
unsigned id = 0;
st_thread_startup startup;
startup.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(startup.hEvent != NULL)
{
startup.pThread = this;
startup.toRunFile = torunfile;
uintptr_t handle = _beginthreadex(NULL, stacksize, thread_proc, &startup, initflag, &id);
if(handle > 0)
{
::WaitForSingleObject(startup.hEvent, INFINITE);
::CloseHandle(startup.hEvent);
modify(VARIANT_ID_NAME, std::tr1::shared_ptr<_variant_>(new (std::nothrow)_variant_(id)));
modify(VARIANT_HANDLE_NAME, std::tr1::shared_ptr<_variant_>(new (std::nothrow)_variant_(handle)));
}
}
return id;
}
unsigned __stdcall thread::thread_proc(void* lp)
{
st_thread_startup* pstartup = reinterpret_cast<st_thread_startup*>(lp);
if(pstartup)
{
thread* pThis = pstartup->pThread;
if(pThis)
{
CStringA toRunFile = pstartup->toRunFile;
#ifdef ENABLE_SCRIPT_DEBUGINFO_OUTPUT
CStringA strLog;
strLog.Format("[script][thread_proc] torunfile:%s", toRunFile);
#endif
if(pstartup->hEvent)
{
::SetEvent(pstartup->hEvent);
}
if(pThis->m_script)
{
//下面執行具體的線程邏輯
//在一個全新的script對象裏運行線程的函數
if(::PathFileExistsA(toRunFile))
{
pThis->m_script->ExecuteFromFile(toRunFile);
}
}
}
}
return 0;
}
}
腳本中實例化這個c++類
//實例化C++類
_thread = thread()
給類的實例添加一下數據
_thread.ext="text"
_thread.sum=10
完成的腳本例子
//mm.script, 腳本函數
for(i=0,i<100000,1)
js.debug.p("i")
end
_thread = thread()
_thread.ext="text"
_thread.sum=10
_thread.start("C:\\Users\\Administrator\\Desktop\\pack_236\\mm.script")
_thread.wait(2000)