void TempoClock::Add(double inBeats, PyrSlot* inTask)
{
	double prevBeats = mQueue->size > 1 ? slotRawFloat(mQueue->slots) : -1e10;
	bool added = addheap(g, (PyrObject*)mQueue, inBeats, inTask);
	if (!added) post("scheduler queue is full.\n");
	else {
		if (isKindOfSlot(inTask, class_thread)) {
			SetFloat(&slotRawThread(inTask)->nextBeat, inBeats);
		}
		if (slotRawFloat(mQueue->slots) != prevBeats) {
			pthread_cond_signal (&mCondition);
		}
	}
}
void dumpheap(PyrObject *heapArg)
{
	PyrHeap * heap = (PyrHeap*)heapArg;
	double mintime = slotRawFloat(&heap->slots[0]);
	int count = slotRawFloat(&heap->slots[2]);
	int heapSize = heap->size - 1;
	post("SCHED QUEUE (%d)\n", heapSize);
	for (int i=0; i<heapSize; i+=3) {
		post("%3d(%3d) %9.2f %p %d\n", i/3, i, slotRawFloat(&heap->slots[i]), slotRawObject(&heap->slots[i+1]), slotRawInt(&heap->slots[i+2]));
		if ((slotRawFloat(&heap->slots[i]) < mintime)
			|| (slotRawFloat(&heap->slots[i]) == mintime && slotRawInt(&heap->slots[i+2]) < count )
		)
			post("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
	}
}
void schedAdd(VMGlobals *g, PyrObject* inQueue, double inSeconds, PyrSlot* inTask)
{
	// gLangMutex must be locked
	double prevTime = inQueue->size > 1 ? slotRawFloat(inQueue->slots + 1) : -1e10;
	bool added = addheap(g, inQueue, inSeconds, inTask);
	if (!added) post("scheduler queue is full.\n");
	else {
		if (isKindOfSlot(inTask, class_thread)) {
			SetFloat(&slotRawThread(inTask)->nextBeat, inSeconds);
		}
		if (slotRawFloat(inQueue->slots + 1) != prevTime) {
			//post("pthread_cond_signal\n");
			pthread_cond_signal (&gSchedCond);
		}
	}
}
void offsetheap(VMGlobals *g, PyrObject *heap, double offset)
{
	long i;
	for (i=0; i<heap->size; i+=2) {
		SetRaw(&heap->slots[i], slotRawFloat(&heap->slots[i]) + offset);
		//post("%3d %9.2f %9.2f\n", i>>1, heap->slots[i].uf, offset);
	}
}
bool lookheap(PyrObject *heap, double *schedtime, PyrSlot *task)
{
	if (heap->size > 1) {
		*schedtime = slotRawFloat(&heap->slots[0]);
		slotCopy(task, &heap->slots[1]);
		return true;
	} else return false;
}
示例#6
0
inline int prOpFloat(VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b;
	PyrSymbol *msg;

	a = g->sp - 1;
	b = g->sp;

	switch (GetTag(b)) {
		case tagInt :
			SetRaw(a, Functor::run(slotRawFloat(a), (double)slotRawInt(b)));
			break;
		case tagChar :
		case tagPtr :
		case tagNil :
		case tagFalse :
		case tagTrue :
			goto send_normal_2;
		case tagSym :
			SetSymbol(a, slotRawSymbol(b));
			break;
		case tagObj :
			if (isKindOf(slotRawObject(b), class_signal))
				SetObject(a, Functor::signal_fx(g, slotRawFloat(a), slotRawObject(b)));
			else
				goto send_normal_2;
			break;
		default :
			SetRaw(a, Functor::run(slotRawFloat(a), slotRawFloat(b)));
			break;
	}
	g->sp-- ; // drop
	g->numpop = 0;
#if TAILCALLOPTIMIZE
	g->tailCall = 0;
#endif
	return errNone;

	send_normal_2:
	if (numArgsPushed != -1)  // special case flag meaning it is a primitive
		return errFailed;	// arguments remain on the stack

	msg = gSpecialBinarySelectors[g->primitiveIndex];
	sendMessage(g, msg, 2);
	return errNone;
}
示例#7
0
int prAs32Bits(VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a = g->sp;
	// return an integer that is a bit pattern for the 32 bit float representation
	union { float f; int32 i; } u;
	u.f = slotRawFloat(a);
	SetInt(a, u.i);
	return errNone;
}
示例#8
0
static int addMsgSlot(big_scpacket *packet, PyrSlot *slot)
{
	switch (GetTag(slot)) {
		case tagInt :
			packet->addi(slotRawInt(slot));
			break;
		case tagSym :
			packet->adds(slotRawSymbol(slot)->name);
			break;
		case tagObj :
			if (isKindOf(slotRawObject(slot), class_string)) {
				PyrString *stringObj = slotRawString(slot);
				packet->adds(stringObj->s, stringObj->size);
			} else if (isKindOf(slotRawObject(slot), class_int8array)) {
				PyrInt8Array *arrayObj = slotRawInt8Array(slot);
				packet->addb(arrayObj->b, arrayObj->size);
			} else if (isKindOf(slotRawObject(slot), class_array)) {
				PyrObject *arrayObj = slotRawObject(slot);
				big_scpacket packet2;
				if (arrayObj->size > 1 && isKindOfSlot(arrayObj->slots+1, class_array)) {
					makeSynthBundle(&packet2, arrayObj->slots, arrayObj->size, true);
				} else {
					int error = makeSynthMsgWithTags(&packet2, arrayObj->slots, arrayObj->size);
					if (error != errNone)
						return error;
				}
				packet->addb((uint8*)packet2.data(), packet2.size());
			}
			break;
		case tagNil :
		case tagTrue :
		case tagFalse :
		case tagChar :
		case tagPtr :
			break;
		default :
			if (gUseDoubles) packet->addd(slotRawFloat(slot));
			else packet->addf(slotRawFloat(slot));
			break;
	}
	return errNone;
}
示例#9
0
void PriorityQueuePostpone(PyrObject* queueobj, double time)
{
	PyrSlot *schedqSlot = queueobj->slots;

	if (IsObj(schedqSlot)) {
		PyrObject *schedq = slotRawObject(schedqSlot);
		PyrSlot* slots = schedq->slots;
		for (int i=1; i < schedq->size; i+=3) {
			SetRaw(&slots[i], slotRawFloat(&slots[i]) + time);
		}
	}
}
示例#10
0
int prLow32Bits(VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a = g->sp;

#if BYTE_ORDER == BIG_ENDIAN
	union { struct { uint32 hi, lo; } i; double f; } du;
#else
	union { struct { uint32 lo, hi; } i; double f; } du;
#endif

	du.f = slotRawFloat(a);
	SetInt(a, du.i.lo);
	return errNone;
}
bool addheap(VMGlobals *g, PyrObject *heapArg, double schedtime, PyrSlot *task)
{
	PyrHeap * heap = (PyrHeap*)heapArg;
#ifdef GC_SANITYCHECK
	g->gc->SanityCheck();
#endif
	if (heap->size >= ARRAYMAXINDEXSIZE(heap))
		return false;
	assert(heap->size);

// 	post("->addheap\n");
// 	dumpheap(heapArg);

	/* parent and sibling in the heap, not in the task hierarchy */
	int mom = heap->size - 1;
	PyrSlot * pme = heap->slots + mom;
	int stabilityCount = slotRawInt(&heap->count);
	SetRaw(&heap->count, stabilityCount + 1);

	for (; mom>0;) {	/* percolate up heap */
		int newMom = ((mom - 3) / 2);
		mom = newMom - newMom % 3; /// LATER: we could avoid the division by using 4 slots per element
		PyrSlot * pmom = heap->slots + mom;
		if (schedtime < slotRawFloat(pmom)) {
			assert(slotRawInt(pmom + 2) < stabilityCount);
			slotCopy(&pme[0], &pmom[0]);
			slotCopy(&pme[1], &pmom[1]);
			slotCopy(&pme[2], &pmom[2]);
			pme = pmom;
		} else break;
	}
	SetFloat(&pme[0], schedtime);
	slotCopy(&pme[1], task);
	SetInt(&pme[2], stabilityCount);
	g->gc->GCWrite(heap, task);
	heap->size += 3;

#ifdef GC_SANITYCHECK
	g->gc->SanityCheck();
#endif
// 	dumpheap(heapArg);
// 	post("<-addheap %g\n", schedtime);
	return true;
}
示例#12
0
int prNetAddr_SendBundle(VMGlobals *g, int numArgsPushed)
{
	PyrSlot* netAddrSlot = g->sp - numArgsPushed + 1;
	PyrSlot* args = netAddrSlot + 1;
	big_scpacket packet;

	double time;
	int err = slotDoubleVal(args, &time);
	if (!err) {
		time += slotRawFloat(&g->thread->seconds);
		SetFloat(args, time);
	}
	int numargs = numArgsPushed - 1;
	makeSynthBundle(&packet, args, numargs, true);

	//for (int i=0; i<packet.size()/4; i++) post("%d %p\n", i, packet.buf[i]);

	return netAddrSend(slotRawObject(netAddrSlot), packet.size(), (char*)packet.buf);
}
示例#13
0
int mathFoldFloat(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *c;
	double lo, hi;
	int err;

	a = g->sp - 2;
	b = g->sp - 1;
	c = g->sp;

	if (IsSym(b)) {
		*a = *b;
	} else if (IsSym(c)) {
		*a = *c;
	} else {
		err = slotDoubleVal(b, &lo);
		if (err) return err;
		err = slotDoubleVal(c, &hi);
		if (err) return err;
		SetRaw(a, sc_fold(slotRawFloat(a), lo, hi));
	}
	return errNone;
}
示例#14
0
    void serialize(PyrSlot * slot)
    {
        if (IsFloat(slot)) {
            emitter << slotRawFloat(slot);
            return;
        }

        switch (GetTag(slot)) {
        case tagNil:
            emitter << YAML::Null;
            return;

        case tagInt:
            emitter << slotRawInt(slot);
            return;

        case tagFalse:
            emitter << false;
            return;

        case tagTrue:
            emitter << true;
            return;

        case tagObj:
            serialize(slotRawObject(slot));
            return;

        case tagSym:
            emitter << YAML::DoubleQuoted << slotRawSymbol(slot)->name;
            return;

        default:
            printf ("type: %d\n", GetTag(slot));
            throw std::runtime_error("YAMLSerializer: not implementation for this type");
        }
    }
int prFileWriteLE(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *ptr;
	PyrFile *pfile;
	FILE *file;
	PyrObject *obj;
	char chr;

	a = g->sp - 1;
	b = g->sp;
	pfile = (PyrFile*)slotRawObject(a);
	file = (FILE*)slotRawPtr(&pfile->fileptr);
	if (file == NULL) return errFailed;
	switch (GetTag(b)) {
		case tagInt :
		{
			SC_IOStream<FILE*> scio(file);
			scio.writeInt32_le(slotRawInt(b));
			break;
		}
		case tagSym :
			fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
			break;
		case tagChar :
			chr = slotRawInt(b);
			fwrite(&chr, sizeof(char), 1, file);
			break;
		case tagNil :
		case tagFalse :
		case tagTrue :
		case tagPtr :
			return errWrongType;
		case tagObj :
		{
			// writes the indexable part of any non obj_slot format object
			obj = slotRawObject(b);
			if (!isKindOf(obj, class_rawarray)
				|| isKindOf(obj, class_symbolarray)) return errWrongType;
			if (obj->size) {
				ptr = obj->slots;
				int elemSize = gFormatElemSize[obj->obj_format];
				int numElems = obj->size;
#if BYTE_ORDER == BIG_ENDIAN
				switch (elemSize) {
					case 1:
						fwrite(ptr, elemSize, numElems, file);
						break;
					case 2:
					{
						char *ptr = slotRawString(b)->s;
						char *ptrend = ptr + numElems*2;
						for (; ptr < ptrend; ptr+=2) {
							fputc(ptr[1], file);
							fputc(ptr[0], file);
						}
						break;
					}
					case 4:
					{
						char *ptr = slotRawString(b)->s;
						char *ptrend = ptr + numElems*4;
						for (; ptr < ptrend; ptr+=4) {
							fputc(ptr[3], file);
							fputc(ptr[2], file);
							fputc(ptr[1], file);
							fputc(ptr[0], file);
						}
						break;
					}
					case 8:
					{
						char *ptr = slotRawString(b)->s;
						char *ptrend = ptr + numElems*8;
						for (; ptr < ptrend; ptr+=8) {
							fputc(ptr[7], file);
							fputc(ptr[6], file);
							fputc(ptr[5], file);
							fputc(ptr[4], file);
							fputc(ptr[3], file);
							fputc(ptr[2], file);
							fputc(ptr[1], file);
							fputc(ptr[0], file);
						}
						break;
					}
				}
#else
				fwrite(ptr, elemSize, numElems, file);
#endif
			}
			break;
		}
		default : // double
		{
			SC_IOStream<FILE*> scio(file);
			scio.writeDouble_le(slotRawFloat(b));
			break;
		}
	}
	return errNone;
}
示例#16
0
 static float read( PyrSlot *slot )
 {
   return slotRawFloat(slot);
 }
bool getheap(VMGlobals *g, PyrObject *heapArg, double *schedtime, PyrSlot *task)
{
	PyrHeap * heap = (PyrHeap*)heapArg;
	PyrGC* gc = g->gc;
	bool isPartialScanObj = gc->IsPartialScanObject(heapArg);
	assert(heap->size);

// 	post("->getheap\n");
// 	dumpheap(heapArg);
	if (heap->size>1) {
		*schedtime = slotRawFloat(&heap->slots[0]);
		slotCopy(task, &heap->slots[1]);
		heap->size -= 3;
		int size = heap->size - 1;
		slotCopy(&heap->slots[0], &heap->slots[size]);
		slotCopy(&heap->slots[1], &heap->slots[size+1]);
		slotCopy(&heap->slots[2], &heap->slots[size+2]);

		/* parent and sibling in the heap, not in the task hierarchy */
		int mom = 0;
		int me = 3;
		PyrSlot * pmom = heap->slots + mom;
		PyrSlot * pme = heap->slots + me;
		PyrSlot * pend = heap->slots + size;
		double timetemp = slotRawFloat(&pmom[0]);
		int stabilityCountTemp = slotRawInt(&pmom[2]);
		PyrSlot tasktemp;
		slotCopy(&tasktemp, &pmom[1]);
		for (;pme < pend;) {
			/* demote heap */
			if (pme+3 < pend && ((slotRawFloat(&pme[0]) > slotRawFloat(&pme[3])) ||
				((slotRawFloat(&pme[0]) == slotRawFloat(&pme[3])) && (slotRawInt(&pme[2]) > slotRawInt(&pme[5]))
				))) {
				me += 3; pme += 3;
			}
			if (timetemp > slotRawFloat(&pme[0]) ||
				(timetemp == slotRawFloat(&pme[0]) && stabilityCountTemp > slotRawInt(&pme[2]))) {
				slotCopy(&pmom[0], &pme[0]);
				slotCopy(&pmom[1], &pme[1]);
				slotCopy(&pmom[2], &pme[2]);
				if (isPartialScanObj) {
					gc->GCWriteBlack(pmom+1);
				}
				pmom = pme;
				me = ((mom = me) * 2) + 3;
				pme = heap->slots + me;
			} else break;
		}
		SetRaw(&pmom[0], timetemp);
		slotCopy(&pmom[1], &tasktemp);
		SetRaw(&pmom[2], stabilityCountTemp);
		if (isPartialScanObj)
			gc->GCWriteBlack(pmom+1);

		if (size == 0)
			SetInt(&heap->count, 0);

// 	dumpheap(heapArg);
// 	post("<-getheap true\n");
		return true;
	} else {
// 	post("<-getheap false\n");
		return false;
	}
}
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* 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;
}