open source
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
@file JSEnv.h
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2018_8_23
|
||||
*/
|
||||
|
||||
#ifndef __JSEnv_H__
|
||||
#define __JSEnv_H__
|
||||
|
||||
#include <v8.h>
|
||||
#include <libplatform/libplatform.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <misc/JCWorkerThread.h>
|
||||
#include <util/ListNode.h>
|
||||
#include "JSArrayBuffer.h"
|
||||
#include <util/Log.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
|
||||
namespace laya
|
||||
{
|
||||
void JSPrint( const char* p_sBuffer );
|
||||
void JSAlert( const char* p_sBuffer );
|
||||
void evalJS( const char* p_sSource );
|
||||
const char* ToCString(const v8::String::Utf8Value& value);
|
||||
|
||||
class Javascript
|
||||
{
|
||||
public:
|
||||
typedef std::recursive_mutex _MutexType;
|
||||
|
||||
typedef void(*voidfun)(void* data);
|
||||
|
||||
Javascript();
|
||||
|
||||
void init(int nPort);
|
||||
|
||||
//在init之后,并且在js线程的情况下,可以添加js导出
|
||||
//执行一段脚本。并立即退出。
|
||||
void run(const char* sSource );
|
||||
|
||||
//preRunFunc 是在执行脚本之前先执行的函数,例如可以做导出对象
|
||||
void run(const char* sSource, std::function<void(void)> preRunFunc );
|
||||
|
||||
//执行一个函数。并立即退出
|
||||
void run(voidfun func,void* pdata);
|
||||
|
||||
//不能在v8线程,在js退出后,可以进行js对象的清理
|
||||
void uninit();
|
||||
|
||||
void initJSEngine();
|
||||
|
||||
void uninitJSEngine();
|
||||
|
||||
public:
|
||||
static v8::Persistent<v8::Context> m_DebugMessageContext;
|
||||
v8::Isolate* m_pIsolate;
|
||||
v8::Platform* m_pPlatform;
|
||||
v8::Isolate::Scope* m_pScope;
|
||||
v8::HandleScope* m_pHandleScope;
|
||||
v8::Locker* m_pV8Locker;
|
||||
ArrayBufferAllocator* m_pABAlloc;
|
||||
_MutexType m_Lock;
|
||||
int m_nListenPort;
|
||||
};
|
||||
|
||||
|
||||
class JSThreadInterface
|
||||
{
|
||||
public:
|
||||
JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual void post(std::function<void(void)> func) = 0;
|
||||
virtual void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void initialize(int nPort) = 0;
|
||||
virtual void uninitialize() = 0;
|
||||
virtual void setLoopFunc(std::function<bool(void)> func) = 0;
|
||||
virtual void pushDbgFunc(std::function<void(void)> task) = 0;
|
||||
virtual void runDbgFuncs() = 0;
|
||||
virtual void waitAndRunDbgFuncs() = 0;
|
||||
virtual bool hasDbgFuncs() = 0;
|
||||
virtual JCWorkerThread* getWorker() = 0;
|
||||
virtual void run(Javascript::voidfun func,void* pData) = 0;
|
||||
virtual void clearFunc() = 0;
|
||||
};
|
||||
|
||||
class JSV8Worker : public JCWorkerThread
|
||||
{
|
||||
public:
|
||||
|
||||
JSV8Worker();
|
||||
|
||||
~JSV8Worker();
|
||||
|
||||
//因为要trycatch,所以只好再抄一份了
|
||||
virtual void _defRunLoop();
|
||||
|
||||
virtual void _runLoop();
|
||||
|
||||
public:
|
||||
|
||||
Javascript* m_pJS;
|
||||
|
||||
};
|
||||
|
||||
//把Javascript对象放到一个单独的线程中执行。
|
||||
class JSMulThread: public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
|
||||
JSMulThread()
|
||||
{
|
||||
m_kWorker.setThreadName("JavaScript Main");
|
||||
m_kWorker.m_pJS = &m_kJS;
|
||||
}
|
||||
|
||||
~JSMulThread()
|
||||
{
|
||||
//uninitialize();
|
||||
}
|
||||
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
m_kWorker.post(func);
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0)
|
||||
{
|
||||
m_kWorker.on(nEvent, func, (JCWorkerThread*)pInThread);
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kWorker.start();
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kWorker.stop();
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
m_kJS.init(nPort);
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
m_kJS.uninit();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
m_kWorker.setLoopFunc(func);
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFunction.push_back(task);
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
for (std::function<void(void)>& task : m_DbgFunction)
|
||||
{
|
||||
task();
|
||||
}
|
||||
m_DbgFunction.clear();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
bool bRet = false;
|
||||
m_DbgFuncLock.lock();
|
||||
bRet = m_DbgFunction.size() > 0;
|
||||
m_DbgFuncLock.unlock();
|
||||
return bRet;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return &m_kWorker;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
|
||||
std::mutex m_DbgFuncLock;
|
||||
JSV8Worker m_kWorker;
|
||||
Javascript m_kJS;
|
||||
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//把Javascript对象放到一个单独的线程中执行。
|
||||
class JSSingleThread : public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
|
||||
JSSingleThread()
|
||||
{
|
||||
|
||||
}
|
||||
~JSSingleThread()
|
||||
{
|
||||
//uninitialize();
|
||||
}
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.push_back(func);
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0)
|
||||
{
|
||||
switch (nEvent)
|
||||
{
|
||||
case JCWorkerThread::Event_threadStart:
|
||||
m_kStartFunc.func = func;
|
||||
m_kStartFunc.bDel = false;
|
||||
break;
|
||||
case JCWorkerThread::Event_threadStop:
|
||||
m_kStopFunc.func = func;
|
||||
m_kStopFunc.bDel = false;
|
||||
break;
|
||||
default:
|
||||
LOGE("JSSingleThread on() event type error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kStartFunc.func(NULL);
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kStopFunc.func(NULL);
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.init(nPort);
|
||||
m_kJS.initJSEngine();
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.uninit();
|
||||
m_kJS.uninitJSEngine();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
LOGE("JSSingleThread setLoopFunc error,You can't call this function on V8 Engine");
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFunction.push_back(task);
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
for (std::function<void(void)>& task : m_DbgFunction)
|
||||
{
|
||||
task();
|
||||
}
|
||||
m_DbgFunction.clear();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
bool bRet = false;
|
||||
m_DbgFuncLock.lock();
|
||||
bRet = m_DbgFunction.size() > 0;
|
||||
m_DbgFuncLock.unlock();
|
||||
return bRet;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
v8::TryCatch try_catch(m_kJS.m_pIsolate);
|
||||
runFunQueue();
|
||||
if (pData)func(pData);
|
||||
if (try_catch.HasCaught())
|
||||
{
|
||||
__JSRun::ReportException(m_kJS.m_pIsolate, &try_catch);
|
||||
}
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.clear();
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
public:
|
||||
|
||||
void runFunQueue()
|
||||
{
|
||||
std::vector<std::function<void(void)>> vWorkQueue;
|
||||
m_kQueueLock.lock();
|
||||
std::swap(vWorkQueue, m_vFuncQueue);
|
||||
m_kQueueLock.unlock();
|
||||
for (int i = 0; i < (int)vWorkQueue.size(); i++)
|
||||
{
|
||||
vWorkQueue[i]();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
|
||||
std::mutex m_DbgFuncLock;
|
||||
Javascript m_kJS;
|
||||
JCEventEmitter::EvtHandlerPack m_kStartFunc;
|
||||
JCEventEmitter::EvtHandlerPack m_kStopFunc;
|
||||
std::vector<std::function<void(void)>> m_vFuncQueue; //需要在此线程执行的函数的队列
|
||||
std::mutex m_kQueueLock;
|
||||
|
||||
};
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JSEnv_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
Reference in New Issue
Block a user