Example #1
0
void
PrtPop(
_Inout_ PRT_MACHINEINST_PRIV		*context
)
{
	context->lastOperation = PopStatement;
	PrtFreeValue(context->currentTrigger);
	PrtFreeValue(context->currentPayload);
	context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL);
	context->currentPayload = PrtMkNullValue();
	// Actual pop happens in PrtPopState; the exit function must be executed first.
	// context->{currentTrigger,currentPayload} are set on for the benefit of the exit function.
}
Example #2
0
void
PrtPushNewEventHandlerFrame(
_Inout_ PRT_MACHINEINST_PRIV	*context,
_In_ PRT_UINT32					funIndex,
_In_ PRT_VALUE					**locals
)
{
	PRT_UINT16 length = context->funStack.length;
	PrtAssert(length < PRT_MAX_FUNSTACK_DEPTH, "Fun stack overflow");
	context->funStack.length = length + 1;
	context->funStack.funs[length].funIndex = funIndex;
	PRT_BOOLEAN freeLocals = (locals == NULL);
	PRT_FUNDECL *funDecl = &(context->process->program->machines[context->instanceOf].funs[funIndex]);
	if (locals == NULL && funDecl->maxNumLocals != 0)
	{
		locals = PrtCalloc(funDecl->maxNumLocals, sizeof(PRT_VALUE *));
		for (PRT_UINT32 i = 0; i < funDecl->maxNumLocals; i++)
		{
			locals[i] = NULL;
		}
	}
	PRT_UINT32 count = funDecl->numEnvVars;
	if (funDecl->name == NULL)
	{
		PrtAssert(0 < count, "numEnvVars must be positive for anonymous function");
		PRT_UINT32 payloadIndex = count - 1;
		if (locals[payloadIndex] != NULL)
		{
			PrtFreeValue(locals[payloadIndex]);
		}
		locals[payloadIndex] = PrtCloneValue(context->currentPayload);
	}
	if (funDecl->localsNmdTupType != NULL)
	{
		PRT_UINT32 size = funDecl->localsNmdTupType->typeUnion.nmTuple->arity;
		for (PRT_UINT32 i = 0; i < size; i++)
		{
			PRT_TYPE *indexType = funDecl->localsNmdTupType->typeUnion.nmTuple->fieldTypes[i];
			if (locals[count] != NULL)
			{
				PrtFreeValue(locals[count]);
			}
			locals[count] = PrtMkDefaultValue(indexType);
			count++;
		}
	}
	context->funStack.funs[length].locals = locals;
	context->funStack.funs[length].freeLocals = freeLocals;
	context->funStack.funs[length].returnTo = 0xFFFF;
	context->funStack.funs[length].rcase = NULL;
}
Example #3
0
void
PrtFreeLocals(
_In_ PRT_MACHINEINST_PRIV		*context,
_Inout_ PRT_FUNSTACK_INFO		*frame
)
{
	if (!frame->freeLocals)
	{
		return;
	}

	if (frame->locals == NULL)
	{
		return;
	}

	PRT_FUNDECL *funDecl = &context->process->program->machines[context->instanceOf].funs[frame->funIndex];
	for (PRT_UINT32 i = 0; i < funDecl->maxNumLocals; i++)
	{
		if (frame->locals[i] != NULL)
		{
			PrtFreeValue(frame->locals[i]);
		}
	}
	PrtFree(frame->locals);
}
Example #4
0
void
PrtRaise(
_Inout_ PRT_MACHINEINST_PRIV		*context,
_In_ PRT_VALUE						*event,
_In_ PRT_VALUE						*payload
)
{
	PrtAssert(!PrtIsSpecialEvent(event), "Raised event must not be null");
	PrtAssert(PrtInhabitsType(payload, PrtGetPayloadType(context, event)), "Payload must be member of event payload type");
	context->lastOperation = RaiseStatement;
	PrtFreeValue(context->currentTrigger);
	PrtFreeValue(context->currentPayload);
	context->currentTrigger = PrtCloneValue(event);
	context->currentPayload = PrtCloneValue(payload);
	PrtLog(PRT_STEP_RAISE, context);
}
Example #5
0
PRT_VALUE *P_FUN_StartTimer_IMPL(PRT_MACHINEINST *context)
{
	PRT_MACHINEINST_PRIV *p_tmp_mach_priv = (PRT_MACHINEINST_PRIV *)context;
	PRT_VALUE *p_tmp_ret = NULL;
	PRT_FUNSTACK_INFO p_tmp_frame;

	// pop frame
	PrtPopFrame(p_tmp_mach_priv, &p_tmp_frame);

	PRT_VALUE* timerMachineId = p_tmp_frame.locals[0];
	PRT_MACHINEINST* timerMachine = PrtGetMachine(context->process, timerMachineId);
	TimerContext *timerContext = (TimerContext *)timerMachine->extContext;

	int timeout_value = p_tmp_frame.locals[1]->valueUnion.nt;
	
	SleepMs(timeout_value);

	PRT_VALUE *ev = PrtMkEventValue(P_EVENT_TIMEOUT);
	PRT_MACHINEINST* clientMachine = PrtGetMachine(context->process, timerContext->client);
	PrtSend(context, clientMachine, ev, context->id, PRT_FALSE);
	PrtFreeValue(ev);

	// free the frame
	PrtFreeLocals(p_tmp_mach_priv, &p_tmp_frame);
	return NULL;
}
Example #6
0
void PRT_CALL_CONV PrtSetLocalVarEx(_Inout_ PRT_VALUE **locals, _In_ PRT_UINT32 varIndex, _In_ PRT_VALUE *value, _In_ PRT_BOOLEAN cloneValue)
{
	PRT_DBG_ASSERT(PrtIsValidValue(value), "value is not valid");
	PRT_DBG_ASSERT(PrtIsValidValue(locals[varIndex]), "Variable must contain a valid value");
	PrtFreeValue(locals[varIndex]);
	locals[varIndex] = cloneValue ? PrtCloneValue(value) : value;
}
Example #7
0
void PRT_CALL_CONV PrtSetGlobalVarEx(_Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_UINT32 varIndex, _In_ PRT_VALUE *value, _In_ PRT_BOOLEAN cloneValue)
{
	PRT_DBG_ASSERT(PrtIsValidValue(value), "value is not valid");
	PRT_DBG_ASSERT(PrtIsValidValue(context->varValues[varIndex]), "Variable must contain a valid value");
	PrtFreeValue(context->varValues[varIndex]);
	context->varValues[varIndex] = cloneValue ? PrtCloneValue(value) : value;
}
Example #8
0
void P_SEND_Timer_IMPL(PRT_MACHINEINST *context, PRT_VALUE *evnt, PRT_VALUE *payload, PRT_BOOLEAN doTransfer)
{
    printf("Entering P_SEND_Timer_IMPL\n");
    PRT_VALUE *ev;
    BOOL success;
    TimerContext *timerContext = (TimerContext *)context->extContext;
    if (!inStart && evnt->valueUnion.ev == P_EVENT_START) {
        printf("Timer received START\n");
        LARGE_INTEGER liDueTime;
        liDueTime.QuadPart = -10000 * payload->valueUnion.nt;
        success = SetWaitableTimer(timerContext->timer, &liDueTime, 0, Callback, context, FALSE);
        inStart = TRUE;
        PrtAssert(success, "SetWaitableTimer failed");
    }
    else if (evnt->valueUnion.ev == P_EVENT_CANCEL) {
        printf("Timer received CANCEL\n");
        inStart = FALSE;
        success = CancelWaitableTimer(timerContext->timer);
        if (success) {
            ev = PrtMkEventValue(P_EVENT_CANCEL_SUCCESS);
            PrtSend(context, PrtGetMachine(context->process, timerContext->client), ev, context->id, PRT_FALSE);
        }
        else {
            ev = PrtMkEventValue(P_EVENT_CANCEL_FAILURE);
            PrtSend(context, PrtGetMachine(context->process, timerContext->client), ev, context->id, PRT_FALSE);
        }
        PrtFreeValue(ev);
    }
    else {
        PrtAssert(FALSE, "Illegal event");
    }
}
Example #9
0
void P_DTOR_Timer_IMPL(PRT_MACHINEINST *context)
{
	TimerContext *timerContext;
	timerContext = (TimerContext *)context->extContext;

	PrtFreeValue(timerContext->client);
	PrtFree(timerContext);
}
Example #10
0
File: Timer.c Project: annakoppad/P
VOID CALLBACK Callback(LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
{
    inStart = FALSE;
    PRT_MACHINEINST *context = (PRT_MACHINEINST *)arg;
    TimerContext *timerContext = (TimerContext *)context->extContext;
    PRT_VALUE *ev = PrtMkEventValue(P_EVENT_TIMEOUT);
    PrtSend(PrtGetMachine(context->process, timerContext->client), ev, context->id, PRT_FALSE);
    PrtFreeValue(ev);
}
Example #11
0
void
PrtCleanupModel(
_Inout_ PRT_MACHINEINST			*context
)
{
	if (context->extContext != NULL)
		context->process->program->modelImpls[context->instanceOf].dtorFun(context);
	PrtFreeValue(context->id);
}
Example #12
0
void P_DTOR_Timer_IMPL(PRT_MACHINEINST *context)
{
    printf("Entering P_DTOR_Timer_IMPL\n");
    TimerContext *timerContext;
    timerContext = (TimerContext *)context->extContext;
    PrtFreeValue(timerContext->client);
    CloseHandle(timerContext->timer);
    free(timerContext);
}
Example #13
0
void
PrtPushNewFrame(
_Inout_ PRT_MACHINEINST_PRIV	*context,
_In_ PRT_UINT32					funIndex,
_In_ PRT_VALUE					*parameters
)
{
	PRT_UINT16 length = context->funStack.length;
	PrtAssert(length < PRT_MAX_FUNSTACK_DEPTH, "Fun stack overflow");
	context->funStack.length = length + 1;
	context->funStack.funs[length].funIndex = funIndex;
	PRT_FUNDECL *funDecl = &(context->process->program->machines[context->instanceOf].funs[funIndex]);
	PRT_VALUE **locals = NULL;
	if (funDecl->maxNumLocals == 0)
	{
		PrtAssert(parameters == NULL && funDecl->localsNmdTupType == NULL, "Incorrect maxNumLocals value");
	}
	else
	{
		locals = PrtCalloc(funDecl->maxNumLocals, sizeof(PRT_VALUE *));
		for (PRT_UINT32 i = 0; i < funDecl->maxNumLocals; i++)
		{
			locals[i] = NULL;
		}
		PRT_UINT32 count = 0;
		if (parameters != NULL)
		{
			PRT_UINT32 size = parameters->valueUnion.tuple->size;
			for (PRT_UINT32 i = 0; i < size; i++)
			{
				locals[count] = PrtTupleGet(parameters, i);
				count++;
			}
			PrtFreeValue(parameters);
		}
		if (funDecl->localsNmdTupType != NULL)
		{
			PRT_UINT32 size = funDecl->localsNmdTupType->typeUnion.nmTuple->arity;
			for (PRT_UINT32 i = 0; i < size; i++)
			{
				PRT_TYPE *indexType = funDecl->localsNmdTupType->typeUnion.nmTuple->fieldTypes[i];
				locals[count] = PrtMkDefaultValue(indexType);
				count++;
			}
		}
	}
	context->funStack.funs[length].locals = locals;
	context->funStack.funs[length].freeLocals = PRT_TRUE;
	context->funStack.funs[length].returnTo = 0xFFFF;
	context->funStack.funs[length].rcase = NULL;
}
Example #14
0
File: Main.c Project: thisiscam/P
int main(int argc, char *argv[])
{
	PRT_PROCESS *process;
	PRT_GUID processGuid;
	PRT_VALUE *payload;
	processGuid.data1 = 1;
	processGuid.data2 = 0;
	processGuid.data3 = 0;
	processGuid.data4 = 0;
	process = PrtStartProcess(processGuid, &P_GEND_PROGRAM, ErrorHandler, Log);
	payload = PrtMkNullValue();
	PrtMkMachine(process, P_MACHINE_TestMachine, payload);
	PrtFreeValue(payload);
	PrtStopProcess(process);
}
Example #15
0
int main(int argc, char *argv[])
{
	//The commandline arguments 
    FirstArgument = argv[0];

    if (argc != 5)
    {
        PrintUsage();
        return;
    }

	int createMain = atoi(argv[2]);
	PrtAssert(createMain == 0 || createMain == 1, "CreateMain should be either 0 or 1");
	int processId = atoi(argv[3]);
	PrtAssert(processId >= 0, "Process Id should be positive");
	int nodeId = atoi(argv[4]);
	
	PRT_DBG_START_MEM_BALANCED_REGION
	{
		//Initialize the cluster configuration.
		PrtDistClusterConfigInitialize(argv[1]);
		SetCurrentDirectory(ClusterConfiguration.LocalFolder);
		PRT_GUID processGuid;
		processGuid.data1 = processId;
		processGuid.data2 = nodeId; //nodeId
		processGuid.data3 = 0;
		processGuid.data4 = 0;
		ContainerProcess = PrtStartProcess(processGuid, &P_GEND_PROGRAM, PrtDistSMExceptionHandler, PrtDistSMLogHandler);
		HANDLE listener = NULL;
		PRT_INT32 portNumber = atoi(ClusterConfiguration.ContainerPortStart) + processId;
		listener = CreateThread(NULL, 0, PrtDistCreateRPCServerForEnqueueAndWait, &portNumber, 0, NULL);
		if (listener == NULL)
		{
			PrtDistLog("Error Creating RPC server in PrtDistStartNodeManagerMachine");
		}
		else
		{
			DWORD status;
			//Sleep(3000);
			//check if the thread is all ok
			GetExitCodeThread(listener, &status);
			if (status != STILL_ACTIVE)
				PrtDistLog("ERROR : Thread terminated");

		}

		if (createMain)
		{
			//create main machine 
			PRT_VALUE* payload = PrtMkNullValue();
			PrtMkMachine(ContainerProcess, _P_MACHINE_MAIN, payload);
			PrtFreeValue(payload);
		}
		else
		{
			//create container machine
			PrtDistLog("Creating Container Machine");
			PRT_VALUE* payload = PrtMkNullValue();
			PrtMkMachine(ContainerProcess, P_MACHINE_Container, payload);
			PrtFreeValue(payload);

		}

		//after performing all operations block and wait
		WaitForSingleObject(listener, INFINITE);

		PrtStopProcess(ContainerProcess);
	}
	PRT_DBG_END_MEM_BALANCED_REGION
}
Example #16
0
void
PrtCleanupMachine(
_Inout_ PRT_MACHINEINST_PRIV			*context
)
{
	if (context->isHalted)
		return;

	if (context->eventQueue.events != NULL)
	{
		PRT_EVENT *queue = context->eventQueue.events;
		PRT_UINT32 head = context->eventQueue.headIndex;
		PRT_UINT32 tail = context->eventQueue.tailIndex;
		PRT_UINT32 count = 0;

		while (count < context->eventQueue.size && head < context->eventQueue.eventsSize)
		{
			if (queue[head].payload != NULL)
			{
				PrtFreeValue(queue[head].payload);
			}
			if (queue[head].trigger != NULL) {
				PrtFreeValue(queue[head].trigger);
			}
			head++;
			count++;
		}
		head = 0;
		while (count < context->eventQueue.size)
		{
			if (queue[head].payload != NULL)
			{
				PrtFreeValue(queue[head].payload);
			}
			if (queue[head].trigger != NULL) {
				PrtFreeValue(queue[head].trigger);
			}
			head++;
			count++;
		}

		PrtFree(context->eventQueue.events);
	}

	for (int i = 0; i < context->callStack.length; i++)
	{
		PRT_STATESTACK_INFO *info = &context->callStack.stateStack[i];
		if (info->inheritedActionSetCompact != NULL)
		{
			PrtFree(info->inheritedActionSetCompact);
		}
		if (info->inheritedDeferredSetCompact != NULL)
		{
			PrtFree(info->inheritedDeferredSetCompact);
		}
	}

	for (int i = 0; i < context->funStack.length; i++)
	{
		PRT_FUNSTACK_INFO *info = &context->funStack.funs[i];
		PrtFreeLocals(context, info);
	}

	if (context->currentActionSetCompact != NULL)
	{
		PrtFree(context->currentActionSetCompact);
	}

	if (context->currentDeferredSetCompact != NULL)
	{
		PrtFree(context->currentDeferredSetCompact);
	}

	if (context->inheritedActionSetCompact != NULL)
	{
		PrtFree(context->inheritedActionSetCompact);
	}

	if (context->inheritedDeferredSetCompact != NULL)
	{
		PrtFree(context->inheritedDeferredSetCompact);
	}

	if (context->varValues != NULL)
	{
		UINT i;
		PRT_MACHINEDECL *mdecl = &(context->process->program->machines[context->instanceOf]);

		for (i = 0; i < mdecl->nVars; i++) {
			PrtFreeValue(context->varValues[i]);
		}
		PrtFree(context->varValues);
	}

	if (context->stateMachineLock != NULL)
	{
		PrtDestroyMutex(context->stateMachineLock);
	}

	if (context->extContext != NULL)
		context->process->program->machines[context->instanceOf].extDtorFun((PRT_MACHINEINST *)context);
	PrtFreeValue(context->id);

	PrtFreeValue(context->currentTrigger);
	PrtFreeValue(context->currentPayload);

	if (context->recvMap != NULL)
	{
		PrtFreeValue(context->recvMap);
	}
}
void P_DTOR_Client_IMPL(PRT_MACHINEINST *context)
{
    ClientContext *clientContext = (ClientContext *)context->extContext;
    PrtFreeValue(clientContext->client);
    PrtFree(clientContext);
}
Example #18
0
int main(int argc, char *argv[])
{
#ifndef PRT_PLAT_WINUSER
    init_ros("test_motion_planner", &argc, argv);
#endif
    if (!ParseCommandLine(argc, argv))
    {
        PrintUsage();
        return 1;
    }

    const char* motion_planner_delta_s = getenv("MOTION_PLANNER_DELTA");
    if(motion_planner_delta_s) {
        Delta = atoi(motion_planner_delta_s);
        printf("Using MOTION_PLANNER_DELTA = %d\n", Delta);
    }

    printf("Press any key to start simulation\n");
    getchar();

	PRT_DBG_START_MEM_BALANCED_REGION
	{
		PRT_PROCESS *process;
		PRT_GUID processGuid;
		PRT_VALUE *payload;

		//Initialize the workspace
		WORKSPACE_INFO = ParseWorkspaceConfig(workspaceConfig);

#ifdef USE_DIJKSTRA_PRECOMPUTATION
        WS_LocationsList ends;
        ends.size = WORKSPACE_INFO->starts.size + WORKSPACE_INFO->ends.size;
        ends.locations = malloc(sizeof(WS_Coord) * ends.size);
        int count = 0;
        for(int i=0; i < WORKSPACE_INFO->starts.size; i++) {
            ends.locations[count++] = WORKSPACE_INFO->starts.locations[i];
        }
        for(int i=0; i < WORKSPACE_INFO->ends.size; i++) {
            ends.locations[count++] = WORKSPACE_INFO->ends.locations[i];
        }
        PreComputeObstacleDistanceH(WORKSPACE_INFO->dimension, WORKSPACE_INFO->obstacles, ends);
#endif

		processGuid.data1 = 1;
		processGuid.data2 = 0;
		processGuid.data3 = 0;
		processGuid.data4 = 0;
		process = PrtStartProcess(processGuid, &P_GEND_PROGRAM, ErrorHandler, Log);
        if (cooperative)
        {
            PrtSetSchedulingPolicy(process, PRT_SCHEDULINGPOLICY_COOPERATIVE);
        }
		if (parg == NULL)
		{
			payload = PrtMkNullValue();
		}
		else
		{
			int i = atoi(parg);
			payload = PrtMkIntValue(i);
		}

		PrtUpdateAssertFn(MyAssert);

		PrtMkMachine(process, P_MACHINE_Main, payload);

        if (cooperative)
        {
            // test some multithreading across state machines.
#if defined(PRT_PLAT_WINUSER)
			HANDLE* threadsArr = (HANDLE*)PrtMalloc(threads*sizeof(HANDLE));
            for (int i = 0; i < threads; i++)
            {
                DWORD threadId;
                threadsArr[i] = CreateThread(NULL, 16000, (LPTHREAD_START_ROUTINE)RunToIdle, process, 0, &threadId);
            }
			WaitForMultipleObjects(threads, threadsArr, TRUE, INFINITE);
			PrtFree(threadsArr);
#elif defined(PRT_PLAT_LINUXUSER)
typedef void *(*start_routine) (void *);
            pthread_t tid[threads];
            for (int i = 0; i < threads; i++)
            {
                pthread_create(&tid[i], NULL, (start_routine)RunToIdle, (void*)process);
            }
            for (int i = 0; i < threads; i++)
            {
                pthread_join(tid[i], NULL);
            }
#else
#error Invalid Platform
#endif
        }
		PrtFreeValue(payload);
		PrtStopProcess(process);
	}
	PRT_DBG_END_MEM_BALANCED_REGION

	//_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
	//_CrtDumpMemoryLeaks();
}
Example #19
0
PRT_BOOLEAN
PrtDequeueEvent(
_Inout_ PRT_MACHINEINST_PRIV	*context,
_Inout_ PRT_FUNSTACK_INFO		*frame
)
{
	PRT_UINT32 queueLength;
	PRT_EVENTQUEUE *queue;
	PRT_UINT32* deferPacked;
	PRT_UINT32 i, head;

	queue = &context->eventQueue;
	queueLength = queue->eventsSize;
	deferPacked = PrtGetDeferredPacked(context, context->currentState);
	head = queue->headIndex;

	PRT_DBG_ASSERT(queue->size <= queueLength, "Check Failed");
	PRT_DBG_ASSERT(queue->size >= 0, "Check Failed");
	PRT_DBG_ASSERT(queue->headIndex >= 0, "Check Failed");
	PRT_DBG_ASSERT(queue->tailIndex >= 0, "Check Failed");

	//
	// Find the element to dequeue
	//
	for (i = 0; i < queue->size; i++) {
		PRT_UINT32 index = (head + i) % queueLength;
		PRT_EVENT e = queue->events[index];
		PRT_UINT32 triggerIndex = PrtPrimGetEvent(e.trigger);
		if (context->receive == NULL)
		{
			if (!PrtIsEventDeferred(triggerIndex, context->currentDeferredSetCompact))
			{
				PrtFreeValue(context->currentTrigger);
				PrtFreeValue(context->currentPayload);
				context->currentTrigger = e.trigger;
				context->currentPayload = e.payload;
				break;
			}
		}
		else
		{
			if (PrtIsEventReceivable(context, triggerIndex))
			{
				PrtFreeValue(context->currentTrigger);
				PrtFreeValue(context->currentPayload);
				context->currentTrigger = e.trigger;
				context->currentPayload = e.payload;
				for (PRT_UINT32 i = 0; i < context->receive->nCases; i++)
				{
					PRT_CASEDECL *rcase = &context->receive->cases[i];
					if (triggerIndex == rcase->triggerEventIndex)
					{
						frame->rcase = rcase;
						PrtPushNewEventHandlerFrame(context, rcase->funIndex, frame->locals);
						break;
					}
				}
				context->receive = NULL;
				break;
			}
		}
	}

	//
	// Check if not found
	//
	if (i == queue->size) {
		if (context->receive == NULL)
		{
			if (PrtStateHasDefaultTransitionOrAction(context))
			{
				PrtFreeValue(context->currentTrigger);
				PrtFreeValue(context->currentPayload);
				context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL);
				context->currentPayload = PrtMkNullValue();
				return PRT_TRUE;
			}
			else
			{
				return PRT_FALSE;
			}
		}
		else
		{
			PRT_BOOLEAN hasDefaultCase = (context->process->program->eventSets[context->receive->caseSetIndex].packedEvents[0] & 0x1) == 1;
			if (hasDefaultCase)
			{
				PrtFreeValue(context->currentTrigger);
				PrtFreeValue(context->currentPayload);
				context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL);
				context->currentPayload = PrtMkNullValue();
				for (PRT_UINT32 i = 0; i < context->receive->nCases; i++)
				{
					PRT_CASEDECL *rcase = &context->receive->cases[i];
					if (PRT_SPECIAL_EVENT_NULL == rcase->triggerEventIndex)
					{
						frame->rcase = rcase;
						PrtPushNewEventHandlerFrame(context, rcase->funIndex, frame->locals);
						break;
					}
				}
				context->receive = NULL;
				return PRT_TRUE;
			}
			else
			{
				return PRT_FALSE;
			}
		}
	}

	//
	// Collapse the event queue on the removed event
	// by moving the previous elements forward.
	//
	for (; i > 0; i--) {
		INT index = (head + i) % queueLength;
		INT prev = (index - 1 + queueLength) % queueLength;
		queue->events[index] = queue->events[prev];
	}

	//
	// Adjust the queue size
	//
	queue->headIndex = (queue->headIndex + 1) % queueLength;
	queue->size--;

	PRT_DBG_ASSERT(queue->size <= queueLength, "Check Failed");
	PRT_DBG_ASSERT(queue->size >= 0, "Check Failed");
	PRT_DBG_ASSERT(queue->headIndex >= 0, "Check Failed");
	PRT_DBG_ASSERT(queue->tailIndex >= 0, "Check Failed");

	//
	//Log
	//
	PrtLog(PRT_STEP_DEQUEUE, context);
	return PRT_TRUE;
}
static void *machine_thread(void *arg)
{
    int maxSteps = 0;
    printf("PingPong starting...\n");

    lastCpuTime = 0;

    PrintHeader();

    if (arg != NULL)
    {
        char* ptr = (char*)arg;
        maxSteps = atoi(ptr);
    }

    PRT_GUID processGuid;
    processGuid.data1 = 1;
    processGuid.data2 = 1;
    processGuid.data3 = 0;
    processGuid.data4 = 0;
    ContainerProcess = PrtStartProcess(processGuid, &P_GEND_PROGRAM, ErrorHandler, LogHandler);

    PrtSetSchedulingPolicy(ContainerProcess, PRT_SCHEDULINGPOLICY_COOPERATIVE);

    //create main machine
    PRT_VALUE* payload = PrtMkNullValue();
    PrtMkMachine(ContainerProcess, _P_MACHINE_MAIN, payload);
    PrtFreeValue(payload);

    start = clock_systimer();
    intervalStart = start;
    steps = 0;
    intervalSteps = 0;

    // push the state machines while yielding the CPU to other higher priority tasks.
    PRT_PROCESS_PRIV* privateProcess = (PRT_PROCESS_PRIV*)ContainerProcess;
    while (privateProcess->terminating == PRT_FALSE && (maxSteps == 0 || steps < maxSteps))
    {
        PRT_STEP_RESULT result = PrtStepProcess(ContainerProcess);
        switch (result) {
        case PRT_STEP_TERMINATING:
            break;
        case PRT_STEP_IDLE:
            PrtWaitForWork(ContainerProcess);
            break;
        case PRT_STEP_MORE:
            PrtYieldThread();
            break;
        }
        CountSteps();
    }

    int32_t elapsed = clock_systimer() - start;
    int32_t milliseconds = elapsed / (TICK_PER_SEC / 1000);

    printf("PingPong ran %d steps in %d ms\n", steps, milliseconds);

    if (maxSteps != 0)
    {
        // cleanup the memory for the process
        PrtStopProcess(ContainerProcess);
        ContainerProcess = NULL;
    }
    return NULL;
}