Tcl_Ungets help [long, technical]?



Hi all.

Does anyone have experience using Tcl_Ungets, and mixing stdio and Tcl
streams?

Here's the scenario: we have a socket sending data. To avoid the "read and
resend" overhead, the Tcl app which is in control passes the Tcl channel to
my C++ extension to let it read and parse the data directly, and when the
data is done (ends with "." on a line by itself), my extension returns.

The controlling Tcl code (not mine, although I can poke around in it a bit)
then reads the socket with gets until it read a "." of its own (i.e. a
second ".").

Here's what the C++ code currently does (and it works) - I've omitted some
details for clarity:

Tcl_Channel ch = Tcl_GetChannel(interp, channel, &mode);
while( (len = Tcl_Gets(ch,&dstring)) >= 0 )
{
// do a little processing on the line

// process the object
processObject();

//needed to avoid appending
Tcl_DStringSetLength(&dstring,0);
}
Tcl_DStringFree(&dstring);

what I'd LIKE to do (I realize this is probably Unix specific - we'll deal
with Windows when we get to it):

Tcl_Channel ch = Tcl_GetChannel(interp, channel, &mode);

int fd, dfd;

if( Tcl_GetChannelHandle(ch, mode, (ClientData*) &fd) != TCL_OK)
{
//error
return;
}

dfd = dup(fd);
FILE *fp = fdopen(dfd, "r");
while( fgets(buff,10239, fp) != NULL )
{
// do a little processing on the line

// process the object
processObject();
}


That part works.

The problem is: due to buffering, etc. my dup-ed stream reads the second "."
from the socket, and when I return, there's no data for the Tcl app to
consume, so it blocks in its "gets".

So, in order to combat that, I've tried (after the second example above):

close(dfd);
idx = 0;
while( (c = fgets(fp)) != EOF )
{
buff[idx++] = c;
}
buff[idx]='\0';
fclose(fp);

printf("Channel bytes buffered: %d\n",Tcl_InputBuffered(ch));
c = Tcl_Ungets(ch,buff,idx,0);
printf("Channel bytes buffered: %d\n",Tcl_InputBuffered(ch));

printf("Start Reading\n");
while( (len = Tcl_Gets(ch,&dstring)) >= 0 )
{
printf("Read after bytes: %s\n",&dstring);
}
printf("Done Reading\n");


(the last little bit is to test the Ungets to see if it works).

I now get:
Channel bytes buffered: 0
Channel bytes buffered: 14
Start Reading

(and that's it).

I.e. MY code is now blocking in the Tcl_Gets.

However, I'm absolutely sure there are two \n's in the data. For good
measure, I translated \n to \r\n (Tcl seems to prefer this), and Tcl_Gets
still blocks. Even though there are two full lines to read, and
Tcl_InputBuffered tells me it got them.

So, obviously the "gets" in Tcl code after I return will also block. What am
I missing?

Thanks,
Mattias
.



Relevant Pages

  • Re: Integrating C++ and Tcl event loops.
    ... At that point the function reading data off of the socket ... doesn't know if the Tcl interp is executing anything or not. ... unavailable for that compile. ... when Tcl is compiled for multithread support ...
    (comp.lang.tcl)
  • Dr. Dobbs Tcl-URL! - weekly Tcl news and links (Mar 16)
    ... control over socket options. ... compatible with existing Tcl socket based applications. ... The cep command ... XML items ...
    (comp.lang.tcl)
  • Re: Tcl on Google Android phones
    ... 'The Jacl executable is 200 MB big, and Android has a executable ... writes the user's files via a socket based mechanism. ... This should also be buildable / testable using pure Tcl and components ... unless that if for all executables combined. ...
    (comp.lang.tcl)
  • Re: Question about Tcl event loop/Tcl_EventQueue and friends
    ... Part of my solution involves a socket on which Tcl script ... The main loop (before Tcl/Tk was added) was: ...
    (comp.lang.tcl)
  • Re: Text Parser
    ... Szombathely, Hungary never picked up a TCL book, but can write some ... Socket Number, Barcode, Time-stamp, Date Stamp, Test-Time, test1, ...
    (comp.lang.tcl)