diff --git a/.gitignore b/.gitignore index 9622188..d3792e2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules npm-debug.log deps/minifier/bin/minify run-all-tests-output.log +package-lock.json \ No newline at end of file diff --git a/package.json b/package.json index 0febe93..6b9cfa3 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "url": "http://github.com/audreyt/node-webworker-threads.git" }, "scripts": { - "js": "env PATH=./node_modules/.bin:\"$PATH\" lsc -cj package.ls;\ngcc deps/minifier/src/minify.c -o deps/minifier/bin/minify;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/worker.ls > src/worker.js;\n./deps/minifier/bin/minify kWorker_js < src/worker.js > src/worker.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/events.ls > src/events.js;\n./deps/minifier/bin/minify kEvents_js < src/events.js > src/events.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/createPool.ls > src/createPool.js;\n./deps/minifier/bin/minify kCreatePool_js < src/createPool.js > src/createPool.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/thread_nextTick.ls > src/thread_nextTick.js;\n./deps/minifier/bin/minify kThread_nextTick_js 1 < src/thread_nextTick.js > src/thread_nextTick.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/load.ls > src/load.js;\n./deps/minifier/bin/minify kLoad_js 1 1 < src/load.js > src/load.js.c;", + "js": "env PATH=./node_modules/.bin:\"$PATH\" lsc -cj package.ls;\ngcc deps/minifier/src/minify.c -o deps/minifier/bin/minify;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/worker.ls > src/worker.js;\n./deps/minifier/bin/minify kWorker_js < src/worker.js > src/worker.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/events.ls > src/events.js;\n./deps/minifier/bin/minify kEvents_js < src/events.js > src/events.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/createPool.ls > src/createPool.js;\n./deps/minifier/bin/minify kCreatePool_js < src/createPool.js > src/createPool.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/thread_nextTick.ls > src/thread_nextTick.js;\n./deps/minifier/bin/minify kThread_nextTick_js 1 < src/thread_nextTick.js > src/thread_nextTick.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" ./deps/minifier/bin/minify kThread_timer_js 1 < src/thread_timer.js > src/thread_timer.js.c;\nenv PATH=./node_modules/.bin:\"$PATH\" lsc -cbp src/load.ls > src/load.js;\n./deps/minifier/bin/minify kLoad_js 1 1 < src/load.js > src/load.js.c;", "pretest": "npm run js && node-gyp rebuild", "test": "./run-all-tests.sh" }, diff --git a/package.ls b/package.ls index 4eac72a..761c859 100755 --- a/package.ls +++ b/package.ls @@ -33,6 +33,7 @@ scripts: ./deps/minifier/bin/minify kCreatePool_js < src/createPool.js > src/createPool.js.c; env PATH=./node_modules/.bin:"$PATH" lsc -cbp src/thread_nextTick.ls > src/thread_nextTick.js; ./deps/minifier/bin/minify kThread_nextTick_js 1 < src/thread_nextTick.js > src/thread_nextTick.js.c; + env PATH=./node_modules/.bin:"$PATH" ./deps/minifier/bin/minify kThread_timer_js 1 < src/thread_timer.js > src/thread_timer.js.c; env PATH=./node_modules/.bin:"$PATH" lsc -cbp src/load.ls > src/load.js; ./deps/minifier/bin/minify kLoad_js 1 1 < src/load.js > src/load.js.c; """ diff --git a/src/WebWorkerThreads.cc b/src/WebWorkerThreads.cc index cfe329b..ed8e12d 100644 --- a/src/WebWorkerThreads.cc +++ b/src/WebWorkerThreads.cc @@ -1,6 +1,9 @@ //2011-11 Proyectos Equis Ka, s.l., jorge@jorgechamorro.com //WebWorkerThreads.cc +// Modified By LostAbaddon +// 2018.02.08 +// Add setImmediate functon and timers. #include #include @@ -12,7 +15,6 @@ #include "nan.h" #include "nan_isolate_data_accessor.h" - #include "queues_a_gogo.cc" #include "bson.cc" #include "jslib.cc" @@ -88,7 +90,6 @@ typedef struct { } typeJob; /* - cd deps/minifier/src gcc minify.c -o minify cat ../../../src/events.js | ./minify kEvents_js > ../../../src/kEvents_js @@ -96,7 +97,6 @@ cat ../../../src/load.js | ./minify kLoad_js > ../../../src/kLoad_js cat ../../../src/createPool.js | ./minify kCreatePool_js > ../../../src/kCreatePool_js cat ../../../src/worker.js | ./minify kWorker_js > ../../../src/kWorker_js cat ../../../src/thread_nextTick.js | ./minify kThread_nextTick_js > ../../../src/kThread_nextTick_js - */ #include "events.js.c" @@ -104,16 +104,10 @@ cat ../../../src/thread_nextTick.js | ./minify kThread_nextTick_js > ../../../sr #include "createPool.js.c" #include "worker.js.c" #include "thread_nextTick.js.c" +#include "thread_timer.js.c" //node-waf configure uninstall distclean configure build install - - - - - - - static typeQueueItem* nuJobQueueItem (void) { typeQueueItem* qitem= queue_pull(freeJobsQueue); if (!qitem) { @@ -122,11 +116,6 @@ static typeQueueItem* nuJobQueueItem (void) { return qitem; } - - - - - static typeThread* isAThread (Local receiver) { typeThread* thread; @@ -142,11 +131,6 @@ static typeThread* isAThread (Local receiver) { return NULL; } - - - - - static void pushToInQueue (typeQueueItem* qitem, typeThread* thread) { uv_mutex_lock(&thread->IDLE_mutex); queue_push(qitem, &thread->inQueue); @@ -156,11 +140,6 @@ static void pushToInQueue (typeQueueItem* qitem, typeThread* thread) { uv_mutex_unlock(&thread->IDLE_mutex); } - - - - - NAN_METHOD(Puts) { Nan::HandleScope scope; int i= 0; @@ -171,28 +150,23 @@ NAN_METHOD(Puts) { } fflush(stdout); - //fprintf(stdout, "*** Puts END\n"); info.GetReturnValue().SetUndefined(); } NAN_METHOD(Print) { - Nan::HandleScope scope; - int i= 0; - while (i < info.Length()) { - String::Utf8Value c_str(info[i]); - fputs(*c_str, stdout); - i++; - } - static char end = '\n'; - fputs(&end, stdout); - fflush(stdout); - - //fprintf(stdout, "*** Puts END\n"); - info.GetReturnValue().SetUndefined(); -} - - + Nan::HandleScope scope; + int i= 0; + while (i < info.Length()) { + String::Utf8Value c_str(info[i]); + fputs(*c_str, stdout); + i++; + } + static char end = '\n'; + fputs(&end, stdout); + fflush(stdout); + info.GetReturnValue().SetUndefined(); +} static void eventLoop (typeThread* thread); @@ -213,7 +187,7 @@ static void aThread (void* arg) { NanSetIsolateData(thread->isolate, thread); if (useLocker) { - v8::Locker myLocker(thread->isolate); + v8::Locker myLocker(thread->isolate); // I think it's not ok to create a isolate scope here, // because it will call Isolate::Exit automatically. //v8::Isolate::Scope isolate_scope(thread->isolate); @@ -228,14 +202,10 @@ static void aThread (void* arg) { if (!(thread->inQueue.length)) uv_async_send(&thread->async_watcher); } - - NAN_METHOD(threadEmit); NAN_METHOD(postMessage); NAN_METHOD(postError); - - static void eventLoop (typeThread* thread) { Isolate::Scope isolate_scope(thread->isolate); @@ -244,13 +214,12 @@ static void eventLoop (typeThread* thread) { ExtensionConfiguration extensions(0, NULL); Local ftmpl = Nan::New(); - Local otmpl = ftmpl->InstanceTemplate(); + Local otmpl = ftmpl->InstanceTemplate(); Local ctx = Nan::New(&extensions, otmpl); - //thread->context= Context::New(); + // thread->context= Context::New(); thread->context.Reset(ctx); - ctx->Enter(); - + ctx->Enter(); Local global= Nan::New(thread->context)->Global(); @@ -279,15 +248,20 @@ static void eventLoop (typeThread* thread) { threadObject->Set(Nan::New("emit").ToLocalChecked(), Nan::New(threadEmit)->GetFunction()); Local dispatchEvents= Nan::CallAsFunction(Script::Compile(Nan::New(kEvents_js).ToLocalChecked())->Run()->ToObject(), threadObject, 0, NULL).ToLocalChecked()->ToObject(); Local dispatchNextTicks= Script::Compile(Nan::New(kThread_nextTick_js).ToLocalChecked())->Run()->ToObject(); + Local dispatchSetImmediate= Script::Compile(Nan::New(kThread_timer_js).ToLocalChecked())->Run()->ToObject(); Array* _ntq = Array::Cast(*threadObject->Get(Nan::New("_ntq").ToLocalChecked())); + Array* _nlp = Array::Cast(*threadObject->Get(Nan::New("_nlp").ToLocalChecked())); Script::Compile(Nan::New(kLoad_js).ToLocalChecked())->Run(); double nextTickQueueLength= 0; + double nextLoopQueueLength= 0; long int ctr= 0; + long int ctq= 0; while (!thread->sigkill) { + // printf("EventLoop Running...\n"); typeJob* job; typeQueueItem* qitem; @@ -298,20 +272,34 @@ static void eventLoop (typeThread* thread) { Local source; Local resultado; + // printf("Before Loop: %i, %f\n", _nlp->Length(), nextLoopQueueLength); + if (_nlp->Length()) { + if ((++ctq) > 2e3) { + ctq= 0; + Nan::IdleNotification(1000); + } - while ((qitem= queue_pull(&thread->inQueue))) { + resultado= Nan::CallAsFunction(dispatchSetImmediate, global, 0, NULL).ToLocalChecked(); + if (onError.HasCaught()) { + nextLoopQueueLength= 1; + onError.Reset(); + } + else { + nextLoopQueueLength= resultado->NumberValue(); + // printf("Inside Loop: %i, %f\n", _nlp->Length(), nextLoopQueueLength); + } + } + while ((qitem= queue_pull(&thread->inQueue))) { job= (typeJob*) qitem->asPtr; if ((++ctr) > 2e3) { ctr= 0; Nan::IdleNotification(1000); - } if (job->jobType == kJobTypeEval) { //Ejecutar un texto - if (job->typeEval.useStringObject) { str= job->typeEval.scriptText_StringObject; source= Nan::New(**str, (*str).length()).ToLocalChecked(); @@ -344,7 +332,6 @@ static void eventLoop (typeThread* thread) { } else if (job->jobType == kJobTypeEvent) { //Emitir evento. - Local info[2]; str= job->typeEvent.eventName; info[0]= Nan::New(**str, (*str).length()).ToLocalChecked(); @@ -371,28 +358,25 @@ static void eventLoop (typeThread* thread) { info[0]= Nan::New(**str, (*str).length()).ToLocalChecked(); delete str; - int len = job->typeEventSerialized.length; - Local array= Nan::New(len); - info[1]= array; - - { - BSON *bson = new BSON(); - char* data = job->typeEventSerialized.buffer; - size_t size = job->typeEventSerialized.bufferSize; - BSONDeserializer deserializer(bson, data, size); - Local result = deserializer.DeserializeDocument(true)->ToObject(); - int i = 0; do { array->Set(i, result->Get(i)); } while (++i < len); - free(data); - delete bson; - } - + int len = job->typeEventSerialized.length; + Local array= Nan::New(len); + info[1]= array; + { + BSON *bson = new BSON(); + char* data = job->typeEventSerialized.buffer; + size_t size = job->typeEventSerialized.bufferSize; + BSONDeserializer deserializer(bson, data, size); + Local result = deserializer.DeserializeDocument(true)->ToObject(); + int i = 0; do { array->Set(i, result->Get(i)); } while (++i < len); + free(data); + delete bson; + } queue_push(qitem, freeJobsQueue); Nan::CallAsFunction(dispatchEvents, global, 2, info); } } if (_ntq->Length()) { - if ((++ctr) > 2e3) { ctr= 0; Nan::IdleNotification(1000); @@ -405,11 +389,13 @@ static void eventLoop (typeThread* thread) { } else { nextTickQueueLength= resultado->NumberValue(); + // printf("Inside Tick: %i, %f\n", _ntq->Length(), nextTickQueueLength); } } } - if (nextTickQueueLength || thread->inQueue.length) continue; + // printf("End: %f, %f, %u, %li\n", nextTickQueueLength, nextLoopQueueLength, _nlp->Length(), thread->inQueue.length); + if (nextTickQueueLength || nextLoopQueueLength || _nlp->Length() || thread->inQueue.length) continue; if (thread->sigkill) break; uv_mutex_lock(&thread->IDLE_mutex); @@ -420,17 +406,10 @@ static void eventLoop (typeThread* thread) { } uv_mutex_unlock(&thread->IDLE_mutex); } - } - thread->context.Reset(); } - - - - - static void destroyaThread (typeThread* thread) { Nan::HandleScope scope; @@ -442,7 +421,6 @@ static void destroyaThread (typeThread* thread) { thread->JSObject.Reset(); uv_unref((uv_handle_t*)&thread->async_watcher); - #ifdef WIN32 TerminateThread(thread->thread, 1); #else @@ -450,11 +428,6 @@ static void destroyaThread (typeThread* thread) { #endif } - - - - - // C callback that runs in the main nodejs thread. This is the one responsible for // calling the thread's JS callback. static void Callback (uv_async_t *watcher, int revents) { @@ -477,7 +450,6 @@ static void Callback (uv_async_t *watcher, int revents) { job= (typeJob*) qitem->asPtr; if (job->jobType == kJobTypeEval) { - if (job->typeEval.tiene_callBack) { str= job->typeEval.resultado; @@ -512,9 +484,6 @@ static void Callback (uv_async_t *watcher, int revents) { } } else if (job->jobType == kJobTypeEvent) { - - //fprintf(stdout, "*** Callback\n"); - Local info[2]; str= job->typeEvent.eventName; @@ -547,16 +516,16 @@ static void Callback (uv_async_t *watcher, int revents) { Local array= Nan::New(len); info[1]= array; - { - BSON *bson = new BSON(); - char* data = job->typeEventSerialized.buffer; - size_t size = job->typeEventSerialized.bufferSize; - BSONDeserializer deserializer(bson, data, size); - Local result = deserializer.DeserializeDocument(true)->ToObject(); - int i = 0; do { array->Set(i, result->Get(i)); } while (++i < len); - free(data); - delete bson; - } + { + BSON *bson = new BSON(); + char* data = job->typeEventSerialized.buffer; + size_t size = job->typeEventSerialized.bufferSize; + BSONDeserializer deserializer(bson, data, size); + Local result = deserializer.DeserializeDocument(true)->ToObject(); + int i = 0; do { array->Set(i, result->Get(i)); } while (++i < len); + free(data); + delete bson; + } queue_push(qitem, freeJobsQueue); Nan::CallAsFunction(Nan::New(thread->dispatchEvents), Nan::New(thread->JSObject), 2, info); @@ -564,11 +533,6 @@ static void Callback (uv_async_t *watcher, int revents) { } } - - - - - // unconditionally destroys a thread by brute force. NAN_METHOD(Destroy) { Nan::HandleScope scope; @@ -589,11 +553,6 @@ NAN_METHOD(Destroy) { info.GetReturnValue().SetUndefined(); } - - - - - // Eval: Pushes a job into the thread's ->inQueue. NAN_METHOD(Eval){ Nan::HandleScope scope; @@ -623,10 +582,6 @@ NAN_METHOD(Eval){ info.GetReturnValue().Set(info.This()); } - - - - static char* readFile (Local path) { v8::String::Utf8Value c_str(path); FILE* fp= fopen(*c_str, "rb"); @@ -652,11 +607,6 @@ static char* readFile (Local path) { return buf; } - - - - - // Load: Loads from file and passes to Eval NAN_METHOD(Load) { Nan::HandleScope scope; @@ -690,11 +640,6 @@ NAN_METHOD(Load) { info.GetReturnValue().Set(info.This()); } - - - - - NAN_METHOD(processEmit) { Nan::HandleScope scope; @@ -744,21 +689,21 @@ NAN_METHOD(processEmitSerialized) { Local array= Nan::New(len-1); int i = 1; do { array->Set(i-1, info[i]); } while (++i < len); - { - char* buffer; - BSON *bson = new BSON(); - size_t object_size; - Local object = bson->GetSerializeObject(array); - BSONSerializer counter(bson, false, false); - counter.SerializeDocument(object); - object_size = counter.GetSerializeSize(); - buffer = (char *)malloc(object_size); - BSONSerializer data(bson, false, false, buffer); - data.SerializeDocument(object); - job->typeEventSerialized.buffer= buffer; - job->typeEventSerialized.bufferSize= object_size; - delete bson; - } + { + char* buffer; + BSON *bson = new BSON(); + size_t object_size; + Local object = bson->GetSerializeObject(array); + BSONSerializer counter(bson, false, false); + counter.SerializeDocument(object); + object_size = counter.GetSerializeSize(); + buffer = (char *)malloc(object_size); + BSONSerializer data(bson, false, false, buffer); + data.SerializeDocument(object); + job->typeEventSerialized.buffer= buffer; + job->typeEventSerialized.bufferSize= object_size; + delete bson; + } pushToInQueue(qitem, thread); @@ -783,21 +728,21 @@ NAN_METHOD(processEmitSerialized) { Local array= Nan::New(len); \ int i = 0; do { array->Set(i, info[i]); } while (++i < len); \ \ - { \ - char* buffer; \ - BSON *bson = new BSON(); \ - size_t object_size; \ - Local object = bson->GetSerializeObject(array); \ - BSONSerializer counter(bson, false, false); \ - counter.SerializeDocument(object); \ - object_size = counter.GetSerializeSize(); \ - buffer = (char *)malloc(object_size); \ - BSONSerializer data(bson, false, false, buffer); \ - data.SerializeDocument(object); \ - job->typeEventSerialized.buffer= buffer; \ - job->typeEventSerialized.bufferSize= object_size; \ - delete bson; \ - } \ + { \ + char* buffer; \ + BSON *bson = new BSON(); \ + size_t object_size; \ + Local object = bson->GetSerializeObject(array); \ + BSONSerializer counter(bson, false, false); \ + counter.SerializeDocument(object); \ + object_size = counter.GetSerializeSize(); \ + buffer = (char *)malloc(object_size); \ + BSONSerializer data(bson, false, false, buffer); \ + data.SerializeDocument(object); \ + job->typeEventSerialized.buffer= buffer; \ + job->typeEventSerialized.bufferSize= object_size; \ + delete bson; \ + } \ \ queue_push(qitem, &thread->outQueue); \ if (!(thread->inQueue.length)) uv_async_send(&thread->async_watcher); \ @@ -840,13 +785,6 @@ NAN_METHOD(threadEmit) { info.GetReturnValue().Set(info.This()); } - - - - - - - // Creates and launches a new isolate in a new background thread. NAN_METHOD(Create) { Nan::HandleScope scope; @@ -873,7 +811,7 @@ NAN_METHOD(Create) { thread->JSObject.Reset(local_JSObject); Local dispatchEvents= Nan::CallAsFunction(Script::Compile(Nan::New(kEvents_js).ToLocalChecked())->Run()->ToObject(), local_JSObject, 0, NULL).ToLocalChecked(); - Local local_dispatchEvents = dispatchEvents->ToObject(); + Local local_dispatchEvents = dispatchEvents->ToObject(); thread->dispatchEvents.Reset(local_dispatchEvents); uv_async_init(uv_default_loop(), &thread->async_watcher, reinterpret_cast(Callback)); @@ -895,15 +833,14 @@ NAN_METHOD(Create) { info.GetReturnValue().Set(Nan::New(thread->JSObject)); } - #if NODE_MODULE_VERSION >= 0x000E -void Init (Handle target, Handle module, void *) { +void Init (Handle target, Handle module, void *) #elif NODE_MODULE_VERSION >= 0x000B -void Init (Handle target, Handle module) { +void Init (Handle target, Handle module) #else -void Init (Handle target) { +void Init (Handle target) #endif - +{ initQueues(); freeThreadsQueue= nuQueue(-3); freeJobsQueue= nuQueue(-4); @@ -912,7 +849,8 @@ void Init (Handle target) { useLocker= v8::Locker::IsActive(); - target->Set(Nan::New("create").ToLocalChecked(), Nan::New(Create)->GetFunction()); + target->Set(Nan::New("create").ToLocalChecked(), + Nan::New(Create)->GetFunction()); target->Set(Nan::New("createPool").ToLocalChecked(), Script::Compile(Nan::New(kCreatePool_js).ToLocalChecked())->Run()->ToObject()); target->Set(Nan::New("Worker").ToLocalChecked(), @@ -929,11 +867,8 @@ void Init (Handle target) { threadTemplate.Reset(local_threadTemplate); } - - - NODE_MODULE(WebWorkerThreads, Init) /* gcc -E -I /Users/jorge/JAVASCRIPT/binarios/include/node -o /o.c /Users/jorge/JAVASCRIPT/threads_a_gogo/src/threads_a_gogo.cc && mate /o.c -*/ +*/ \ No newline at end of file diff --git a/src/jslib.cc b/src/jslib.cc index aa2344a..d137146 100644 --- a/src/jslib.cc +++ b/src/jslib.cc @@ -17,6 +17,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. +// Modified By LostAbaddon +// 2018.02.08 +// Changed the output format of console. + #include static const PropertyAttribute attribute_ro_dd = (PropertyAttribute)(ReadOnly | DontDelete); @@ -24,13 +28,13 @@ static const PropertyAttribute attribute_ro_de_dd = (PropertyAttribute)(ReadOnly // 'obj.name = fnname' with PropertyAttribute attribute_ro_dd. #define JSObjFn(obj, name, fnname) \ - Nan::DefineOwnProperty(obj, Nan::New(name).ToLocalChecked(), Nan::New(fnname)->GetFunction(), (PropertyAttribute)(DontDelete)); + Nan::DefineOwnProperty(obj, Nan::New(name).ToLocalChecked(), Nan::New(fnname)->GetFunction(), (PropertyAttribute)(DontDelete)); static void ReportException(Nan::TryCatch* try_catch) { - Nan::HandleScope scope; + Nan::HandleScope scope; String::Utf8Value exception(try_catch->Exception()); - Local message = try_catch->Message(); + Local message = try_catch->Message(); if (message.IsEmpty()) { printf("%s\n", *exception); @@ -72,13 +76,13 @@ static void ReportException(Nan::TryCatch* try_catch) { //static Local readFileSync_(const Arguments &info) { NAN_METHOD(readFileSync_) { - Nan::HandleScope scope; + Nan::HandleScope scope; - FILE *f = fopen(*String::Utf8Value(Local::Cast(info[0])), "rb"); + FILE *f = fopen(*String::Utf8Value(Local::Cast(info[0])), "rb"); if (f == NULL) { char str[256]; sprintf(str, "Error: readfile open failed. %d %s\n", errno, strerror(errno)); - return Nan::ThrowError(Nan::New(str).ToLocalChecked()); + return Nan::ThrowError(Nan::New(str).ToLocalChecked()); } fseek(f, 0, SEEK_END); size_t s = ftell(f); @@ -91,98 +95,112 @@ NAN_METHOD(readFileSync_) { sprintf(str, "Error: readfile read failed. %d %s\n", ferror(f), strerror(ferror(f))); delete[] buf; fclose(f); - Nan::ThrowError(str); + Nan::ThrowError(str); } buf[s] = 0; - Local str = Nan::New(buf).ToLocalChecked(); + Local str = Nan::New(buf).ToLocalChecked(); free(buf); fclose(f); - info.GetReturnValue().Set(str); + info.GetReturnValue().Set(str); } - - // console section -static inline void console_common_1(const Local &v, FILE* fd, const int deep) { +static inline void console_common_1(const Local &v, FILE* fd, const int deep, const bool inside) { char indent[36] = {}; + char tab = 0x20; int i, n; int mark = 0; for (i=0; i lv; + Local lv; if (v->IsFunction()) { - fprintf(fd, "%s[Function]\n", indent); - } else if (v->IsObject()) { - Local obj = Local::Cast(v); - Local ar = obj->GetPropertyNames(); - fprintf(fd, "%s{Object}\n", indent); - for (i=0, n=ar->Length(); iGet(ar->Get(i)); - fprintf(fd, "%s%s: ", indent, *(String::Utf8Value(Local::Cast(ar->Get(i))))); + fprintf(fd, "[Function]\n"); + } else if (v->IsArray()) { + Local obj = Local::Cast(v); + if (inside) fprintf(fd, "[\n"); + else fprintf(fd, "%s[\n", indent); + for (i=0, n=obj->Length(); iGet(i); if (lv->IsFunction()) { - fprintf(fd, "%s[Function]\n", indent); + fprintf(fd, "%s%c%c[Function]", indent, tab, tab); } else if (lv->IsObject() || lv->IsArray()) { - //fprintf(fd, "\n"); - console_common_1(lv, fd, deep+1); + fprintf(fd, "%s%c%c", indent, tab, tab); + console_common_1(lv, fd, deep+1, true); } else { - fprintf(fd, "%s%s\n", indent, *(String::Utf8Value(Local::Cast(lv)))); + fprintf(fd, "%s%c%c%s", indent, tab, tab, *(String::Utf8Value(Local::Cast(lv)))); + } + if (iIsArray()) { - Local obj = Local::Cast(v); - fprintf(fd, "%s[Array]\n", indent); - for (i=0, n=obj->Length(); iGet(i); - fprintf(fd, "%s%d: ", indent, i); + if (inside) fprintf(fd, "%s]", indent); + else fprintf(fd, "%s]\n", indent); + } else if (v->IsObject()) { + Local obj = Local::Cast(v); + Local ar = obj->GetPropertyNames(); + if (inside) fprintf(fd, "{\n"); + else fprintf(fd, "%s{\n", indent); + for (i=0, n=ar->Length(); iGet(ar->Get(i)); + // Print Key + fprintf(fd, "%s%c%c%s: ", indent, tab, tab, *(String::Utf8Value(Local::Cast(ar->Get(i))))); + // Pring Value if (lv->IsFunction()) { - fprintf(fd, "%s[Function]\n", indent); + fprintf(fd, "[Function]"); } else if (lv->IsObject() || lv->IsArray()) { - fprintf(fd, "\n"); - console_common_1(lv, fd, deep+1); + console_common_1(lv, fd, deep+1, true); } else { - fprintf(fd, "%s%s\n", indent, *(String::Utf8Value(Local::Cast(lv)))); + fprintf(fd, "%s", *(String::Utf8Value(Local::Cast(lv)))); + } + if (i::Cast(v)))); + fprintf(fd, "%s\n", *(String::Utf8Value(Local::Cast(v)))); } } NAN_METHOD(console_log) { - Nan::HandleScope scope; + Nan::HandleScope scope; Nan::TryCatch trycatch; - for (int i=0, n=info.Length(); i= 0) thread._nlp.splice(i, 1); + return this; + } + function dispatchSetImmediate(l, p, err, _nlp){ + _nlp = thread._nlp.map(i => i); + thread._nlp.splice(0, thread._nlp.length); + if (l = _nlp.length) { + err = 0; + try { + for (p = 0; p < l; p ++) { + _nlp[p](); + } + } catch (e) { + _nlp = _nlp.slice(++p); + _nlp.map(i => thread._nlp.push(i)); + throw e; + } + return _nlp.length; + } + return 0; + } + thread._nlp = []; + thread.setImmediate = setImmediate; + thread.clearImmediate = clearImmediate; + + thread.AllTimerTag = Symbol('AllTimerTag'); + var timerPool = []; + const getStamp = () => new Date().getTime(); + const invokeTask = () => { + var pending = [], now = getStamp(); + for (var i = 0, l = timerPool.length; i < l; i ++) { + let task = timerPool[i]; + if (task.expire <= now) { + pending.push(task); + if (!task.keep) { + timerPool.splice(i, 1); + l --; + i --; + } + } + else break; + } + if (timerPool.length > 0) setImmediate(invokeTask); + pending.map(task => { + var t = 0; + if (task.tag === 2 && task.delay !== 2) { + t = task.delay === 0 ? now : getStamp(); + } + task.func(); + if (task.tag === 2 && task.delay == 2) { + t = getStamp(); + } + if (task.tag === 2) { + task.expire = t + task.duration; + } + }); + }; + const dispatchTask = (task) => { + timerPool.push(task); + timerPool.sort((ta, tb) => ta.expire - tb.expire); + setImmediate(invokeTask); + }; + const removeTask = (tag, func) => { + var index = -1; + timerPool.some((task, i) => { + if (task.tag === tag && task.func === func) { + index = i; + return true; + } + }); + if (index < 0) return; + timerPool.splice(index, 1); + }; + const removeAllTask = (tag) => { + var l = timerPool.length, i; + for (i = l - 1; i >= 0; i --) { + let task = timerPool[i]; + if (task.tag === tag) { + timerPool.splice(i, 1); + } + } + }; + thread.setTimeout = (cb, delay) => { + delay = (delay * 1) || 0; + var data = { + tag: 1, + func: cb, + expire: getStamp() + delay, + duration: delay, + keep: false, + delay: 0 + }; + dispatchTask(data); + }; + thread.clearTimeout = cb => { + if (cb === thread.AllTimerTag) removeAllTask(1); + else removeTask(1, cb); + }; + thread.setInterval = (cb, delay, delayMode) => { + delay = (delay * 1) || 0; + var data = { + tag: 2, + func: cb, + expire: getStamp() + delay, + duration: delay, + keep: true, + delay: delayMode || 0 + }; + dispatchTask(data); + }; + thread.clearInterval = cb => { + if (cb === thread.AllTimerTag) removeAllTask(2); + else removeTask(2, cb); + }; + + return dispatchSetImmediate; +} diff --git a/src/thread_timer.js.c b/src/thread_timer.js.c new file mode 100644 index 0000000..67f946d --- /dev/null +++ b/src/thread_timer.js.c @@ -0,0 +1 @@ +static const char* kThread_timer_js= "(\n\x66\x75\x6e\x63\x74\x69\x6f\x6e \x54\x68\x72\x65\x61\x64\x53\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x29\x7b\x66\x75\x6e\x63\x74\x69\x6f\x6e \x73\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x63\x62\x29\x7b\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x70\x75\x73\x68\x28\x63\x62\x29\x3b\x72\x65\x74\x75\x72\x6e \x74\x68\x69\x73\x3b\x7d\n\x66\x75\x6e\x63\x74\x69\x6f\x6e \x63\x6c\x65\x61\x72\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x63\x62\x29\x7b\x76\x61\x72 \x69\x3d\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x69\x6e\x64\x65\x78\x4f\x66\x28\x63\x62\x29\x3b\x69\x66\x28\x69\x3e\x3d\x30\x29\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x73\x70\x6c\x69\x63\x65\x28\x69\x2c\x31\x29\x3b\x72\x65\x74\x75\x72\x6e \x74\x68\x69\x73\x3b\x7d\n\x66\x75\x6e\x63\x74\x69\x6f\x6e \x64\x69\x73\x70\x61\x74\x63\x68\x53\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x6c\x2c\x70\x2c\x65\x72\x72\x2c\x5f\x6e\x6c\x70\x29\x7b\x5f\x6e\x6c\x70\x3d\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x6d\x61\x70\x28\x69\x3d\x3e\x69\x29\x3b\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x73\x70\x6c\x69\x63\x65\x28\x30\x2c\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x6c\x65\x6e\x67\x74\x68\x29\x3b\x69\x66\x28\x6c\x3d\x5f\x6e\x6c\x70\x2e\x6c\x65\x6e\x67\x74\x68\x29\x7b\x65\x72\x72\x3d\x30\x3b\x74\x72\x79\x7b\x66\x6f\x72\x28\x70\x3d\x30\x3b\x70\x3c\x6c\x3b\x70\x2b\x2b\x29\x7b\x5f\x6e\x6c\x70\x5b\x70\x5d\x28\x29\x3b\x7d\x7d\x63\x61\x74\x63\x68\x28\x65\x29\x7b\x5f\x6e\x6c\x70\x3d\x5f\x6e\x6c\x70\x2e\x73\x6c\x69\x63\x65\x28\x2b\x2b\x70\x29\x3b\x5f\x6e\x6c\x70\x2e\x6d\x61\x70\x28\x69\x3d\x3e\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x2e\x70\x75\x73\x68\x28\x69\x29\x29\x3b\x74\x68\x72\x6f\x77 \x65\x3b\x7d\n\x72\x65\x74\x75\x72\x6e \x5f\x6e\x6c\x70\x2e\x6c\x65\x6e\x67\x74\x68\x3b\x7d\n\x72\x65\x74\x75\x72\x6e \x30\x3b\x7d\n\x74\x68\x72\x65\x61\x64\x2e\x5f\x6e\x6c\x70\x3d\x5b\x5d\x3b\x74\x68\x72\x65\x61\x64\x2e\x73\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x3d\x73\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x3b\x74\x68\x72\x65\x61\x64\x2e\x63\x6c\x65\x61\x72\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x3d\x63\x6c\x65\x61\x72\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x3b\x74\x68\x72\x65\x61\x64\x2e\x41\x6c\x6c\x54\x69\x6d\x65\x72\x54\x61\x67\x3d\x53\x79\x6d\x62\x6f\x6c\x28\x27\x41\x6c\x6c\x54\x69\x6d\x65\x72\x54\x61\x67\x27\x29\x3b\x76\x61\x72 \x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x3d\x5b\x5d\x3b\x63\x6f\x6e\x73\x74 \x67\x65\x74\x53\x74\x61\x6d\x70\x3d\x28\x29\x3d\x3e\x6e\x65\x77 \x44\x61\x74\x65\x28\x29\x2e\x67\x65\x74\x54\x69\x6d\x65\x28\x29\x3b\x63\x6f\x6e\x73\x74 \x69\x6e\x76\x6f\x6b\x65\x54\x61\x73\x6b\x3d\x28\x29\x3d\x3e\x7b\x76\x61\x72 \x70\x65\x6e\x64\x69\x6e\x67\x3d\x5b\x5d\x2c\x6e\x6f\x77\x3d\x67\x65\x74\x53\x74\x61\x6d\x70\x28\x29\x3b\x66\x6f\x72\x28\x76\x61\x72 \x69\x3d\x30\x2c\x6c\x3d\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x6c\x65\x6e\x67\x74\x68\x3b\x69\x3c\x6c\x3b\x69\x2b\x2b\x29\x7b\x6c\x65\x74 \x74\x61\x73\x6b\x3d\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x5b\x69\x5d\x3b\x69\x66\x28\x74\x61\x73\x6b\x2e\x65\x78\x70\x69\x72\x65\x3c\x3d\x6e\x6f\x77\x29\x7b\x70\x65\x6e\x64\x69\x6e\x67\x2e\x70\x75\x73\x68\x28\x74\x61\x73\x6b\x29\x3b\x69\x66\x28\x21\x74\x61\x73\x6b\x2e\x6b\x65\x65\x70\x29\x7b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x73\x70\x6c\x69\x63\x65\x28\x69\x2c\x31\x29\x3b\x6c\x2d\x2d\x3b\x69\x2d\x2d\x3b\x7d\x7d\n\x65\x6c\x73\x65 \x62\x72\x65\x61\x6b\x3b\x7d\n\x69\x66\x28\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x6c\x65\x6e\x67\x74\x68\x3e\x30\x29\x73\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x69\x6e\x76\x6f\x6b\x65\x54\x61\x73\x6b\x29\x3b\x70\x65\x6e\x64\x69\x6e\x67\x2e\x6d\x61\x70\x28\x74\x61\x73\x6b\x3d\x3e\x7b\x76\x61\x72 \x74\x3d\x30\x3b\x69\x66\x28\x74\x61\x73\x6b\x2e\x74\x61\x67\x3d\x3d\x3d\x32\x26\x26\x74\x61\x73\x6b\x2e\x64\x65\x6c\x61\x79\x21\x3d\x3d\x32\x29\x7b\x74\x3d\x74\x61\x73\x6b\x2e\x64\x65\x6c\x61\x79\x3d\x3d\x3d\x30\x3f\x6e\x6f\x77\x3a\x67\x65\x74\x53\x74\x61\x6d\x70\x28\x29\x3b\x7d\n\x74\x61\x73\x6b\x2e\x66\x75\x6e\x63\x28\x29\x3b\x69\x66\x28\x74\x61\x73\x6b\x2e\x74\x61\x67\x3d\x3d\x3d\x32\x26\x26\x74\x61\x73\x6b\x2e\x64\x65\x6c\x61\x79\x3d\x3d\x32\x29\x7b\x74\x3d\x67\x65\x74\x53\x74\x61\x6d\x70\x28\x29\x3b\x7d\n\x69\x66\x28\x74\x61\x73\x6b\x2e\x74\x61\x67\x3d\x3d\x3d\x32\x29\x7b\x74\x61\x73\x6b\x2e\x65\x78\x70\x69\x72\x65\x3d\x74\x2b\x74\x61\x73\x6b\x2e\x64\x75\x72\x61\x74\x69\x6f\x6e\x3b\x7d\x7d\x29\x3b\x7d\x3b\x63\x6f\x6e\x73\x74 \x64\x69\x73\x70\x61\x74\x63\x68\x54\x61\x73\x6b\x3d\x28\x74\x61\x73\x6b\x29\x3d\x3e\x7b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x70\x75\x73\x68\x28\x74\x61\x73\x6b\x29\x3b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x73\x6f\x72\x74\x28\x28\x74\x61\x2c\x74\x62\x29\x3d\x3e\x74\x61\x2e\x65\x78\x70\x69\x72\x65\x2d\x74\x62\x2e\x65\x78\x70\x69\x72\x65\x29\x3b\x73\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x28\x69\x6e\x76\x6f\x6b\x65\x54\x61\x73\x6b\x29\x3b\x7d\x3b\x63\x6f\x6e\x73\x74 \x72\x65\x6d\x6f\x76\x65\x54\x61\x73\x6b\x3d\x28\x74\x61\x67\x2c\x66\x75\x6e\x63\x29\x3d\x3e\x7b\x76\x61\x72 \x69\x6e\x64\x65\x78\x3d\x2d\x31\x3b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x73\x6f\x6d\x65\x28\x28\x74\x61\x73\x6b\x2c\x69\x29\x3d\x3e\x7b\x69\x66\x28\x74\x61\x73\x6b\x2e\x74\x61\x67\x3d\x3d\x3d\x74\x61\x67\x26\x26\x74\x61\x73\x6b\x2e\x66\x75\x6e\x63\x3d\x3d\x3d\x66\x75\x6e\x63\x29\x7b\x69\x6e\x64\x65\x78\x3d\x69\x3b\x72\x65\x74\x75\x72\x6e \x74\x72\x75\x65\x3b\x7d\x7d\x29\x3b\x69\x66\x28\x69\x6e\x64\x65\x78\x3c\x30\x29\x72\x65\x74\x75\x72\x6e\x3b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x73\x70\x6c\x69\x63\x65\x28\x69\x6e\x64\x65\x78\x2c\x31\x29\x3b\x7d\x3b\x63\x6f\x6e\x73\x74 \x72\x65\x6d\x6f\x76\x65\x41\x6c\x6c\x54\x61\x73\x6b\x3d\x28\x74\x61\x67\x29\x3d\x3e\x7b\x76\x61\x72 \x6c\x3d\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x6c\x65\x6e\x67\x74\x68\x2c\x69\x3b\x66\x6f\x72\x28\x69\x3d\x6c\x2d\x31\x3b\x69\x3e\x3d\x30\x3b\x69\x2d\x2d\x29\x7b\x6c\x65\x74 \x74\x61\x73\x6b\x3d\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x5b\x69\x5d\x3b\x69\x66\x28\x74\x61\x73\x6b\x2e\x74\x61\x67\x3d\x3d\x3d\x74\x61\x67\x29\x7b\x74\x69\x6d\x65\x72\x50\x6f\x6f\x6c\x2e\x73\x70\x6c\x69\x63\x65\x28\x69\x2c\x31\x29\x3b\x7d\x7d\x7d\x3b\x74\x68\x72\x65\x61\x64\x2e\x73\x65\x74\x54\x69\x6d\x65\x6f\x75\x74\x3d\x28\x63\x62\x2c\x64\x65\x6c\x61\x79\x29\x3d\x3e\x7b\x64\x65\x6c\x61\x79\x3d\x28\x64\x65\x6c\x61\x79\x2a\x31\x29\x7c\x7c\x30\x3b\x76\x61\x72 \x64\x61\x74\x61\x3d\x7b\x74\x61\x67\x3a\x31\x2c\x66\x75\x6e\x63\x3a\x63\x62\x2c\x65\x78\x70\x69\x72\x65\x3a\x67\x65\x74\x53\x74\x61\x6d\x70\x28\x29\x2b\x64\x65\x6c\x61\x79\x2c\x64\x75\x72\x61\x74\x69\x6f\x6e\x3a\x64\x65\x6c\x61\x79\x2c\x6b\x65\x65\x70\x3a\x66\x61\x6c\x73\x65\x2c\x64\x65\x6c\x61\x79\x3a\x30\x7d\x3b\x64\x69\x73\x70\x61\x74\x63\x68\x54\x61\x73\x6b\x28\x64\x61\x74\x61\x29\x3b\x7d\x3b\x74\x68\x72\x65\x61\x64\x2e\x63\x6c\x65\x61\x72\x54\x69\x6d\x65\x6f\x75\x74\x3d\x63\x62\x3d\x3e\x7b\x69\x66\x28\x63\x62\x3d\x3d\x3d\x74\x68\x72\x65\x61\x64\x2e\x41\x6c\x6c\x54\x69\x6d\x65\x72\x54\x61\x67\x29\x72\x65\x6d\x6f\x76\x65\x41\x6c\x6c\x54\x61\x73\x6b\x28\x31\x29\x3b\x65\x6c\x73\x65 \x72\x65\x6d\x6f\x76\x65\x54\x61\x73\x6b\x28\x31\x2c\x63\x62\x29\x3b\x7d\x3b\x74\x68\x72\x65\x61\x64\x2e\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x3d\x28\x63\x62\x2c\x64\x65\x6c\x61\x79\x2c\x64\x65\x6c\x61\x79\x4d\x6f\x64\x65\x29\x3d\x3e\x7b\x64\x65\x6c\x61\x79\x3d\x28\x64\x65\x6c\x61\x79\x2a\x31\x29\x7c\x7c\x30\x3b\x76\x61\x72 \x64\x61\x74\x61\x3d\x7b\x74\x61\x67\x3a\x32\x2c\x66\x75\x6e\x63\x3a\x63\x62\x2c\x65\x78\x70\x69\x72\x65\x3a\x67\x65\x74\x53\x74\x61\x6d\x70\x28\x29\x2b\x64\x65\x6c\x61\x79\x2c\x64\x75\x72\x61\x74\x69\x6f\x6e\x3a\x64\x65\x6c\x61\x79\x2c\x6b\x65\x65\x70\x3a\x74\x72\x75\x65\x2c\x64\x65\x6c\x61\x79\x3a\x64\x65\x6c\x61\x79\x4d\x6f\x64\x65\x7c\x7c\x30\x7d\x3b\x64\x69\x73\x70\x61\x74\x63\x68\x54\x61\x73\x6b\x28\x64\x61\x74\x61\x29\x3b\x7d\x3b\x74\x68\x72\x65\x61\x64\x2e\x63\x6c\x65\x61\x72\x49\x6e\x74\x65\x72\x76\x61\x6c\x3d\x63\x62\x3d\x3e\x7b\x69\x66\x28\x63\x62\x3d\x3d\x3d\x74\x68\x72\x65\x61\x64\x2e\x41\x6c\x6c\x54\x69\x6d\x65\x72\x54\x61\x67\x29\x72\x65\x6d\x6f\x76\x65\x41\x6c\x6c\x54\x61\x73\x6b\x28\x32\x29\x3b\x65\x6c\x73\x65 \x72\x65\x6d\x6f\x76\x65\x54\x61\x73\x6b\x28\x32\x2c\x63\x62\x29\x3b\x7d\x3b\x72\x65\x74\x75\x72\x6e \x64\x69\x73\x70\x61\x74\x63\x68\x53\x65\x74\x49\x6d\x6d\x65\x64\x69\x61\x74\x65\x3b\x7d)()"; diff --git a/test/nextloop.js b/test/nextloop.js new file mode 100644 index 0000000..f14e748 --- /dev/null +++ b/test/nextloop.js @@ -0,0 +1,5 @@ +var Threads = require('../'); +var worker = new Threads.Worker(__dirname + '/nextloop_worker.js'); +worker.addEventListener('close', () => { + worker.terminate(); +}); \ No newline at end of file diff --git a/test/nextloop_worker.js b/test/nextloop_worker.js new file mode 100644 index 0000000..1b79aa2 --- /dev/null +++ b/test/nextloop_worker.js @@ -0,0 +1,41 @@ +console.log('Welcome To Kosmos!!!'); + +var go = true; +var time = 0; +var limit = 1; + +const ticker = () => { + console.log('tick'); + if (time < limit) { + thread.nextTick(ticker); + time ++; + } + else { + time = 0; + go = true; + } +}; + +const looper = () => { + console.log('loop'); + thread.setImmediate(looper); + if (go) { + go = false; + thread.nextTick(ticker); + } +}; + +var test = () => { + console.log('>>>>>>>> FUCK!!!'); +}; +try { + // thread.setImmediate(looper); + thread.setInterval(test, 100); + thread.setTimeout(() => { + thread.clearInterval(test); + thread.emit('close'); + }, 100); +} +catch (err) { + console.log(err.message); +} \ No newline at end of file