实例化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)