static EjsWorker *initWorker(Ejs *ejs, EjsWorker *worker, Ejs *baseVM, cchar *name, EjsArray *search, cchar *scriptFile) { Ejs *wejs; EjsWorker *self; EjsName sname; static int workerSeqno = 0; ejsBlockGC(ejs); if (worker == 0) { worker = ejsCreateWorker(ejs); } worker->ejs = ejs; worker->state = EJS_WORKER_BEGIN; if (name) { worker->name = sclone(name); } else { lock(ejs); worker->name = sfmt("worker-%d", workerSeqno++); unlock(ejs); } /* Create a new interpreter and an "inside" worker object and pair it with the current "outside" worker. The worker interpreter gets a new dispatcher */ if (baseVM) { if ((wejs = ejsCloneVM(baseVM)) == 0) { ejsThrowMemoryError(ejs); return 0; } } else { if ((wejs = ejsCreateVM(0, 0, ejs->flags)) == 0) { ejsThrowMemoryError(ejs); return 0; } if (ejsLoadModules(wejs, 0, 0) < 0) { return 0; } } worker->pair = self = ejsCreateWorker(wejs); self->state = EJS_WORKER_BEGIN; self->ejs = wejs; self->inside = 1; self->pair = worker; self->name = sjoin("inside-", worker->name, NULL); #if MOB mprEnableDispatcher(wejs->dispatcher); #endif if (search) { ejsSetSearchPath(ejs, (EjsArray*) search); } // TODO - these should be don't delete ejsSetProperty(ejs, worker, ES_Worker_name, ejsCreateStringFromAsc(ejs, self->name)); ejsSetProperty(wejs, self, ES_Worker_name, ejsCreateStringFromAsc(wejs, self->name)); sname = ejsName(wejs, EJS_WORKER_NAMESPACE, "self"); ejsSetPropertyByName(wejs, wejs->global, sname, self); /* Workers have a dedicated namespace to enable viewing of the worker globals (self, onmessage, postMessage...) */ ejsDefineReservedNamespace(wejs, wejs->global, NULL, EJS_WORKER_NAMESPACE); addWorker(ejs, worker); if (scriptFile) { worker->scriptFile = sclone(scriptFile); worker->state = EJS_WORKER_STARTED; if (mprCreateEvent(wejs->dispatcher, "workerMain", 0, (MprEventProc) workerMain, self, 0) < 0) { mprRemoveItem(ejs->workers, worker); ejsThrowStateError(ejs, "Cannot create worker event"); return 0; } } return worker; }
/* * function Worker(script: String = null, options: Object = null) * * Script is optional. If supplied, the script is run immediately by a worker thread. This call * does not block. Options are: search and name. */ static EjsVar *workerConstructor(Ejs *ejs, EjsWorker *worker, int argc, EjsVar **argv) { Ejs *wejs; EjsVar *options, *value; EjsName qname; EjsWorker *self; cchar *search, *name; worker->ejs = ejs; worker->state = EJS_WORKER_BEGIN; options = (argc == 2) ? (EjsVar*) argv[1]: NULL; name = 0; search = ejs->ejsPath; if (options) { value = ejsGetPropertyByName(ejs, options, ejsName(&qname, "", "search")); if (ejsIsString(value)) { search = ejsGetString(value); } value = ejsGetPropertyByName(ejs, options, ejsName(&qname, "", "name")); if (ejsIsString(value)) { name = ejsGetString(value); } } if (name) { worker->name = mprStrdup(worker, name); } else { worker->name = mprAsprintf(worker, -1, "worker-%d", mprGetListCount(ejs->workers)); } /* * Create a new interpreter and an "inside" worker object and pair it with the current "outside" worker. */ wejs = ejsCreate(ejs->service, NULL, search, 0); if (wejs == 0) { ejsThrowMemoryError(ejs); return 0; } worker->pair = self = ejsCreateWorker(wejs); self->state = EJS_WORKER_BEGIN; self->ejs = wejs; self->inside = 1; self->pair = worker; self->name = mprStrcat(self, -1, "inside-", worker->name, NULL); ejsSetProperty(ejs, (EjsVar*) worker, ES_ejs_sys_Worker_name, (EjsVar*) ejsCreateString(ejs, self->name)); ejsSetProperty(wejs, (EjsVar*) self, ES_ejs_sys_Worker_name, (EjsVar*) ejsCreateString(wejs, self->name)); ejsSetProperty(wejs, wejs->global, ES_ejs_sys_worker_self, (EjsVar*) self); /* * Workers have a dedicated namespace to enable viewing of the worker globals (self, onmessage, postMessage...) */ ejsDefineReservedNamespace(wejs, wejs->globalBlock, 0, EJS_WORKER_NAMESPACE); /* * Make the inside worker permanent so we don't need to worry about whether worker->pair->ejs is valid */ self->obj.var.permanent = 1; if (argc > 0 && ejsIsPath(argv[0])) { addWorker(ejs, worker); worker->scriptFile = mprStrdup(worker, ((EjsPath*) argv[0])->path); worker->state = EJS_WORKER_STARTED; worker->obj.var.permanent = 1; if (mprStartWorker(ejs, (MprWorkerProc) workerMain, (void*) worker, MPR_NORMAL_PRIORITY) < 0) { ejsThrowStateError(ejs, "Can't start worker"); worker->obj.var.permanent = 0; return 0; } } return (EjsVar*) worker; }