Permalink
Browse files

Fix for GH-1: parallel async bufferify()s, test15.js.

  • Loading branch information...
1 parent 6c67ab7 commit 9ae31f737f4ddef007efdb51893d8a546bb69284 @xk committed May 18, 2011
View
Binary file not shown.
View
@@ -1,4 +1,4 @@
-# project noname (0.0.1) configured on Wed May 18 17:23:51 2011 by
+# project noname (0.0.1) configured on Wed May 18 23:36:18 2011 by
# waf 1.5.16 (abi 7, python 20601f0 on darwin)
# using /Users/jorge/JAVASCRIPT/bin/node-waf configure clean build
#
View
Binary file not shown.
View
Binary file not shown.
View
@@ -72,24 +72,27 @@ typedef struct bufferStruct {
#define kPlayCallbackQueueItemType 1
#define kRenderCallbackQueueItemType 2
#define kBufferListQueueItemType 3
+#define kRenderJobsListQueueItemType 4
typedef struct queueStruct {
void* item;
queueStruct* next;
queueStruct* last;
int type;
} queueStruct;
static queueStruct* callbacksQueue= NULL;
+static queueStruct* renderJobsQueue= NULL;
static ev_async eio_sound_async_notifier;
pthread_mutex_t callbacksQueue_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t renderJobsQueue_mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct renderJob {
char* str;
ssize_t strLen;
queueStruct* qHead;
ssize_t bytesRead;
v8::Persistent<v8::Object> JSCallback;
- pthread_t renderThread;
} renderJob;
+int gRenderingNow;
static v8::Persistent<String> volume_symbol;
static v8::Persistent<String> loop_symbol;
@@ -139,9 +142,10 @@ queueStruct* newQueueItem (void* item, int type, queueStruct* qHead) {
// = destroyQueueItem() =
// ======================
-queueStruct* destroyQueueItem (queueStruct* item) {
- queueStruct* next= item->next;
- free(item);
+queueStruct* destroyQueueItem (queueStruct* qitem) {
+ queueStruct* next= qitem->next;
+ if (next != NULL) next->last= qitem->last;
+ free(qitem);
return next;
}
@@ -978,21 +982,36 @@ v8::Handle<Value> BufferifySync (const Arguments &args) {
-// =================
-// = renderAsync() =
-// =================
+// ==================
+// = renderThread() =
+// ==================
-static void* renderAsync (void* ptr) {
+static void* renderThread (void* ptr) {
+
+ int RUN;
+ renderJob* job;
+ queueStruct* qitem;
- renderJob* job= (renderJob*) ptr;
- renderSound(job);
- queueStruct* qitem= newQueueItem(job, kRenderCallbackQueueItemType, NULL);
+ do {
+ job= (renderJob*) renderJobsQueue->item;
- pthread_mutex_lock(&callbacksQueue_mutex);
- if (callbacksQueue == NULL) callbacksQueue= qitem;
- else callbacksQueue->last->next= qitem;
- callbacksQueue->last= qitem;
- pthread_mutex_unlock(&callbacksQueue_mutex);
+ renderSound(job);
+ qitem= newQueueItem(job, kRenderCallbackQueueItemType, NULL);
+
+ pthread_mutex_lock(&callbacksQueue_mutex);
+ if (callbacksQueue == NULL) callbacksQueue= qitem;
+ else callbacksQueue->last->next= qitem;
+ callbacksQueue->last= qitem;
+ pthread_mutex_unlock(&callbacksQueue_mutex);
+
+
+ RUN= 0;
+ pthread_mutex_lock(&renderJobsQueue_mutex);
+ renderJobsQueue= destroyQueueItem(renderJobsQueue);
+ RUN= renderJobsQueue != NULL;
+ pthread_mutex_unlock(&renderJobsQueue_mutex);
+
+ } while (RUN);
ev_async_send(EV_DEFAULT_UC_ &eio_sound_async_notifier);
@@ -1015,8 +1034,11 @@ v8::Handle<Value> Bufferify (const Arguments &args) {
HandleScope scope;
+ int RUN;
renderJob* job;
+ pthread_t thread;
Local<String> str;
+ queueStruct* qitem;
if ((args.Length() != 2) || (!(args[0]->IsString() && args[1]->IsFunction()))) {
return ThrowException(Exception::TypeError(String::New("Sound::bufferify(): bad arguments")));
@@ -1031,7 +1053,21 @@ v8::Handle<Value> Bufferify (const Arguments &args) {
job->qHead= NULL;
job->JSCallback= v8::Persistent<v8::Object>::New(args[1]->ToObject());
- pthread_create(&job->renderThread, NULL, renderAsync, job);
+ // Grab the queue.
+ qitem= newQueueItem(job, kRenderJobsListQueueItemType, NULL);
+ pthread_mutex_lock(&renderJobsQueue_mutex);
+ if (renderJobsQueue == NULL) {
+ RUN= 1;
+ renderJobsQueue= qitem;
+ }
+ else {
+ RUN= 0;
+ renderJobsQueue->last->next= qitem;
+ }
+ renderJobsQueue->last= qitem;
+ pthread_mutex_unlock(&renderJobsQueue_mutex);
+
+ if (RUN) pthread_create(&thread, NULL, renderThread, NULL);
return Undefined();
}
View
@@ -1,26 +1,27 @@
-// test for async bufferify()s in series in a loop to detect leaks and other problems.
+// test for async bufferify()s IN SERIES in a loop to detect leaks and other problems.
var Sound= require('./build/default/sound');
-var sounds= ['Sous La Pluie.mp3', 'sound.wav', 'sound.aif', 'sound.mp3', 'sound.m4a', 'error.file'];
+var sounds= ['sound.wav', 'sound.aif', 'sound.au', 'sound.mp3', 'sound.m4a'];
var ctr= 0;
var i= sounds.length;
function next () {
if (--i<0) i= sounds.length-1;
- Sound.bufferify(sounds[i], cb.bind(sounds[i]));
+ var path= sounds[i];
+ Sound.bufferify(path, cb.bind(path));
}
function cb (err, buffer) {
var path= ''+ this;
- var ctrStr= '\n['+ (ctr++)+ '] *** ';
+ process.stdout.write('\n['+ (ctr++)+ '] *** -> ');
if (err) {
- process.stdout.write(ctrStr+ 'ERROR -> '+ path);
+ process.stdout.write('ERROR -> '+ path);
}
else {
- process.stdout.write(ctrStr+ 'OK -> '+ path);
+ process.stdout.write('OK -> '+ path);
}
next();
View
@@ -1,13 +1,7 @@
-// test for multiple async bufferify()s in parallel in a loop to detect leaks and other problems.
-
-// ==================================
-// = OOPS, SEGFAULTS EVERY TIME !!! =
-// ==================================
-
-// GRRR, Apple dice: (ExtAudioFileRead) This function works only on a single thread. If you want your application to read an audio file on multiple threads, use Audio File Services instead (en vez de *Extended* Audio File Services). :-(
+// test for multiple async bufferify()s IN PARALLEL in a loop to detect leaks and other problems.
var Sound= require('./build/default/sound');
-var sounds= ['sound.wav', 'sound.aif', 'sound.au', 'sound.m4a', 'sound.mp3', 'Sous La Pluie.mp3', 'error.file', 'sound.cc'];
+var sounds= ['sound.wav', 'sound.aif', 'sound.au', 'sound.m4a', 'sound.mp3'];
var ctr= 0;
var all= sounds.length;

0 comments on commit 9ae31f7

Please sign in to comment.