Skip to content
This repository

Windows support #28

Closed
wants to merge 7 commits into from

6 participants

唐鳳 Roger Qiu Ricardo Stuven Nick Desaulniers xk SamJBarney
唐鳳

This fixes #24 and #25, allowing threads_a_gogo compilation on Windows with node 0.9.3+.

and others added some commits
xk Merge pull request #8 from fmgdias/patch-1
Added Includes <sys/time.h>, <sys/signal.h>, <sys/wait.h>
5676584
SamJBarney SamJBarney Implemented uv instead of ev 58ec09b
唐鳳 audreyt * Add binding.gyp for node-gyp building. a3ec46c
唐鳳 audreyt * Change typedefs to uv_*.
  Note that uv_cond_* is only supported by node 0.9.3+, so
  Windows support is not yet possible with node 0.8.x --
  but possibly in node 0.10.x.
(cherry picked from commit c4f120c)

Conflicts:

	src/threads_a_gogo.cc
1780ada
唐鳳 audreyt * Port more pthread_* to uv_*.
(cherry picked from commit 7a69a37)

Conflicts:

	src/threads_a_gogo.cc
aa12a25
唐鳳 audreyt * Finish pthread_* => uv_* porting.
  Now compiles on Win32, although doesn't yet work properly.
(cherry picked from commit 569ddd1)

Conflicts:

	src/threads_a_gogo.cc
9dcae9d
唐鳳 audreyt * Relax "os" support now we compile on Windows. f977e16
Nick Desaulniers

Is this necessary?

Roger Qiu

Does this support windows?

唐鳳

Yes, but only for Node.js 0.9.3 and later. Please refer to https://github.com/audreyt/node-webworker-threads for a backward-compatible for that also offers a WebWorker API that can be installed on Windows easily.

xk xk closed this
Ricardo Stuven

But can't install on Windows because the "os" setting in package.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 7 unique commits by 3 authors.

Apr 13, 2012
xk Merge pull request #8 from fmgdias/patch-1
Added Includes <sys/time.h>, <sys/signal.h>, <sys/wait.h>
5676584
Nov 02, 2012
SamJBarney SamJBarney Implemented uv instead of ev 58ec09b
唐鳳 audreyt * Add binding.gyp for node-gyp building. a3ec46c
Nov 10, 2012
唐鳳 audreyt * Change typedefs to uv_*.
  Note that uv_cond_* is only supported by node 0.9.3+, so
  Windows support is not yet possible with node 0.8.x --
  but possibly in node 0.10.x.
(cherry picked from commit c4f120c)

Conflicts:

	src/threads_a_gogo.cc
1780ada
唐鳳 audreyt * Port more pthread_* to uv_*.
(cherry picked from commit 7a69a37)

Conflicts:

	src/threads_a_gogo.cc
aa12a25
唐鳳 audreyt * Finish pthread_* => uv_* porting.
  Now compiles on Win32, although doesn't yet work properly.
(cherry picked from commit 569ddd1)

Conflicts:

	src/threads_a_gogo.cc
9dcae9d
唐鳳 audreyt * Relax "os" support now we compile on Windows. f977e16
This page is out of date. Refresh to see the latest.
8 binding.gyp
... ... @@ -0,0 +1,8 @@
  1 +{
  2 + 'targets': [
  3 + {
  4 + 'target_name': 'threads_a_gogo',
  5 + 'sources': [ 'src/threads_a_gogo.cc' ]
  6 + }
  7 + ]
  8 +}
7 package.json
@@ -26,11 +26,8 @@
26 26 "type": "git",
27 27 "url": "http://github.com/xk/node-threads-a-gogo.git"
28 28 },
29   - "scripts": {
30   - "install": "node-waf configure install"
31   - },
32   - "os": ["macos", "linux", "darwin"],
  29 + "gypfile": true,
33 30 "engines": {
34   - "node": ">=0.5.1"
  31 + "node": ">=0.8.0"
35 32 }
36 33 }
18 src/queues_a_gogo.cc
... ... @@ -1,11 +1,13 @@
1 1 //2011-11 Proyectos Equis Ka, s.l., jorge@jorgechamorro.com
2 2 //queues_a_gogo.cc
3 3
4   -#include <unistd.h>
5 4 #include <string.h>
6 5 #include <stdio.h>
7   -#include <pthread.h>
  6 +#include <uv.h>
8 7 #include <stdlib.h>
  8 +#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__) || defined(_AIX)
  9 +#include <unistd.h>
  10 +#endif
9 11
10 12 enum types {
11 13 kItemTypeNONE,
@@ -27,7 +29,7 @@ typedef struct typeQueueItem typeQueueItem;
27 29 typedef struct {
28 30 typeQueueItem* first;
29 31 typeQueueItem* last;
30   - pthread_mutex_t queueLock;
  32 + uv_mutex_t queueLock;
31 33 long int id;
32 34 volatile long int length;
33 35 } typeQueue;
@@ -41,7 +43,7 @@ static typeQueue* freeItemsQueue= NULL;
41 43 static void queue_push (typeQueueItem* qitem, typeQueue* queue) {
42 44 qitem->next= NULL;
43 45
44   - pthread_mutex_lock(&queue->queueLock);
  46 + uv_mutex_lock(&queue->queueLock);
45 47 if (queue->last) {
46 48 queue->last->next= qitem;
47 49 }
@@ -50,7 +52,7 @@ static void queue_push (typeQueueItem* qitem, typeQueue* queue) {
50 52 }
51 53 queue->last= qitem;
52 54 queue->length++;
53   - pthread_mutex_unlock(&queue->queueLock);
  55 + uv_mutex_unlock(&queue->queueLock);
54 56 }
55 57
56 58
@@ -59,7 +61,7 @@ static void queue_push (typeQueueItem* qitem, typeQueue* queue) {
59 61 static typeQueueItem* queue_pull (typeQueue* queue) {
60 62 typeQueueItem* qitem;
61 63
62   - pthread_mutex_lock(&queue->queueLock);
  64 + uv_mutex_lock(&queue->queueLock);
63 65 if ((qitem= queue->first)) {
64 66 if (queue->last == qitem) {
65 67 queue->first= queue->last= NULL;
@@ -70,7 +72,7 @@ static typeQueueItem* queue_pull (typeQueue* queue) {
70 72 queue->length--;
71 73 qitem->next= NULL;
72 74 }
73   - pthread_mutex_unlock(&queue->queueLock);
  75 + uv_mutex_unlock(&queue->queueLock);
74 76
75 77 return qitem;
76 78 }
@@ -124,7 +126,7 @@ static typeQueue* nuQueue (long int id) {
124 126 }
125 127 else {
126 128 queue= (typeQueue*) calloc(1, sizeof(typeQueue));
127   - pthread_mutex_init(&queue->queueLock, NULL);
  129 + uv_mutex_init(&queue->queueLock);
128 130 }
129 131
130 132 queue->id= id;
109 src/threads_a_gogo.cc
... ... @@ -1,15 +1,30 @@
1 1 //2011-11 Proyectos Equis Ka, s.l., jorge@jorgechamorro.com
2 2 //threads_a_gogo.cc
3 3
  4 +
4 5 #include <v8.h>
5 6 #include <node.h>
6   -#include <unistd.h>
  7 +#include <uv.h>
7 8 #include <string.h>
8 9 #include <stdio.h>
9   -#include <pthread.h>
10 10 #include <stdlib.h>
11 11 #include <string>
12 12
  13 +#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__) || defined(_AIX)
  14 +#define WWT_PTHREAD 1
  15 +#include <pthread.h>
  16 +#include <unistd.h>
  17 +#ifndef uv_cond_t
  18 +#define uv_cond_signal(x) pthread_cond_signal(x)
  19 +#define uv_cond_init(x) pthread_cond_init(x, NULL)
  20 +#define uv_cond_wait(x,y) pthread_cond_wait(x, y)
  21 +typedef pthread_cond_t uv_cond_t;
  22 +#endif
  23 +#else
  24 +#define pthread_setcancelstate(x,y) NULL
  25 +#define pthread_setcanceltype(x,y) NULL
  26 +#endif
  27 +
13 28 /*
14 29 static int debug_threads= 0;
15 30 static int debug_allocs= 0;
@@ -29,19 +44,19 @@ static typeQueue* freeThreadsQueue= NULL;
29 44
30 45 #define kThreadMagicCookie 0x99c0ffee
31 46 typedef struct {
32   - ev_async async_watcher; //MUST be the first one
  47 + uv_async_t async_watcher; //MUST be the first one
33 48
34 49 long int id;
35   - pthread_t thread;
  50 + uv_thread_t thread;
36 51 volatile int sigkill;
37 52
38 53 typeQueue inQueue; //Jobs to run
39 54 typeQueue outQueue; //Jobs done
40 55
41 56 volatile int IDLE;
42   - pthread_cond_t IDLE_cv;
43   - pthread_mutex_t IDLE_mutex;
44   -
  57 + uv_cond_t IDLE_cv;
  58 + uv_mutex_t IDLE_mutex;
  59 +
45 60 Isolate* isolate;
46 61 Persistent<Context> context;
47 62 Persistent<Object> JSObject;
@@ -138,12 +153,12 @@ static typeThread* isAThread (Handle<Object> receiver) {
138 153
139 154
140 155 static void pushToInQueue (typeQueueItem* qitem, typeThread* thread) {
141   - pthread_mutex_lock(&thread->IDLE_mutex);
  156 + uv_mutex_lock(&thread->IDLE_mutex);
142 157 queue_push(qitem, &thread->inQueue);
143 158 if (thread->IDLE) {
144   - pthread_cond_signal(&thread->IDLE_cv);
  159 + uv_cond_signal(&thread->IDLE_cv);
145 160 }
146   - pthread_mutex_unlock(&thread->IDLE_mutex);
  161 + uv_mutex_unlock(&thread->IDLE_mutex);
147 162 }
148 163
149 164
@@ -167,6 +182,21 @@ static Handle<Value> Puts (const Arguments &args) {
167 182 return Undefined();
168 183 }
169 184
  185 +static Handle<Value> Print (const Arguments &args) {
  186 + HandleScope scope;
  187 + int i= 0;
  188 + while (i < args.Length()) {
  189 + String::Utf8Value c_str(args[i]);
  190 + fputs(*c_str, stdout);
  191 + i++;
  192 + }
  193 + static char end = '\n';
  194 + fputs(&end, stdout);
  195 + fflush(stdout);
  196 +
  197 + //fprintf(stdout, "*** Puts END\n");
  198 + return Undefined();
  199 +}
170 200
171 201
172 202
@@ -174,8 +204,12 @@ static Handle<Value> Puts (const Arguments &args) {
174 204 static void eventLoop (typeThread* thread);
175 205
176 206 // A background thread
  207 +#ifdef WWT_PTHREAD
177 208 static void* aThread (void* arg) {
178   -
  209 +#else
  210 +static void aThread (void* arg) {
  211 +#endif
  212 +
179 213 int dummy;
180 214 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &dummy);
181 215 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy);
@@ -199,9 +233,10 @@ static void* aThread (void* arg) {
199 233 thread->isolate->Dispose();
200 234
201 235 // wake up callback
202   - if (!ev_async_pending(&thread->async_watcher)) ev_async_send(EV_DEFAULT_UC_ &thread->async_watcher);
203   -
  236 + if (!(thread->inQueue.length)) uv_async_send(&thread->async_watcher);
  237 +#ifdef WWT_PTHREAD
204 238 return NULL;
  239 +#endif
205 240 }
206 241
207 242
@@ -220,6 +255,7 @@ static void eventLoop (typeThread* thread) {
220 255
221 256 Local<Object> global= thread->context->Global();
222 257 global->Set(String::NewSymbol("puts"), FunctionTemplate::New(Puts)->GetFunction());
  258 + global->Set(String::NewSymbol("print"), FunctionTemplate::New(Print)->GetFunction());
223 259 Local<Object> threadObject= Object::New();
224 260 global->Set(String::NewSymbol("thread"), threadObject);
225 261
@@ -278,7 +314,7 @@ static void eventLoop (typeThread* thread) {
278 314 job->typeEval.resultado= new String::Utf8Value(job->typeEval.error ? onError.Exception() : resultado);
279 315 queue_push(qitem, &thread->outQueue);
280 316 // wake up callback
281   - if (!ev_async_pending(&thread->async_watcher)) ev_async_send(EV_DEFAULT_UC_ &thread->async_watcher);
  317 + if (!(thread->inQueue.length)) uv_async_send(&thread->async_watcher);
282 318 }
283 319 else {
284 320 queue_push(qitem, freeJobsQueue);
@@ -331,14 +367,14 @@ static void eventLoop (typeThread* thread) {
331 367
332 368 if (nextTickQueueLength || thread->inQueue.length) continue;
333 369 if (thread->sigkill) break;
334   -
335   - pthread_mutex_lock(&thread->IDLE_mutex);
  370 +
  371 + uv_mutex_lock(&thread->IDLE_mutex);
336 372 if (!thread->inQueue.length) {
337 373 thread->IDLE= 1;
338   - pthread_cond_wait(&thread->IDLE_cv, &thread->IDLE_mutex);
  374 + uv_cond_wait(&thread->IDLE_cv, &thread->IDLE_mutex);
339 375 thread->IDLE= 0;
340 376 }
341   - pthread_mutex_unlock(&thread->IDLE_mutex);
  377 + uv_mutex_unlock(&thread->IDLE_mutex);
342 378 }
343 379 }
344 380
@@ -359,8 +395,7 @@ static void destroyaThread (typeThread* thread) {
359 395 thread->JSObject->SetPointerInInternalField(0, NULL);
360 396 thread->JSObject.Dispose();
361 397
362   - ev_async_stop(EV_DEFAULT_UC_ &thread->async_watcher);
363   - ev_unref(EV_DEFAULT_UC);
  398 + uv_unref((uv_handle_t*)&thread->async_watcher);
364 399
365 400 if (freeThreadsQueue) {
366 401 queue_push(nuItem(kItemTypePointer, thread), freeThreadsQueue);
@@ -377,7 +412,7 @@ static void destroyaThread (typeThread* thread) {
377 412
378 413 // C callback that runs in the main nodejs thread. This is the one responsible for
379 414 // calling the thread's JS callback.
380   -static void Callback (EV_P_ ev_async *watcher, int revents) {
  415 +static void Callback (uv_async_t *watcher, int revents) {
381 416 typeThread* thread= (typeThread*) watcher;
382 417
383 418 if (thread->sigkill) {
@@ -420,7 +455,7 @@ static void Callback (EV_P_ ev_async *watcher, int revents) {
420 455
421 456 if (onError.HasCaught()) {
422 457 if (thread->outQueue.first) {
423   - ev_async_send(EV_DEFAULT_UC_ &thread->async_watcher); // wake up callback again
  458 + uv_async_send(&thread->async_watcher); // wake up callback again
424 459 }
425 460 node::FatalException(onError);
426 461 return;
@@ -474,11 +509,11 @@ static Handle<Value> Destroy (const Arguments &args) {
474 509 if (!thread->sigkill) {
475 510 //pthread_cancel(thread->thread);
476 511 thread->sigkill= 1;
477   - pthread_mutex_lock(&thread->IDLE_mutex);
  512 + uv_mutex_lock(&thread->IDLE_mutex);
478 513 if (thread->IDLE) {
479   - pthread_cond_signal(&thread->IDLE_cv);
  514 + uv_cond_signal(&thread->IDLE_cv);
480 515 }
481   - pthread_mutex_unlock(&thread->IDLE_mutex);
  516 + uv_mutex_unlock(&thread->IDLE_mutex);
482 517 }
483 518
484 519 return Undefined();
@@ -643,7 +678,7 @@ static Handle<Value> threadEmit (const Arguments &args) {
643 678 } while (++i <= job->typeEvent.length);
644 679
645 680 queue_push(qitem, &thread->outQueue);
646   - if (!ev_async_pending(&thread->async_watcher)) ev_async_send(EV_DEFAULT_UC_ &thread->async_watcher); // wake up callback
  681 + if (!(thread->inQueue.length)) uv_async_send(&thread->async_watcher); // wake up callback
647 682
648 683 //fprintf(stdout, "*** threadEmit END\n");
649 684
@@ -682,19 +717,23 @@ static Handle<Value> Create (const Arguments &args) {
682 717 Local<Value> dispatchEvents= Script::Compile(String::New(kEvents_js))->Run()->ToObject()->CallAsFunction(thread->JSObject, 0, NULL);
683 718 thread->dispatchEvents= Persistent<Object>::New(dispatchEvents->ToObject());
684 719
685   - ev_async_init(&thread->async_watcher, Callback);
686   - ev_async_start(EV_DEFAULT_UC_ &thread->async_watcher);
687   - ev_ref(EV_DEFAULT_UC);
688   -
689   - pthread_cond_init(&thread->IDLE_cv, NULL);
690   - pthread_mutex_init(&thread->IDLE_mutex, NULL);
691   - pthread_mutex_init(&thread->inQueue.queueLock, NULL);
692   - pthread_mutex_init(&thread->outQueue.queueLock, NULL);
  720 + uv_async_init(uv_default_loop(), &thread->async_watcher, Callback);
  721 + uv_ref((uv_handle_t*)&thread->async_watcher);
  722 +
  723 + uv_cond_init(&thread->IDLE_cv);
  724 + uv_mutex_init(&thread->IDLE_mutex);
  725 + uv_mutex_init(&thread->inQueue.queueLock);
  726 + uv_mutex_init(&thread->outQueue.queueLock);
  727 +
  728 +#ifdef WWT_PTHREAD
693 729 pthread_attr_t attr;
694 730 pthread_attr_init(&attr);
695 731 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
696 732 int err= pthread_create(&thread->thread, &attr, aThread, thread);
697 733 pthread_attr_destroy(&attr);
  734 +#else
  735 + int err= uv_thread_create(&thread->thread, aThread, thread);
  736 +#endif
698 737 if (err) {
699 738 //Ha habido un error no se ha arrancado esta thread
700 739 destroyaThread(thread);
@@ -739,4 +778,4 @@ NODE_MODULE(threads_a_gogo, Init)
739 778
740 779 /*
741 780 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
742   -*/
  781 +*/

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.