void* TempoClock::Run()
{
	//printf("->TempoClock::Run\n");
	pthread_mutex_lock (&gLangMutex);
	while (mRun) {
		assert(mQueue->size);
		//printf("tempo %g  dur %g  beats %g\n", mTempo, mBeatDur, mBeats);
		//printf("wait until there is something in scheduler\n");
		// wait until there is something in scheduler
		while (mQueue->size == 1) {
			//printf("wait until there is something in scheduler\n");
			pthread_cond_wait (&mCondition, &gLangMutex);
			//printf("mRun a %d\n", mRun);
			if (!mRun) goto leave;
		}
		//printf("wait until an event is ready\n");

		// wait until an event is ready
		double elapsedBeats;
		do {
			elapsedBeats = ElapsedBeats();
			if (elapsedBeats >= slotRawFloat(mQueue->slots)) break;
			struct timespec abstime;
			//doubleToTimespec(mQueue->slots->uf, &abstime);
			//printf("event ready at %g . elapsed beats %g\n", mQueue->slots->uf, elapsedBeats);
			double wakeTime = BeatsToSecs(slotRawFloat(mQueue->slots));
			ElapsedTimeToTimespec(wakeTime, &abstime);
			//printf("wait until an event is ready. wake %g  now %g\n", wakeTime, elapsedTime());
			pthread_cond_timedwait (&mCondition, &gLangMutex, &abstime);
			//printf("mRun b %d\n", mRun);
			if (!mRun) goto leave;
			//printf("time diff %g\n", elapsedTime() - mQueue->slots->uf);
		} while (mQueue->size > 1);
		//printf("perform all events that are ready %d %.9f\n", mQueue->size, elapsedBeats);

		// perform all events that are ready
		//printf("perform all events that are ready\n");
		while (mQueue->size > 1 && elapsedBeats >= slotRawFloat(mQueue->slots)) {
			double delta;
			PyrSlot task;

			//printf("while %.6f >= %.6f\n", elapsedBeats, mQueue->slots->uf);

			getheap(g, (PyrObject*)mQueue, &mBeats, &task);

			if (isKindOfSlot(&task, class_thread)) {
				SetNil(&slotRawThread(&task)->nextBeat);
			}

			slotCopy((++g->sp), &task);
			SetFloat(++g->sp, mBeats);
			SetFloat(++g->sp, BeatsToSecs(mBeats));
			++g->sp;	SetObject(g->sp, mTempoClockObj);

			runAwakeMessage(g);
			long err = slotDoubleVal(&g->result, &delta);
			if (!err) {
				// add delta time and reschedule
				double beats = mBeats + delta;
				Add(beats, &task);
			}
		}
	}
leave:
	//printf("<-TempoClock::Run\n");
	pthread_mutex_unlock (&gLangMutex);
	return 0;
}
void SC_TerminalClient::commandLoop()
{
	bool haveNext = false;
	struct timespec nextAbsTime;

	lockSignal();

	while( shouldBeRunning() )
	{

		while ( mSignals ) {
			int sig = mSignals;

			unlockSignal();

			if (sig & sig_input) {
				//postfl("input\n");
				lockInput();
				interpretInput();
				// clear input signal, as we've processed anything signalled so far.
				lockSignal();
				mSignals &= ~sig_input;
				unlockSignal();
				unlockInput();
			}

			if (sig & sig_sched) {
				//postfl("tick\n");
				double secs;
				lock();
				haveNext = tickLocked( &secs );
				// clear scheduler signal, as we've processed all items scheduled up to this time.
				// and will enter the wait according to schedule.
				lockSignal();
				mSignals &= ~sig_sched;
				unlockSignal();
				unlock();

				flush();

				//postfl("tick -> next time = %f\n", haveNext ? secs : -1);
				ElapsedTimeToTimespec( secs, &nextAbsTime );
			}

			if (sig & sig_stop) {
				stopMain();
				lockSignal();
				mSignals &= ~sig_stop;
				unlockSignal();
			}

			if (sig & sig_recompile) {
				recompileLibrary();
				lockSignal();
				mSignals &= ~sig_recompile;
				unlockSignal();
			}

			lockSignal();
		}

		if( !shouldBeRunning() ) {
			break;
		}
		else if( haveNext ) {
			int result = pthread_cond_timedwait( &mCond, &mSignalMutex, &nextAbsTime );
			if( result == ETIMEDOUT ) mSignals |= sig_sched;
		}
		else {
			pthread_cond_wait( &mCond, &mSignalMutex );
		}
	}

	unlockSignal();
}
void* schedRunFunc(void* arg)
{
	pthread_mutex_lock (&gLangMutex);


	VMGlobals *g = gMainVMGlobals;
	PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue);
	//dumpObject(inQueue);

	gRunSched = true;
	while (true) {
		assert(inQueue->size);

		//postfl("wait until there is something in scheduler\n");
		// wait until there is something in scheduler
		while (inQueue->size == 1) {
			//postfl("wait until there is something in scheduler\n");
			pthread_cond_wait (&gSchedCond, &gLangMutex);
			if (!gRunSched) goto leave;
		}
		//postfl("wait until an event is ready\n");

		// wait until an event is ready
		double elapsed;
		do {
			elapsed = elapsedTime();
			if (elapsed >= slotRawFloat(inQueue->slots + 1)) break;
			struct timespec abstime;
			//doubleToTimespec(inQueue->slots->uf, &abstime);
			ElapsedTimeToTimespec(slotRawFloat(inQueue->slots + 1), &abstime);
			//postfl("wait until an event is ready\n");
			pthread_cond_timedwait (&gSchedCond, &gLangMutex, &abstime);
			if (!gRunSched) goto leave;
			//postfl("time diff %g\n", elapsedTime() - inQueue->slots->uf);
		} while (inQueue->size > 1);

		//postfl("perform all events that are ready %d %.9f\n", inQueue->size, elapsed);

		// perform all events that are ready
		//postfl("perform all events that are ready\n");
		while ((inQueue->size > 1) && elapsed >= slotRawFloat(inQueue->slots + 1)) {
			double schedtime, delta;
			PyrSlot task;

			//postfl("while %.6f >= %.6f\n", elapsed, inQueue->slots->uf);

			getheap(g, inQueue, &schedtime, &task);

			if (isKindOfSlot(&task, class_thread)) {
				SetNil(&slotRawThread(&task)->nextBeat);
			}

			slotCopy((++g->sp), &task);
			SetFloat(++g->sp, schedtime);
			SetFloat(++g->sp, schedtime);
			++g->sp;	SetObject(g->sp, s_systemclock->u.classobj);

			runAwakeMessage(g);
			long err = slotDoubleVal(&g->result, &delta);
			if (!err) {
				// add delta time and reschedule
				double time = schedtime + delta;

				schedAdd(g, inQueue, time, &task);
			}
		}
		//postfl("loop\n");
	}
	//postfl("exitloop\n");
leave:
	pthread_mutex_unlock (&gLangMutex);
	return 0;
}
void SC_TerminalClient::commandLoop()
{
	bool haveNext = false;
	struct timespec nextAbsTime;

	lockSignal();

	while( shouldBeRunning() )
	{

		while ( mSignals ) {
			int sig = mSignals;
			mSignals = 0;

			unlockSignal();

			if (sig & sig_input) {
				//postfl("input\n");
				lockInput();
				interpretInput();
				unlockInput();
			}

			if (sig & sig_sched) {
				//postfl("tick\n");
				double secs;
				lock();
				haveNext = tickLocked( &secs );
				unlock();

				flush();

				//postfl("tick -> next time = %f\n", haveNext ? secs : -1);
				ElapsedTimeToTimespec( secs, &nextAbsTime );
			}

			if (sig & sig_stop) {
				stopMain();
			}

			if (sig & sig_recompile) {
				recompileLibrary();
			}

			lockSignal();
		}

		if( !shouldBeRunning() ) {
			break;
		}
		else if( haveNext ) {
			int result = pthread_cond_timedwait( &mCond, &mSignalMutex, &nextAbsTime );
			if( result == ETIMEDOUT ) mSignals |= sig_sched;
		}
		else {
			pthread_cond_wait( &mCond, &mSignalMutex );
		}
	}

	unlockSignal();
}