On Sat, Nov 16, 2013 at 8:14 PM, João Henriques <[email protected]> wrote:
>
> I'm building a module to be used on a server application that does some
> heavy work on the background, and the best design I thought for
> not blocking node's main event loop was creating a new thread and a new
> event loop with libuv, keeping it referenced in the background until someone
> needs it,
>
>
> /**************************************************
>  * Module initialization
>  **************************************************/
>
> uv_loop_t *second_threaded_loop;
>
> void create_loop(void *)
> {
> uv_run(second_threaded_loop, UV_RUN_DEFAULT);
> }
>
> void init (Handle<Object> target)
> {
> NanScope();
>
> uv_thread_t thread_loop;
> uv_async_t async;
>
> second_threaded_loop = uv_loop_new();
>
> // Reference the second loop so it keeps on idle
> uv_async_init(second_threaded_loop, &async, NULL);
>
> uv_thread_create(&thread_loop, create_loop, NULL);
>
> // ....
> }
>
> /**************************************************
>  * Then, a random function running on
>  * the main loop does
>  **************************************************/
>
> NAN_METHOD(Foo::doHeavyOperation)
> {
> // ...
>
> uv_work_t* req = new uv_work_t;
>
> random_context_struct *ctx = new random_context_struct;
> // ctx->handle is a Handle<Object>
> ctx->handle = Persistent<Object>::New(args.This());
>
> req->data = /* random context */;
>
> uv_queue_work(second_threaded_loop, req, startHeavyOpeation, EmitMessage);
>
> // ....
>
> NanReturnUndefined();
> }
>
> /**************************************************
>  * After startHeavyOpeation ends, Emit Message is called
>  * Where it supossly should emit an event
>  * informing that the task finished
>  **************************************************/
>
> void EmitMessage(uv_work_t *req, int status)
> {
> random_context_struct *ctx = (random_context_struct*)req->data;
>
> Local<Value> argv[1] = { NanSymbol("parsed") };
>
> TryCatch tc;
>
> MakeCallback(ctx->handle, "done", 1, argv);
>
> if (tc.HasCaught())
> printf("Error occured");
> }
>
>
>
> Now, if I run this task on the main event loop the operation succeeds and
> the event is triggered,
> but in the second loop the application prematurely ends, without any
> explicit error being thrown, or being caught.
>
> A second loop to me seems the best idea, because blocking in the main event
> loop is not be acceptable as the server
> will be receiving new connections from other users. Creating a thread for
> each request would not be acceptable too,
> as the overhead would be unmanageable. A second event loop on a child thread
> seems a reasonably approach but emitting seems not to be possible.

V8 as it's used in node.js is not thread safe.  You cannot call V8
functions from another thread.*

Do you need a separate event loop?  The uv_queue_work() function runs
the work callback in a separate thread and invokes the done callback
on the original thread (i.e. the main thread.)

* V8 can be entered from different threads only if you use appropriate
mutual exclusion with v8::Locker and v8::Unlocker objects.  That won't
help in your case because your worker thread would block the main
thread if it somehow acquired the Locker.

-- 
-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

--- 
You received this message because you are subscribed to the Google Groups 
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to