int CsoundPerformanceThread::Perform() { int retval = 0; do { while (firstMessage) { csoundLockMutex(queueLock); do { CsoundPerformanceThreadMessage *msg; // get oldest message msg = (CsoundPerformanceThreadMessage*) firstMessage; if (!msg) break; // unlink from FIFO firstMessage = msg->nxt; if (!msg->nxt) lastMessage = (CsoundPerformanceThreadMessage*) 0; // process and destroy message retval = msg->run(); delete msg; } while (!retval); if (paused) csoundWaitThreadLock(pauseLock, (size_t) 0); // mark queue as empty csoundNotifyThreadLock(flushLock); csoundUnlockMutex(queueLock); // if error or end of score, return now if (retval) goto endOfPerf; // if paused, wait until a new message is received, then loop back if (!paused) break; // VL: if this is paused, then it will double lock. csoundWaitThreadLockNoTimeout(pauseLock); csoundNotifyThreadLock(pauseLock); } if(processcallback != NULL) processcallback(cdata); retval = csoundPerformKsmps(csound); } while (!retval); endOfPerf: status = retval; csoundCleanup(csound); // delete any pending messages csoundLockMutex(queueLock); { CsoundPerformanceThreadMessage *msg; msg = (CsoundPerformanceThreadMessage*) firstMessage; firstMessage = (CsoundPerformanceThreadMessage*) 0; lastMessage = (CsoundPerformanceThreadMessage*) 0; while (msg) { CsoundPerformanceThreadMessage *nxt = msg->nxt; delete msg; msg = nxt; } } csoundNotifyThreadLock(flushLock); csoundUnlockMutex(queueLock); running = 1; return retval; }
void CsoundPerformanceThread::FlushMessageQueue() { if (firstMessage) { csoundWaitThreadLockNoTimeout(flushLock); csoundNotifyThreadLock(flushLock); } }
int CsoundPerformanceThread::Join() { int retval; retval = status; if (perfThread) { pthread_cond_signal(&recordData.condvar); retval = csoundJoinThread(perfThread); perfThread = (void*) 0; } // delete any pending messages { CsoundPerformanceThreadMessage *msg; msg = (CsoundPerformanceThreadMessage*) firstMessage; firstMessage = (CsoundPerformanceThreadMessage*) 0; lastMessage = (CsoundPerformanceThreadMessage*) 0; while (msg) { CsoundPerformanceThreadMessage *nxt = msg->nxt; delete msg; msg = nxt; } } // delete all thread locks if (queueLock) { csoundDestroyMutex(queueLock); queueLock = (void*) 0; } if (pauseLock) { csoundNotifyThreadLock(pauseLock); csoundDestroyThreadLock(pauseLock); pauseLock = (void*) 0; } if (flushLock) { csoundNotifyThreadLock(flushLock); csoundDestroyThreadLock(flushLock); flushLock = (void*) 0; } return retval; }
PUBLIC void csoundDestroyThreadLock(void *threadLock) { CsoundThreadLock_t *p; if (threadLock == NULL) return; csoundNotifyThreadLock(threadLock); p = (CsoundThreadLock_t*) threadLock; pthread_cond_destroy(&(p->c)); pthread_mutex_destroy(&(p->m)); free(threadLock); }
void CsoundPerformanceThread::QueueMessage(CsoundPerformanceThreadMessage *msg) { if (status) { delete msg; return; } csoundLockMutex(queueLock); // link message into FIFO if (!lastMessage) firstMessage = msg; else lastMessage->nxt = msg; lastMessage = msg; // mark queue as non-empty csoundWaitThreadLock(flushLock, (size_t) 0); // wake up from pause csoundNotifyThreadLock(pauseLock); csoundUnlockMutex(queueLock); }
int CsoundPerformanceThread::Perform() { int retval = 0; do { while (firstMessage) { csoundLockMutex(queueLock); do { CsoundPerformanceThreadMessage *msg; // get oldest message msg = (CsoundPerformanceThreadMessage*) firstMessage; if (!msg) break; // unlink from FIFO firstMessage = msg->nxt; if (!msg->nxt) lastMessage = (CsoundPerformanceThreadMessage*) 0; // process and destroy message retval = msg->run(); delete msg; // TODO: This should be moved out of the Perform function } while (!retval); if (paused) csoundWaitThreadLock(pauseLock, (size_t) 0); // mark queue as empty csoundNotifyThreadLock(flushLock); csoundUnlockMutex(queueLock); // if error or end of score, return now if (retval) goto endOfPerf; // if paused, wait until a new message is received, then loop back if (!paused) break; // VL: if this is paused, then it will double lock. csoundWaitThreadLockNoTimeout(pauseLock); csoundNotifyThreadLock(pauseLock); } if(processcallback != NULL) processcallback(cdata); retval = csoundPerformKsmps(csound); if (recordData.running) { MYFLT *spout = csoundGetSpout(csound); int len = csoundGetKsmps(csound) * csoundGetNchnls(csound); if (csoundGet0dBFS(csound) != 1.0) { MYFLT zdbfs = csoundGet0dBFS(csound); MYFLT *modspout = spout; for (int i = 0; i < len; i++) { *modspout /= zdbfs; modspout++; } } int written = csoundWriteCircularBuffer(NULL, recordData.cbuf, spout, len); if (written != len) { csoundMessage(csound, "perfThread record buffer overrun."); } } pthread_cond_signal(&recordData.condvar); // Needs to be outside the if for the case where stop record was requested } while (!retval); endOfPerf: status = retval; csoundCleanup(csound); // delete any pending messages csoundLockMutex(queueLock); { CsoundPerformanceThreadMessage *msg; msg = (CsoundPerformanceThreadMessage*) firstMessage; firstMessage = (CsoundPerformanceThreadMessage*) 0; lastMessage = (CsoundPerformanceThreadMessage*) 0; while (msg) { CsoundPerformanceThreadMessage *nxt = msg->nxt; delete msg; msg = nxt; } } csoundNotifyThreadLock(flushLock); csoundUnlockMutex(queueLock); running = 1; return retval; }