// 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); }
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); }
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); }
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; }
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; } }
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; } }