// KplTimeCallbackServiceUntil is called from the KplThreadRunloopCycle() function to call timer callbacks that are due
void KplTimeCallbackServiceUntil(void *param, KplTime until)
{
	KplTimeCallback cb;
	KplThread thread = (KplThread)param;

	cb = (KplTimeCallback)thread->timerCallbacks;
	if (NULL == cb)
		return;

	// mark all those that are due
	while (cb) {
		if (FskTimeCompare((FskTime)until, (FskTime)&cb->trigger) >= 0)
			break;
		cb->marked = true;
		cb = cb->next;
	}

	// Remove and call any timer callbacks that are due
	while (1) {
		cb = (KplTimeCallback)FskListGetNext(thread->timerCallbacks, NULL);
		if (!cb)
			break;
		if (!cb->marked)
			break;
		FskListRemove(&thread->timerCallbacks, cb);

		(*cb->callbackProc)(cb, &cb->trigger, cb->param);
	}

	if (thread->timerCallbacks)
		rescheduleTimer(thread);
}
Example #2
0
static void drawingPumpUpdate(FskWindow win)
{
	FskTimeRecord delta, now;

	FskTimeGetNow(&now);

	gKplScreen->unlocked = false;

	FskTimeCopy(&delta, &now);
	FskTimeSub(&gKplScreen->lastUpdateTime, &delta);

	FskTimeCopy(&gKplScreen->lastUpdateTime, &now);

	MLOG("[%s] called %d ms after last update\n", threadName, FskTimeInMS(&delta)); 

	// estimate next flip time by adding vSync interval to previous flip time
	FskTimeCopy(&gKplScreen->nextFlipTime, &gKplScreen->lastFlipTime);
	FskTimeAdd(&gKplScreen->vSyncIntervalTime, &gKplScreen->nextFlipTime);
	while (FskTimeCompare(&gKplScreen->nextFlipTime, &now) > 0)
		FskTimeAdd(&gKplScreen->vSyncIntervalTime, &gKplScreen->nextFlipTime);

	MLOG("Next flip time %ld.%06ld \n", gKplScreen->nextFlipTime.seconds, gKplScreen->nextFlipTime.useconds);

	FskWindowCheckEventQueue(win);
	FskWindowUpdate(win, &gKplScreen->nextFlipTime);

	if (!gKplScreen->unlocked)
		FskSemaphoreRelease(gKplScreen->flipSemaphore);

	MLOG("[%s] Finished callback %ld, nextFlipTime %1d.%03d\n", threadName, gKplScreen->callbackFiredCount, gKplScreen->nextFlipTime.seconds, gKplScreen->nextFlipTime.useconds / 1000);

}
Example #3
0
FskErr FskUUIDCreate(FskUUID uuid)
{
	FskTimeRecord time;
	static UInt32 clockSequence = 0;
	static FskTimeRecord lastTime;
	char MAC[6];
	FskNetInterfaceRecord *netInterface = NULL;
	UInt32 numInterfaces;

	// find a suitable network interface to get the MAC address from
	numInterfaces = FskNetInterfaceEnumerate();

	while (numInterfaces--) {
		FskNetInterfaceDescribe(numInterfaces, &netInterface);
		if ((0 == netInterface->MAC[0]) && (0 == netInterface->MAC[1]) && (0 == netInterface->MAC[2]) &&
			(0 == netInterface->MAC[3]) && (0 == netInterface->MAC[4]) && (0 == netInterface->MAC[5])) {
			FskNetInterfaceDescriptionDispose(netInterface);
			netInterface = NULL;
			continue;
		}
		break;
	}

	if (NULL == netInterface) {
		// can't fail - clients need a value. make something up. (this happens if all network interfaces are disabled on a phone)
		int i;
		for (i = 0; i < 6; i++)
			MAC[i] = (char)FskRandom();
	}
	else {
		FskMemMove(MAC, netInterface->MAC, sizeof(netInterface->MAC));
		FskNetInterfaceDescriptionDispose(netInterface);
	}

	// make sure the clock sequence is good
	while (0 == clockSequence)
		clockSequence = FskRandom();

	// we need the time, and make sure it is unique.
	FskTimeGetNow(&time);                                           //@@ should be UTC time
	time.useconds = (time.useconds >> 4) | (time.seconds << 28);	// only uses 60 bits of time
	time.seconds >>= 4;												// only uses 60 bits of time
	if (FskTimeCompare(&time, &lastTime) <= 0)
		clockSequence += 1;

	lastTime = time;

	// put the pieces together
	time.useconds = FskEndianU32_NtoB(time.useconds);
	FskMemCopy(&uuid->value[0], &time.useconds, sizeof(time.useconds));
	uuid->value[4] = (UInt8)time.seconds;
	uuid->value[5] = (UInt8)(time.seconds >> 8);
	uuid->value[6] = (((UInt8)(time.seconds >> 24)) & 0x0f) | 1;
	uuid->value[7] = (UInt8)(time.seconds >> 16);
	uuid->value[8] = ((UInt8)(clockSequence >> 8) & 0x3f) | 0x80;
	uuid->value[9] = (UInt8)clockSequence;
	FskMemCopy(&uuid->value[10], MAC, sizeof(MAC));

	return kFskErrNone;
}
// Insert this timer callback into the owning thread's "timerCallbacks" queue.
void sInsertInTime(KplTimeCallback el)
{
	KplTimeCallback cur, last = NULL;
	Boolean reschedule = false;
	KplTimeRecord now;
	KplThread thread;

	thread = (KplThread)el->owner;

	KplTimeGetNow(&now);
	if (1 == FskTimeCompare((FskTime)&el->trigger, (FskTime)&now))
		el->trigger = now;
	cur = (KplTimeCallback)FskListGetNext(thread->timerCallbacks, NULL);
	el->next = NULL;
	el->marked = false;

	if (cur == NULL) {
		FskListPrepend(&thread->timerCallbacks, el);
		reschedule = true;
		goto done;
	}
	while (cur) {
		if (FskTimeCompare((FskTime)&el->trigger, (FskTime)&cur->trigger) > 0) {
			if (last == NULL) {
				reschedule = true;
			}
			FskListInsertAfter(&thread->timerCallbacks, el, last);
			goto done;
		}

		last = cur;
		cur = cur->next;
	}
	if (!cur && last) {
		FskListAppend(&thread->timerCallbacks, el);
	}
	
done:
	if (reschedule)
		rescheduleTimer(thread);
}
Example #5
0
static KprMQTTMessage KprMQTTQueueNextMessageToResend(KprMQTTQueue self)
{
	KprMQTTMessage first, message;

	message = first = self->outbox;
	while (message) {
		if (message != first && FskTimeCompare(&message->nextTime, &first->nextTime) > 0) {
			first = message;
		}
		message = message->next;
	}

	return first;
}
Boolean KplTimeCallbackGetNextTime(const KplTime now, KplTime whenNext, void *threadIn)
{
	KplThread thread = threadIn ? threadIn : KplThreadGetCurrent();

	if (thread->timerCallbacks) {
		KplTimeCallback cb = (KplTimeCallback)thread->timerCallbacks;
		if (FskTimeCompare((FskTime)now, (FskTime)&cb->trigger) < 1) {
			FskTimeClear((FskTime)whenNext);
			return false;
		}

		*whenNext = cb->trigger;
	}
	else {
		*whenNext = *now;
		FskTimeAddSecs((FskTime)whenNext, 3600 * 12);	// a long time from now
	}

	return true;
}
Example #7
0
static void fxDoConnect(txMachine *the)
{
	if (!FskStrLen(debugAddress)) {
        char *address = FskEnvironmentGet("debugger");
		if (address)
			FskStrCopy(debugAddress, address);
#if TARGET_OS_WIN32 || (TARGET_OS_MAC && !TARGET_OS_IPHONE)
		else
			FskStrCopy(debugAddress, "localhost");
#endif
	}
	if (FskStrLen(debugAddress) && !debugAddressFailed) {
		FskErr err;
		char host[64];
		char* colon;
		int port;
		FskTimeRecord expireTime, now;
		SInt32 waitMS;
		
		colon = FskStrNCopyUntil(host, debugAddress, 63, ':');
		if (*colon)
			port = FskStrToNum(colon);
		else
			port = 5002;
			
#if TARGET_OS_MAC
		waitMS = 0;
#else
		waitMS = -1;
#endif
		// Connect to the host asynchronously
		err = FskNetConnectToHostPrioritized(host, port, false, fxConnectComplete, the, 0, 0, NULL, "fxConnect");
		if (err) goto bail;
		
		// Allow two seconds for the connection to resolve and for the socket to become readable and writable
		FskTimeGetNow(&expireTime);
		FskTimeAddSecs(&expireTime, 2);
		while (!the->connection) {
			FskTimeGetNow(&now);
			if (FskTimeCompare(&expireTime, &now) > 0)
				goto bail;
			FskThreadRunloopCycle(waitMS);
		}
		while (!FskNetSocketIsReadable((FskSocket)the->connection) && !FskNetSocketIsWritable((FskSocket)the->connection)) {
			FskTimeGetNow(&now);
			if (FskTimeCompare(&expireTime, &now) > 0)
				goto bail;
			FskThreadRunloopCycle(waitMS);
		}
		
		// Make the socket blocking
		FskNetSocketMakeBlocking((FskSocket)the->connection);
		return;
		
bail:
		if (the->connection) {
			FskNetSocketClose((FskSocket)the->connection);
			the->connection = 0;
		}
		debugAddressFailed = true;
	}
}
Example #8
0
void KprHTTPClientIterate()
{
	KprHTTPClient self = gKprHTTPClient;
	KprHTTPConnection connection, candidate, available;
	KprHTTPTarget target, next, other;
	KprMessage message;
	
	for (connection = FskListGetNext(self->connections, NULL); connection; connection = FskListGetNext(self->connections, connection)) {
		target = connection->target;
		if (target) {
			message = connection->target->message;
			if (!KprMessageContinue(message)) {
				KprHTTPConnectionClose(connection);
				KprHTTPClientResumeTarget(target);
			}
		}
	}
	target = FskListGetNext(self->targets, NULL);
	while (target) {
		next = FskListGetNext(self->targets, target);
		message = target->message;
		if (!KprMessageContinue(message)) {
			FskListRemove(&self->targets, target);
			KprHTTPClientResumeTarget(target);
		}
		target = next;
	}
	target = FskListGetNext(self->targets, NULL);
	while (target) {
		next = FskListGetNext(self->targets, target);
		message = target->message;
		candidate = NULL;
		available = NULL;
		for (connection = FskListGetNext(self->connections, NULL); connection; connection = FskListGetNext(self->connections, connection)) {
			if (KprHTTPConnectionCandidate(connection, message)) {
				candidate = connection;
				break;
			}
			else if (KprHTTPConnectionAvailable(connection)) {
				if (!available || (FskTimeCompare(&connection->time, &available->time) > 0)) // make the older connection the candidate for re-use
					available = connection;
			}
		}
		if (candidate) {
			if (KprHTTPConnectionAvailable(candidate)) {
				FskInstrumentedItemSendMessageDebug(candidate, kprInstrumentedHTTPConnectionCandidate, candidate->client);
			}
			else {
				candidate = NULL;
			}
		}
		else if (available) {
			// before closing the available connection, try to find a message that can use it
			for (other = FskListGetNext(self->targets, target); other; other = FskListGetNext(self->targets, other)) {
				if (abs(other->message->priority) < abs(message->priority)) {
					other = NULL;
					break;		// do not let a lower priority request get in ahead of a higher priority one
				}
				if (KprHTTPConnectionCandidate(available, other->message)) {
					break;
				}
			}
			if (other) {
				FskInstrumentedItemSendMessageDebug(available, kprInstrumentedHTTPConnectionCandidate, available->client);
				next = target;
				target = other;
			}
			else
				KprHTTPConnectionClose(available);
			candidate = available;
		}
		else
			break;
		if (candidate) {
			FskListRemove(&self->targets, target);
			if (KprHTTPConnectionProcess(candidate, target)) {
				// put back the message in the queue
				KprHTTPClientAddTarget(target);
			}
		}
		target = next;
	}
}