Example #1
0
*/	REBINT Wait_Ports(REBSER *ports, REBCNT timeout, REBINT only)
/*
**	Inputs:
**		Ports: a block of ports or zero (on stack to avoid GC).
**		Timeout: milliseconds to wait
**
**	Returns:
**		TRUE when port action happened, or FALSE for timeout.
**
***********************************************************************/
{
	REBI64 base = OS_DELTA_TIME(0, 0);
	REBCNT time;
	REBINT result;
	REBCNT wt = 1;
	REBCNT res = (timeout >= 1000) ? 0 : 16;  // OS dependent?

	while (wt) {
		if (GET_SIGNAL(SIG_ESCAPE)) {
			CLR_SIGNAL(SIG_ESCAPE);
			raise Error_Is(TASK_HALT_ERROR);
		}

		// Process any waiting events:
		if ((result = Awake_System(ports, only)) > 0) return TRUE;

		// If activity, use low wait time, otherwise increase it:
		if (result == 0) wt = 1;
		else {
			wt *= 2;
			if (wt > MAX_WAIT_MS) wt = MAX_WAIT_MS;
		}

		if (timeout != ALL_BITS) {
			// Figure out how long that (and OS_WAIT) took:
			time = (REBCNT)(OS_DELTA_TIME(base, 0)/1000);
			if (time >= timeout) break;	  // done (was dt = 0 before)
			else if (wt > timeout - time) // use smaller residual time
				wt = timeout - time;
		}

		//printf("%d %d %d\n", dt, time, timeout);

		// Wait for events or time to expire:
		//Debug_Num("OSW", wt);
		OS_WAIT(wt, res);
	}

	//time = (REBCNT)OS_DELTA_TIME(base, 0);
	//Print("dt: %d", time);

	return FALSE; // timeout
}
Example #2
0
File: p-event.c Project: mbk/ren-c
*/	static REB_R Event_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action)
/*
**		Internal port handler for events.
**
***********************************************************************/
{
	REBVAL *spec;
	REBVAL *state;
	REB_R result;
	REBVAL *arg;
	REBVAL save_port;

	Validate_Port(port, action);

	arg = D_ARG(2);
	*D_OUT = *D_ARG(1);

	// Validate and fetch relevant PORT fields:
	state = BLK_SKIP(port, STD_PORT_STATE);
	spec  = BLK_SKIP(port, STD_PORT_SPEC);
	if (!IS_OBJECT(spec)) Trap1_DEAD_END(RE_INVALID_SPEC, spec);

	// Get or setup internal state data:
	if (!IS_BLOCK(state)) Set_Block(state, Make_Block(EVENTS_CHUNK - 1));

	switch (action) {

	case A_UPDATE:
		return R_NONE;

	// Normal block actions done on events:
	case A_POKE:
		if (!IS_EVENT(D_ARG(3))) Trap_Arg_DEAD_END(D_ARG(3));
		goto act_blk;
	case A_INSERT:
	case A_APPEND:
	//case A_PATH:		// not allowed: port/foo is port object field access
	//case A_PATH_SET:	// not allowed: above
		if (!IS_EVENT(arg)) Trap_Arg_DEAD_END(arg);
	case A_PICK:
act_blk:
		save_port = *D_ARG(1); // save for return
		*D_ARG(1) = *state;
		result = T_Block(call_, action);
		SET_SIGNAL(SIG_EVENT_PORT);
		if (action == A_INSERT || action == A_APPEND || action == A_REMOVE) {
			*D_OUT = save_port;
			break;
		}
		return result; // return condition

	case A_CLEAR:
		VAL_TAIL(state) = 0;
		VAL_BLK_TERM(state);
		CLR_SIGNAL(SIG_EVENT_PORT);
		break;

	case A_LENGTHQ:
		SET_INTEGER(D_OUT, VAL_TAIL(state));
		break;

	case A_OPEN:
		if (!req) { //!!!
			req = OS_MAKE_DEVREQ(RDI_EVENT);
			if (req) {
				SET_OPEN(req);
				OS_DO_DEVICE(req, RDC_CONNECT);		// stays queued
			}
		}
		break;

	case A_CLOSE:
		OS_ABORT_DEVICE(req);
		OS_DO_DEVICE(req, RDC_CLOSE);
		// free req!!!
		SET_CLOSED(req);
		req = 0;
		break;

	case A_FIND: // add it

	default:
		Trap_Action_DEAD_END(REB_PORT, action);
	}

	return R_OUT;
}