Revision: 76613
http://sourceforge.net/p/brlcad/code/76613
Author: starseeker
Date: 2020-07-31 19:18:16 +0000 (Fri, 31 Jul 2020)
Log Message:
-----------
Further restructuring of the callback mechanisms for subprocess I/O.
Modified Paths:
--------------
brlcad/branches/bioh/include/ged/defines.h
brlcad/branches/bioh/include/tclcad.h
brlcad/branches/bioh/src/libged/ged_util.c
brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c
brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c
brlcad/branches/bioh/src/libtclcad/tclcad_obj.c
brlcad/branches/bioh/src/mged/setup.c
Modified: brlcad/branches/bioh/include/ged/defines.h
===================================================================
--- brlcad/branches/bioh/include/ged/defines.h 2020-07-31 16:00:56 UTC (rev
76612)
+++ brlcad/branches/bioh/include/ged/defines.h 2020-07-31 19:18:16 UTC (rev
76613)
@@ -250,11 +250,21 @@
void (*ged_create_vlist_callback)(struct
display_list *); /**< @brief function to call after all vlist created that
loops through creating display list for each solid */
void (*ged_free_vlist_callback)(unsigned int, int);
/**< @brief function to call after freeing a vlist */
- /* Handler functions for I/O communication with asynchronous subprocess
commands */
+ /* Handler functions for I/O communication with asynchronous subprocess
commands. There
+ * are two opaque data structures at play here, with different scopes.
One is the "data"
+ * pointer passed to ged_create_io_handler, which is used to store
command-specific
+ * information internal to the library (the simplest thing to do is pass
ged_subprocess
+ * in as the data pointer, but if that's not enough - see for example
rtcheck - this
+ * mechanism allows for more elaborate measures.
+ *
+ * The second is ged_io_data, which is set in gedp by the calling
application. This is where
+ * information specific to the parent's I/O environment (which by
definition the library
+ * can't know about as it is application specific) lives. It should be
assigned in the
+ * applications gedp before any calls to ged_create_io_handler are made.
+ * */
+ void (*ged_create_io_handler)(struct ged_subprocess *gp, int fd,
ged_io_handler_callback_t callback, void *data);
+ void (*ged_delete_io_handler)(struct ged_subprocess *gp, int fd);
void *ged_io_data; /**< brief caller supplied data */
- int io_mode;
- void (*ged_create_io_handler)(void **chan, struct bu_process *p, int fd,
int mode, void *data, ged_io_handler_callback_t callback);
- void (*ged_delete_io_handler)(void *interp, void *chan, struct bu_process
*p, int fd);
// Other callbacks...
// Tcl command strings - these are libtclcad level callbacks that execute
user supplied Tcl commands if set:
Modified: brlcad/branches/bioh/include/tclcad.h
===================================================================
--- brlcad/branches/bioh/include/tclcad.h 2020-07-31 16:00:56 UTC (rev
76612)
+++ brlcad/branches/bioh/include/tclcad.h 2020-07-31 19:18:16 UTC (rev
76613)
@@ -514,16 +514,17 @@
TCLCAD_EXPORT extern int tclcad_init(Tcl_Interp *interp, int init_gui, struct
bu_vls *tlog);
/**
- * Create Tcl specific I/O handlers
+ * Tcl specific I/O handlers
*/
+struct tclcad_io_data {
+ Tcl_Channel chan;
+ Tcl_Interp *interp;
+ int io_mode;
+};
TCLCAD_EXPORT void
-tclcad_create_io_handler(void **chan, struct bu_process *p, int fd, int mode,
void *data, ged_io_handler_callback_t callback);
-
-/**
- * Delete Tcl specific I/O handlers
- */
+tclcad_create_io_handler(struct ged_subprocess *p, int fd,
ged_io_handler_callback_t callback, void *data);
TCLCAD_EXPORT void
-tclcad_delete_io_handler(void *interp, void *chan, struct bu_process *p, int
fd);
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd);
/* dm_tcl.c */
Modified: brlcad/branches/bioh/src/libged/ged_util.c
===================================================================
--- brlcad/branches/bioh/src/libged/ged_util.c 2020-07-31 16:00:56 UTC (rev
76612)
+++ brlcad/branches/bioh/src/libged/ged_util.c 2020-07-31 19:18:16 UTC (rev
76613)
@@ -1297,27 +1297,19 @@
}
}
-struct _ged_rt_client_data {
- struct ged_subprocess *rrtp;
- void *u_data;
-};
-
void
_ged_rt_output_handler(void *clientData, int UNUSED(mask))
{
- struct _ged_rt_client_data *drcdp = (struct _ged_rt_client_data
*)clientData;
+ struct ged_subprocess *rrtp = (struct ged_subprocess *)clientData;
int count = 0;
int retcode = 0;
int read_failed = 0;
char line[RT_MAXLINE+1] = {0};
- if ((drcdp == (struct _ged_rt_client_data *)NULL) ||
- (drcdp->rrtp == (struct ged_subprocess *)NULL) ||
- (drcdp->rrtp->gedp == (struct ged *)NULL))
+ if ((rrtp == (struct ged_subprocess *)NULL) || (rrtp->gedp == (struct ged
*)NULL))
return;
- struct ged *gedp = drcdp->rrtp->gedp;
- struct ged_subprocess *rrtp = drcdp->rrtp;
+ struct ged *gedp = rrtp->gedp;
/* Get data from rt */
if (bu_process_read((char *)line, &count, rrtp->p, BU_PROCESS_STDERR,
RT_MAXLINE) <= 0) {
@@ -1329,7 +1321,7 @@
/* Done watching for output, undo subprocess I/O hooks. */
if (gedp->ged_delete_io_handler) {
- (*gedp->ged_delete_io_handler)(gedp->ged_interp, rrtp->chan,
rrtp->p, BU_PROCESS_STDERR);
+ (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDERR);
}
@@ -1350,7 +1342,6 @@
/* free rrtp */
BU_LIST_DEQUEUE(&rrtp->l);
BU_PUT(rrtp, struct ged_subprocess);
- BU_PUT(drcdp, struct _ged_rt_client_data);
return;
}
@@ -1432,7 +1423,6 @@
FILE *fp_in;
vect_t eye_model;
struct ged_subprocess *run_rtp;
- struct _ged_rt_client_data *drcdp;
struct bu_process *p = NULL;
bu_process_exec(&p, gd_rt_cmd[0], cmd_len, gd_rt_cmd, 0, 0);
@@ -1460,13 +1450,9 @@
run_rtp->aborted = 0;
run_rtp->gedp = gedp;
- BU_GET(drcdp, struct _ged_rt_client_data);
- drcdp->rrtp = run_rtp;
- drcdp->u_data = gedp->ged_io_data;
-
/* If we know how, set up hooks so the parent process knows to watch for
output. */
if (gedp->ged_create_io_handler) {
- (*gedp->ged_create_io_handler)(&(run_rtp->chan), p, BU_PROCESS_STDERR,
gedp->io_mode, (void *)drcdp, _ged_rt_output_handler);
+ (*gedp->ged_create_io_handler)(run_rtp, BU_PROCESS_STDERR,
_ged_rt_output_handler, (void *)run_rtp);
}
return GED_OK;
}
Modified: brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c
===================================================================
--- brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c 2020-07-31 16:00:56 UTC
(rev 76612)
+++ brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c 2020-07-31 19:18:16 UTC
(rev 76613)
@@ -39,13 +39,11 @@
struct ged_rtcheck {
struct ged_subprocess *rrtp;
- struct ged *gedp;
FILE *fp;
struct bn_vlblock *vbp;
struct bu_list *vhead;
double csize;
void *chan;
- struct bu_process *p;
int read_failed;
int draw_read_failed;
};
@@ -54,24 +52,24 @@
rtcheck_handler_cleanup(struct ged_rtcheck *rtcp)
{
int retcode;
+ struct ged_subprocess *rrtp = rtcp->rrtp;
+ struct ged *gedp = rrtp->gedp;
- if (rtcp->gedp->ged_delete_io_handler) {
- (*rtcp->gedp->ged_delete_io_handler)(rtcp->gedp->ged_interp,
rtcp->rrtp->chan,
- rtcp->rrtp->p, BU_PROCESS_STDOUT);
- (*rtcp->gedp->ged_delete_io_handler)(rtcp->gedp->ged_interp, rtcp->chan,
- rtcp->p, BU_PROCESS_STDERR);
+ if (gedp->ged_delete_io_handler) {
+ (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDOUT);
+ (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDERR);
}
- bu_process_close(rtcp->rrtp->p, BU_PROCESS_STDOUT);
+ bu_process_close(rrtp->p, BU_PROCESS_STDOUT);
/* wait for the forked process */
- retcode = bu_process_wait(NULL, rtcp->rrtp->p, 0);
+ retcode = bu_process_wait(NULL, rrtp->p, 0);
if (retcode != 0) {
- _ged_wait_status(rtcp->gedp->ged_result_str, retcode);
+ _ged_wait_status(gedp->ged_result_str, retcode);
}
- BU_LIST_DEQUEUE(&rtcp->rrtp->l);
- BU_PUT(rtcp->rrtp, struct ged_subprocess);
+ BU_LIST_DEQUEUE(&rrtp->l);
+ BU_PUT(rrtp, struct ged_subprocess);
BU_PUT(rtcp, struct ged_rtcheck);
}
@@ -80,6 +78,8 @@
{
int value = 0;
struct ged_rtcheck *rtcp = (struct ged_rtcheck *)clientData;
+ struct ged_subprocess *rrtp = rtcp->rrtp;
+ struct ged *gedp = rrtp->gedp;
/* Get vector output from rtcheck */
if (!rtcp->draw_read_failed && (feof(rtcp->fp) || (value = getc(rtcp->fp))
== EOF)) {
@@ -89,7 +89,7 @@
rtcp->draw_read_failed = 1;
- dl_set_flag(rtcp->gedp->ged_gdp->gd_headDisplay, DOWN);
+ dl_set_flag(gedp->ged_gdp->gd_headDisplay, DOWN);
/* Add overlay (or, if nothing to draw, clear any stale overlay) */
if (rtcp->vbp) {
@@ -102,7 +102,7 @@
}
if (have_visual) {
- _ged_cvt_vlblock_to_solids(rtcp->gedp, rtcp->vbp, sname, 0);
+ _ged_cvt_vlblock_to_solids(gedp, rtcp->vbp, sname, 0);
bn_vlblock_free(rtcp->vbp);
} else {
/* TODO - yuck. This name is a product of the internals of the
@@ -112,8 +112,8 @@
* current phony object drawing system.*/
const char *sname_obj = "OVERLAPSffff00";
struct directory *dp;
- if ((dp = db_lookup(rtcp->gedp->ged_wdbp->dbip, sname_obj,
LOOKUP_QUIET)) != RT_DIR_NULL) {
- dl_erasePathFromDisplay(rtcp->gedp, sname_obj, 0);
+ if ((dp = db_lookup(gedp->ged_wdbp->dbip, sname_obj, LOOKUP_QUIET))
!= RT_DIR_NULL) {
+ dl_erasePathFromDisplay(gedp, sname_obj, 0);
}
}
@@ -131,7 +131,7 @@
rtcp->fp,
value,
rtcp->csize,
- rtcp->gedp->ged_gdp->gd_uplotOutputMode);
+ gedp->ged_gdp->gd_uplotOutputMode);
}
}
@@ -141,12 +141,14 @@
int count;
char line[RT_MAXLINE] = {0};
struct ged_rtcheck *rtcp = (struct ged_rtcheck *)clientData;
+ struct ged_subprocess *rrtp = rtcp->rrtp;
+ struct ged *gedp = rrtp->gedp;
/* Get textual output from rtcheck */
- if (bu_process_read((char *)line, &count, rtcp->p, BU_PROCESS_STDERR,
RT_MAXLINE) <= 0) {
+ if (bu_process_read((char *)line, &count, rrtp->p, BU_PROCESS_STDERR,
RT_MAXLINE) <= 0) {
rtcp->read_failed = 1;
- if (rtcp->gedp->ged_gdp->gd_rtCmdNotify != (void (*)(int))0)
- rtcp->gedp->ged_gdp->gd_rtCmdNotify(0);
+ if (gedp->ged_gdp->gd_rtCmdNotify != (void (*)(int))0)
+ gedp->ged_gdp->gd_rtCmdNotify(0);
}
@@ -156,10 +158,10 @@
}
line[count] = '\0';
- if (rtcp->gedp->ged_output_handler != (void (*)(struct ged *, char *))0) {
- ged_output_handler_cb(rtcp->gedp, line);
+ if (gedp->ged_output_handler != (void (*)(struct ged *, char *))0) {
+ ged_output_handler_cb(gedp, line);
} else {
- bu_vls_printf(rtcp->gedp->ged_result_str, "%s", line);
+ bu_vls_printf(gedp->ged_result_str, "%s", line);
}
}
@@ -253,7 +255,6 @@
/* create the rtcheck struct */
BU_GET(rtcp, struct ged_rtcheck);
- rtcp->gedp = gedp;
rtcp->fp = bu_process_open(p, BU_PROCESS_STDOUT);
/* Needed on Windows for successful rtcheck drawing data communication */
setmode(fileno(rtcp->fp), O_BINARY);
@@ -260,7 +261,6 @@
rtcp->vbp = rt_vlblock_init();
rtcp->vhead = bn_vlblock_find(rtcp->vbp, 0xFF, 0xFF, 0x00);
rtcp->csize = gedp->ged_gvp->gv_scale * 0.01;
- rtcp->p = p;
rtcp->read_failed = 0;
rtcp->draw_read_failed = 0;
@@ -270,13 +270,13 @@
rtcp->rrtp->aborted = 0;
rtcp->rrtp->gedp = gedp;
if (gedp->ged_create_io_handler) {
- (*gedp->ged_create_io_handler)(&(rtcp->rrtp->chan), p,
BU_PROCESS_STDOUT, gedp->io_mode, (void *)rtcp, rtcheck_vector_handler);
+ (*gedp->ged_create_io_handler)(rtcp->rrtp, BU_PROCESS_STDOUT,
rtcheck_vector_handler, (void *)rtcp);
}
BU_LIST_INIT(&rtcp->rrtp->l);
BU_LIST_APPEND(&gedp->gd_headSubprocess.l, &rtcp->rrtp->l);
if (gedp->ged_create_io_handler) {
- (*gedp->ged_create_io_handler)(&(rtcp->chan), p, BU_PROCESS_STDERR,
gedp->io_mode, (void *)rtcp, rtcheck_output_handler);
+ (*gedp->ged_create_io_handler)(rtcp->rrtp, BU_PROCESS_STDERR,
rtcheck_output_handler, (void *)rtcp);
}
bu_free(gd_rt_cmd, "free gd_rt_cmd");
Modified: brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c
===================================================================
--- brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c 2020-07-31 16:00:56 UTC
(rev 76612)
+++ brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c 2020-07-31 19:18:16 UTC
(rev 76613)
@@ -38,17 +38,10 @@
#include "../ged_private.h"
-struct _ged_rt_client_data {
- struct ged_subprocess *rrtp;
- void *u_data;
-};
-
-
int
_ged_run_rtwizard(struct ged *gedp, int cmd_len, const char **gd_rt_cmd)
{
struct ged_subprocess *run_rtp;
- struct _ged_rt_client_data *drcdp;
struct bu_process *p;
bu_process_exec(&p, gd_rt_cmd[0], cmd_len, (const char **)gd_rt_cmd, 0, 0);
@@ -70,13 +63,8 @@
run_rtp->aborted = 0;
run_rtp->gedp = gedp;
- /* must be BU_GET() to match release in _ged_rt_output_handler */
- BU_GET(drcdp, struct _ged_rt_client_data);
- drcdp->rrtp = run_rtp;
- drcdp->u_data = gedp->ged_io_data;
-
if (gedp->ged_create_io_handler) {
- (*gedp->ged_create_io_handler)(&(run_rtp->chan), p, BU_PROCESS_STDERR,
gedp->io_mode, (void *)drcdp, _ged_rt_output_handler);
+ (*gedp->ged_create_io_handler)(run_rtp, BU_PROCESS_STDERR,
_ged_rt_output_handler, (void *)run_rtp);
}
return GED_OK;
Modified: brlcad/branches/bioh/src/libtclcad/tclcad_obj.c
===================================================================
--- brlcad/branches/bioh/src/libtclcad/tclcad_obj.c 2020-07-31 16:00:56 UTC
(rev 76612)
+++ brlcad/branches/bioh/src/libtclcad/tclcad_obj.c 2020-07-31 19:18:16 UTC
(rev 76613)
@@ -1135,6 +1135,10 @@
BU_PUT(tgd, struct tclcad_ged_data);
top->to_gedp->u_data = NULL;
}
+ if (top->to_gedp->ged_io_data) {
+ struct tclcad_io_data *t_iod = (struct tclcad_io_data
*)top->to_gedp->ged_io_data;
+ BU_PUT(t_iod, struct tclcad_io_data);
+ }
// Got the libtclcad cleanup done, have libged do its up.
ged_close(top->to_gedp);
@@ -1176,20 +1180,19 @@
/* Wrappers for setting up/tearing down IO handler */
#ifndef _WIN32
void
-tclcad_create_io_handler(void **UNUSED(chan), struct bu_process *p, int fd,
int mode, void *data, ged_io_handler_callback_t callback)
+tclcad_create_io_handler(struct ged_subprocess *p, int fd,
ged_io_handler_callback_t callback, void *data)
{
- int *fdp;
- if (!p) return;
- fdp = (int *)bu_process_fd(p, fd);
- Tcl_CreateFileHandler(*fdp, mode, callback, (ClientData)data);
+ if (!p || !p->p || !p->gedp || !p->gedp->ged_io_data) return;
+ int *fdp = (int *)bu_process_fd(p->p, fd);
+ struct tclcad_io_data *t_iod = (struct tclcad_io_data
*)p->gedp->ged_io_data;
+ Tcl_CreateFileHandler(*fdp, t_iod->io_mode, callback, (ClientData)data);
}
void
-tclcad_delete_io_handler(void *UNUSED(interp), void *UNUSED(chan), struct
bu_process *p, int fd)
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd)
{
- int *fdp;
if (!p) return;
- fdp = (int *)bu_process_fd(p, fd);
+ int *fdp = (int *)bu_process_fd(p->p, fd);
Tcl_DeleteFileHandler(*fdp);
close(*fdp);
}
@@ -1196,25 +1199,23 @@
#else
void
-tclcad_create_io_handler(void **chan, struct bu_process *p, int fd, int mode,
void *data, ged_io_handler_callback_t callback)
+tclcad_create_io_handler(struct ged_subprocess *p, int fd,
ged_io_handler_callback_t callback, void *data)
{
- HANDLE *fdp;
- if (!chan || !p) return;
- fdp = (HANDLE *)bu_process_fd(p, fd);
- (*chan) = (void *)Tcl_MakeFileChannel(*fdp, mode);
- Tcl_CreateChannelHandler((Tcl_Channel)(*chan), mode, callback,
(ClientData)data);
+ if (!p || !p->p || !p->gedp || !p->gedp->ged_io_data) return;
+ struct tclcad_io_data *t_iod = (struct tclcad_io_data
*)p->gedp->ged_io_data;
+ HANDLE *fdp = (HANDLE *)bu_process_fd(p->p, fd);
+ (*t_iod->chan) = (void *)Tcl_MakeFileChannel(*fdp, t_iod->io_mode);
+ Tcl_CreateChannelHandler(*t_iod->chan, t_iod->io_mode, callback,
(ClientData)data);
}
void
-tclcad_delete_io_handler(void *interp, void *chan, struct bu_process *p, int
fd)
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd)
{
- HANDLE *fdp;
- Tcl_Interp *tcl_interp;
- if (!chan || !p) return;
- tcl_interp = (Tcl_Interp *)interp;
- fdp = (HANDLE *)bu_process_fd(p, fd);
- Tcl_DeleteChannelHandler((Tcl_Channel)chan, NULL, (ClientData)NULL);
- Tcl_Close(tcl_interp, (Tcl_Channel)chan);
+ if (!p || !p->p || !p->p->gedp || !p->p->gedp->ged_io_data) return;
+ struct tclcad_io_data *t_iod = (struct tclcad_io_data
*)p->gedp->ged_io_data;
+ HANDLE *fdp = (HANDLE *)bu_process_fd(p->p, fd);
+ Tcl_DeleteChannelHandler(t_oid->chan, NULL, (ClientData)NULL);
+ Tcl_Close(t_oid->interp, t_oid->chan);
}
#endif
@@ -1295,9 +1296,13 @@
gedp->ged_interp = (void *)interp;
/* Set the Tcl specific I/O handlers for asynchronous subprocess I/O */
+ struct tclcad_io_data *t_iod;
+ BU_GET(t_iod, struct tclcad_io_data);
+ t_iod->io_mode = TCL_READABLE;
+ t_iod->interp = interp;
+ gedp->ged_io_data = (void *)t_iod;
gedp->ged_create_io_handler = &tclcad_create_io_handler;
gedp->ged_delete_io_handler = &tclcad_delete_io_handler;
- gedp->io_mode = TCL_READABLE;
/* initialize tclcad_obj */
BU_ALLOC(top, struct tclcad_obj);
Modified: brlcad/branches/bioh/src/mged/setup.c
===================================================================
--- brlcad/branches/bioh/src/mged/setup.c 2020-07-31 16:00:56 UTC (rev
76612)
+++ brlcad/branches/bioh/src/mged/setup.c 2020-07-31 19:18:16 UTC (rev
76613)
@@ -476,10 +476,15 @@
mged_global_variable_setup(*interpreter);
mged_variable_setup(*interpreter);
GEDP->ged_interp = (void *)*interpreter;
+ GEDP->ged_interp_eval = &mged_db_search_callback;
+
+ struct tclcad_io_data *t_iod;
+ BU_GET(t_iod, struct tclcad_io_data);
+ t_iod->io_mode = TCL_READABLE;
+ t_iod->interp = *interpreter;
+ GEDP->ged_io_data = t_iod;
GEDP->ged_create_io_handler = &tclcad_create_io_handler;
GEDP->ged_delete_io_handler = &tclcad_delete_io_handler;
- GEDP->io_mode = TCL_READABLE;
- GEDP->ged_interp_eval = &mged_db_search_callback;
/* Tcl needs to write nulls onto subscripted variable names */
bu_vls_printf(&str, "%s(state)", MGED_DISPLAY_VAR);
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits