Skip to content

Commit

Permalink
CHANGE: use handles instead of binaries to hold native port states
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Sep 19, 2024
1 parent ad2b587 commit 2d9961e
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 130 deletions.
2 changes: 2 additions & 0 deletions src/boot/words.reb
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,5 @@ aad-length
file-checksum

xaudio-voice

port-state!
1 change: 1 addition & 0 deletions src/core/c-handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
//printf("Requested HOB for %s (%u) of size %u\n", SYMBOL_TO_NAME(sym), sym, size);
hob = (REBHOB*)Make_Node(HOB_POOL);
hob->data = MAKE_MEM(size);
if (!hob->data) Trap0(RE_NO_MEMORY);
hob->index = idx;
hob->flags = HANDLE_CONTEXT;
hob->sym = sym;
Expand Down
133 changes: 42 additions & 91 deletions src/core/c-port.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
**
*/ REBVAL *Make_Port(REBVAL *spec)
/*
** Create a new port. This is done by calling the MAKE_PORT
** Create a new port. This is done by calling the `make-port*`
** function stored in the system/intrinsic object.
**
***********************************************************************/
Expand All @@ -54,64 +54,32 @@

/***********************************************************************
**
*/ REBFLG Is_Port_Open(REBSER *port)
*/ REBVAL *Use_Port_State_Handle(REBSER *port, REBCNT device, REBCNT type)
/*
** Standard method for checking if port is open.
** A convention. Not all ports use this method.
** Use private state area (handle) in a port. Create if necessary.
** Returns NULL if fails to allocate the state handle.
**
***********************************************************************/
{
REBREQ *req;
REBVAL *state = BLK_SKIP(port, STD_PORT_STATE);
if (!IS_BINARY(state)) return FALSE;
return IS_OPEN(VAL_BIN_DATA(state));
}


/***********************************************************************
**
*/ void Set_Port_Open(REBSER *port, REBFLG flag)
/*
** Standard method for setting a port open/closed.
** A convention. Not all ports use this method.
**
***********************************************************************/
{
REBVAL *state = BLK_SKIP(port, STD_PORT_STATE);
if (IS_BINARY(state)) {
if (flag) SET_OPEN(VAL_BIN_DATA(state));
else SET_CLOSED(VAL_BIN_DATA(state));
// Validate if handle has correct type and is for the expected device
if (IS_HANDLE(state) && VAL_HANDLE_TYPE(state) == type) {
req = (REBREQ *)VAL_HANDLE_CONTEXT_DATA(state);
if (req->device == device) return state;
}
}


/***********************************************************************
**
*/ void *Use_Port_State(REBSER *port, REBCNT device, REBCNT size)
/*
** Use private state area in a port. Create if necessary.
** The size is that of a binary structure used by
** the port for storing internal information.
**
***********************************************************************/
{
REBVAL *state = BLK_SKIP(port, STD_PORT_STATE);

// If state is not a binary structure, create it:
if (!IS_BINARY(state)) {
REBSER *data = Make_Binary(size);
REBREQ *req = (REBREQ*)STR_HEAD(data);
req->clen = size;
CLEAR(STR_HEAD(data), size);
data->tail = size; // makes it easier for ACCEPT to clone the port
SET_FLAG(req->flags, RRF_ALLOC); // not on stack
req->port = port;
req->device = device;
Set_Binary(state, data);
PROTECT_SERIES(data); // protect state from modification...
LOCK_SERIES(data); // ... permanently
// If state is not a handle of the request type, create it:
MAKE_HANDLE(state, type);
if (!VAL_HANDLE_CTX(state)) {
Trap0(RE_NO_MEMORY);
return NULL;
}
req = (REBREQ *)VAL_HANDLE_CONTEXT_DATA(state);
req->port = port;
req->device = device;

return (void *)VAL_BIN(state);
return state;
}


Expand All @@ -129,8 +97,8 @@

if (IS_PORT(port)) {
state = BLK_SKIP(VAL_PORT(port), STD_PORT_STATE);
if (IS_BINARY(state)) {
req = (REBREQ*)VAL_BIN(state);
if (IS_HANDLE(state)) {
req = (REBREQ*)VAL_HANDLE_CONTEXT_DATA(state);
if (!GET_FLAG(req->flags, RRF_PENDING)) return FALSE;
}
}
Expand Down Expand Up @@ -335,44 +303,6 @@ xx*/ REBINT Wait_Device(REBREQ *req, REBCNT timeout)
}


#ifdef not_used
/***********************************************************************
**
*/ REBVAL *Form_Write(REBVAL *arg, REBYTE *newline)
/*
** Converts REBOL values to strings to use as data in WRITE.
** Will also add newlines for conversions of blocks of lines.
**
***********************************************************************/
{
REBSER *series;
REBVAL *val;
REBCNT n = 0;
//REB_MOLD mo = {0 --- more here needed};

if (IS_BLOCK(arg)) {

if (newline) n = LEN_BYTES(newline);

mo.series = series = Make_Binary(VAL_BLK_LEN(arg) * 10);

for (val = VAL_BLK_DATA(arg); NOT_END(val); val++) {
Mold_Value(&mo, val, 0);
if (newline) Append_Series(series, newline, n);
}

Set_String(arg, series);
}

if (!ANY_STRING(arg)) {
Set_String(arg, Copy_Form_Value(arg, 0));
}

return arg;
}
#endif


/***********************************************************************
**
*/ REBCNT Find_Action(REBVAL *object, REBCNT action)
Expand Down Expand Up @@ -465,13 +395,13 @@ xx*/ REBINT Wait_Device(REBREQ *req, REBCNT timeout)
if (GET_FLAG(req->modes, RFM_WRITE)) Trap_Security(flags[POL_WRITE], kind, name);
}


/***********************************************************************
**
*/ REBSER *Validate_Port_Value(REBVAL *value)
/*
** Because port actors are exposed to the user level, we must
** prevent them from being called with invalid values.
** NOTE: used with ports not using native state handle.
**
***********************************************************************/
{
Expand All @@ -488,6 +418,24 @@ xx*/ REBINT Wait_Device(REBREQ *req, REBCNT timeout)
return port;
}

/***********************************************************************
**
*/ REBSER *Validate_Port_With_Request(REBVAL *port_value, REBCNT device, REBREQ**req)
/*
** Because port actors are exposed to the user level, we must
** prevent them from being called with invalid values.
** If port requires a native state, create the handle if not exists.
**
***********************************************************************/
{
REBSER *port = Validate_Port_Value(port_value);
REBVAL *state = Use_Port_State_Handle(port, device, SYM_PORT_STATEX);
*req = (REBREQ *)VAL_HANDLE_CONTEXT_DATA(state);
return port;
}



/***********************************************************************
**
** Scheme Native Action Support
Expand Down Expand Up @@ -620,6 +568,9 @@ SCHEME_ACTIONS *Scheme_Actions; // Initial Global (not threaded)
**
***********************************************************************/
{
// Register a handle used to hold native port states
Register_Handle(SYM_PORT_STATEX, sizeof(REBREQ), NULL);

Scheme_Actions = Make_Mem(sizeof(SCHEME_ACTIONS) * MAX_SCHEMES);

Init_Console_Scheme();
Expand Down
4 changes: 1 addition & 3 deletions src/core/p-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@
REBCNT len;
//REBOOL sync = FALSE; // act synchronously

port = Validate_Port_Value(port_value);
port = Validate_Port_With_Request(port_value, RDI_AUDIO, &req);

arg = D_ARG(2);

req = Use_Port_State(port, RDI_AUDIO, sizeof(REBREQ));

switch (action) {
case A_WRITE:
case A_INSERT:
Expand Down
4 changes: 1 addition & 3 deletions src/core/p-checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@
REBVAL *data;
REBVAL *ctx;

port = Validate_Port_Value(port_value);
port = Validate_Port_With_Request(port_value, RDI_CHECKSUM, &req);

spec = BLK_SKIP(port, STD_PORT_SPEC);
if (!IS_OBJECT(spec)) Trap1(RE_INVALID_SPEC, spec);
Expand All @@ -286,8 +286,6 @@
Trap1(RE_INVALID_SPEC, spec);
}

req = Use_Port_State(port, RDI_CHECKSUM, sizeof(REBREQ));

data = BLK_SKIP(port, STD_PORT_DATA); //will hold result
ctx = BLK_SKIP(port, STD_PORT_EXTRA);
REBLEN ctx_size = 0, blk_size = 0;
Expand Down
7 changes: 2 additions & 5 deletions src/core/p-clipboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@
REBINT len;
REBSER *ser;

port = Validate_Port_Value(port_value);

arg = D_ARG(2);

req = Use_Port_State(port, RDI_CLIPBOARD, sizeof(REBREQ));
port = Validate_Port_With_Request(port_value, RDI_CLIPBOARD, &req);

switch (action) {
case A_UPDATE:
Expand Down Expand Up @@ -113,6 +109,7 @@
return R_RET;

case A_WRITE:
arg = D_ARG(2);
if (!(IS_STRING(arg) || IS_BINARY(arg))) {
#ifdef WRITE_ANY_VALUE_TO_CLIPBOARD
REB_MOLD mo = {0};
Expand Down
3 changes: 1 addition & 2 deletions src/core/p-dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@
REBOOL sync = FALSE; // act synchronously
REBVAL tmp;

port = Validate_Port_Value(port_value);
port = Validate_Port_With_Request(port_value, RDI_DNS, &sock);

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

sock = Use_Port_State(port, RDI_DNS, sizeof(*sock));
spec = OFV(port, STD_PORT_SPEC);

sock->timeout = 4000; // where does this go? !!!
Expand Down
15 changes: 5 additions & 10 deletions src/core/p-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@
**
***********************************************************************/
{
if (Is_Port_Open(port)) Trap1(RE_ALREADY_OPEN, path);
if (IS_OPEN(file)) Trap1(RE_ALREADY_OPEN, path);

if (OS_DO_DEVICE(file, RDC_OPEN) < 0) Trap_Port(RE_CANNOT_OPEN, port, file->error);

Set_Port_Open(port, TRUE);
SET_OPEN(file);
}


Expand Down Expand Up @@ -476,21 +476,16 @@ REBINT Mode_Syms[] = {

//Print("FILE ACTION: %r", Get_Action_Word(action));

port = Validate_Port_Value(port_value);

*D_RET = *D_ARG(1);
port = Validate_Port_With_Request(port_value, RDI_FILE, &file);

// Validate PORT fields:
spec = BLK_SKIP(port, STD_PORT_SPEC);
if (!IS_OBJECT(spec)) Trap1(RE_INVALID_SPEC, spec);
spec = OFV(port, STD_PORT_SPEC);
path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF);
if (!path) Trap1(RE_INVALID_SPEC, spec);

if (IS_URL(path)) path = Obj_Value(spec, STD_PORT_SPEC_FILE_PATH);
else if (!IS_FILE(path)) Trap1(RE_INVALID_SPEC, path);

// Get or setup internal state data:
file = (REBREQ*)Use_Port_State(port, RDI_FILE, sizeof(*file));
*D_RET = *D_ARG(1);

switch (action) {

Expand Down
4 changes: 1 addition & 3 deletions src/core/p-midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@

//printf("MIDI_Actor action: %i\n", action);

port = Validate_Port_Value(port_value);

req = Use_Port_State(port, RDI_MIDI, sizeof(REBREQ));
port = Validate_Port_With_Request(port_value, RDI_MIDI, &req);

switch (action) {

Expand Down
10 changes: 5 additions & 5 deletions src/core/p-net.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ enum Transport_Types {
***********************************************************************/
{
REBREQ *nsock;
REBVAL *state;

// Get temp sock struct created by the device:
nsock = sock->sock;
Expand All @@ -163,9 +164,10 @@ enum Transport_Types {
SET_NONE(OFV(port, STD_PORT_STATE)); // just to be sure.

// Copy over the new sock data:
sock = Use_Port_State(port, RDI_NET, sizeof(*sock));
state = Use_Port_State_Handle(port, RDI_NET, SYM_PORT_STATEX);
sock = (REBREQ *)VAL_HANDLE_CONTEXT_DATA(state);
*sock = *nsock;
sock->clen = sizeof(*sock);
//sock->clen = sizeof(*sock);
sock->port = port;
OS_FREE(nsock); // allocated by dev_net.c (MT issues?)
}
Expand All @@ -186,13 +188,11 @@ enum Transport_Types {
REBCNT len; // generic length
REBSER *ser; // simplifier

port = Validate_Port_Value(port_value);
port = Validate_Port_With_Request(port_value, RDI_NET, &sock);

*D_RET = *D_ARG(1);
arg = D_ARG(2);
//refs = 0;

sock = Use_Port_State(port, RDI_NET, sizeof(*sock));
if (proto == TRANSPORT_UDP) {
SET_FLAG(sock->modes, RST_UDP);
}
Expand Down
9 changes: 1 addition & 8 deletions src/core/p-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,15 @@
REBCNT refs; // refinement argument flags
REBCNT len; // generic length
REBSER *ser; // simplifier
REBVAL *path;
REBSER *port;

port = Validate_Port_Value(port_value);
port = Validate_Port_With_Request(port_value, RDI_SERIAL, &req);

*D_RET = *D_ARG(1);

// Validate PORT fields:
spec = OFV(port, STD_PORT_SPEC);
if (!IS_OBJECT(spec)) Trap0(RE_INVALID_PORT);
path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF);
if (!path) Trap1(RE_INVALID_SPEC, spec);

//if (!IS_FILE(path)) Trap1(RE_INVALID_SPEC, path);

req = Use_Port_State(port, RDI_SERIAL, sizeof(*req));

// Actions for an unopened serial port:
if (!IS_OPEN(req)) {
Expand Down

0 comments on commit 2d9961e

Please sign in to comment.