RE: Line-oriented blocking input from sockets?
--- David Schwartz <[EMAIL PROTECTED]> wrote: > > > Ah, well, I meant that a state machine must store state > > explicitly, whereas > > with threaded code the state is implied in the code flow (in effect, the > > thread system itself is a state machine.) If each thread > > executes a simple > > function like "void foo() {A; B; C;}", then the equivalent state > > machine is > > simple enough -- it just has to remember whether each "thread" is > > at step A, > > B, or C, using an array of state variables or some such. But now > > throw in a > > few nested for's, if's, and local data into the above function... > > well, you > > get the picture. I could certainly implement my program as a > > state machine, > > but that may make my code harder for others to understand/maintain. > > Personally, I completely disagree. It is very hard to understand control > flow when all the state is hidden. You see a 'return' statement -- where > does that go? What if you want to log the state of a connection to > facilitate debugging? Hiding the state on the stack is not good practice. I don't entirely understand what you're saying -- is this a general argument against threads? I thought the whole point of Pth was to store thread state on the stack...? Well, maybe it would help me understand if we used a concrete example: void *threadMain(void *_arg) { char inputBuff[BUFFLEN], moreInput[BUFFLEN]; int client_fd = (int)_arg; pth_readline(client_fd, inputBuff, BUFLEN); if (strncmp(inputBuff, "GET ", 4) == 0) { pth_write(client_fd, ); } else if (strncmp(inputBuff, "PUT ", 4) == 0) { pth_readline(client_fd, moreInput, BUFLEN); pth_write(client_fd, ); } } Okay, so this is a really simple routine executed by worker threads to process a line or two of input from a client and send a response. Is this bad coding style? Would you do this with a single-threaded state machine of some sort? Or some other way? __ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
Re: [Pth] Re: Line-oriented blocking input from sockets?
--- "C. Scott Ananian" <[EMAIL PROTECTED]> wrote: > On Mon, 14 Jul 2003, Damon Hastings wrote: > > > Yeah, I guess my explanation was a little spotty. :-> What I want is > for a > > thread to block only until a newline is received on the socket it's > reading > > from. Suppose the socket receives the 12 bytes "hello world\n". That > has a > > newline and so I would want pth_readline() to return immediately with > the > > output "hello world\n". But if pth_readline() does a blocking 1024-byte > > read on the socket, it will find only 12 bytes available and will thus > > block. Furthermore, the remote host will not send any more bytes > because > > it's waiting for us to respond, and so pth_readline() will time out, or > > never return. > > I don't think there's any way in a POSIX/UNIX operating system to block > until *all of* 1024 bytes have been read from a file descriptor. > The blocking 'read' system call returns as soon as *any* bytes have been > read, not putting more than a certain number in the buffer you provide. > Under POSIX semantics, you *always* have to do a loop in order to > ensure your buffer is filled. Ah, yes, I should have known that. Thanks for straightening out my confusion. pth_readline() does indeed do exactly what I want. :) Damon __ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
RE: Line-oriented blocking input from sockets?
> Ah, well, I meant that a state machine must store state > explicitly, whereas > with threaded code the state is implied in the code flow (in effect, the > thread system itself is a state machine.) If each thread > executes a simple > function like "void foo() {A; B; C;}", then the equivalent state > machine is > simple enough -- it just has to remember whether each "thread" is > at step A, > B, or C, using an array of state variables or some such. But now > throw in a > few nested for's, if's, and local data into the above function... > well, you > get the picture. I could certainly implement my program as a > state machine, > but that may make my code harder for others to understand/maintain. Personally, I completely disagree. It is very hard to understand control flow when all the state is hidden. You see a 'return' statement -- where does that go? What if you want to log the state of a connection to facilitate debugging? Hiding the state on the stack is not good practice. DS __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
Re: [Pth] Re: Line-oriented blocking input from sockets?
On Mon, 14 Jul 2003, Damon Hastings wrote: > Yeah, I guess my explanation was a little spotty. :-> What I want is for a > thread to block only until a newline is received on the socket it's reading > from. Suppose the socket receives the 12 bytes "hello world\n". That has a > newline and so I would want pth_readline() to return immediately with the > output "hello world\n". But if pth_readline() does a blocking 1024-byte > read on the socket, it will find only 12 bytes available and will thus > block. Furthermore, the remote host will not send any more bytes because > it's waiting for us to respond, and so pth_readline() will time out, or > never return. I don't think there's any way in a POSIX/UNIX operating system to block until *all of* 1024 bytes have been read from a file descriptor. The blocking 'read' system call returns as soon as *any* bytes have been read, not putting more than a certain number in the buffer you provide. Under POSIX semantics, you *always* have to do a loop in order to ensure your buffer is filled. So I doubt that pth_read behaves differently. But I haven't looked at the Pth source code in years, so you might want to take a peek to find out if my assumptions are correct. --scott Nazi Rijndael cracking ammunition ASW Ft. Meade nuclear Secretary mail drop postcard United Nations milita assassinate explosives Yeltsin ( http://cscott.net/ ) __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
Re: Line-oriented blocking input from sockets?
--- "Ralf S. Engelschall" <[EMAIL PROTECTED]> wrote: > On Sun, Jul 13, 2003, Damon Hastings wrote: > > > [...] > > > See the file test_common.c in the Pth source tree. It provides a > > > pth_readline() function (just a small but sufficient buffered wrapper > > > around pth_read()) which should do exactly what you want. > > > > It looks like pth_readline_ev() reads a fixed number of bytes at a time > > (i.e. 1024) and will block until it reads that many (or eof). Is that > > right? That works great for reading a file, where more bytes (or eof) > are > > always available, but I'm reading from a socket. I was considering a > > non-blocking approach like: > > > > pth_fdmode(fd, PTH_FDMODE_NONBLOCK); > > while (newline not read yet) { > > pth_select on fd readable, with long timeout; > > bytes = pth_read(fd, buff, 1024); > > if (bytes == 0) > > cleanup on closed connection > > } > > I'm not sure whether I correctly understand your concerns. Yes, > pth_readline_ev() blocks, but just the current thread, of course. > That's what you usually want in a threaded application: you logically > program each thread in blocking mode, but the threading implementation > takes care that in case a thread would block, another (ready for next > operation) thread is scheduled for execution in the meantime. Internally > Pth uses non-blocking I/O to achieve all this, of course. Yeah, I guess my explanation was a little spotty. :-> What I want is for a thread to block only until a newline is received on the socket it's reading from. Suppose the socket receives the 12 bytes "hello world\n". That has a newline and so I would want pth_readline() to return immediately with the output "hello world\n". But if pth_readline() does a blocking 1024-byte read on the socket, it will find only 12 bytes available and will thus block. Furthermore, the remote host will not send any more bytes because it's waiting for us to respond, and so pth_readline() will time out, or never return. > Sure, Pth just swaps the stack pointer, of course. Nevertheless what > here was mentioned is the fact that each stack consumes memory. If you > have a large number of threads in your system, just the allocated stacks > already accumulate to a rather large memory consumption. Hey, that's great! I was a little concerned for a moment there. But with it just swapping a few pointers each context switch, Pth should be much faster than Linux Pthreads. (And I have 1GB physical RAM, so no worries about memory consumption.) Can you give me a ballpark idea of the cost per context switch for 150 threads, almost all of which are waiting on I/O at any given time? And does Pth block the entire process when all its threads are blocked? (I would assume so, if you're using a global "select" under the covers.) __ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
Re: Line-oriented blocking input from sockets?
On Sun, Jul 13, 2003, Damon Hastings wrote: > [...] > > See the file test_common.c in the Pth source tree. It provides a > > pth_readline() function (just a small but sufficient buffered wrapper > > around pth_read()) which should do exactly what you want. > > It looks like pth_readline_ev() reads a fixed number of bytes at a time > (i.e. 1024) and will block until it reads that many (or eof). Is that > right? That works great for reading a file, where more bytes (or eof) are > always available, but I'm reading from a socket. I was considering a > non-blocking approach like: > > pth_fdmode(fd, PTH_FDMODE_NONBLOCK); > while (newline not read yet) { > pth_select on fd readable, with long timeout; > bytes = pth_read(fd, buff, 1024); > if (bytes == 0) > cleanup on closed connection > } I'm not sure whether I correctly understand your concerns. Yes, pth_readline_ev() blocks, but just the current thread, of course. That's what you usually want in a threaded application: you logically program each thread in blocking mode, but the threading implementation takes care that in case a thread would block, another (ready for next operation) thread is scheduled for execution in the meantime. Internally Pth uses non-blocking I/O to achieve all this, of course. If you pth_select() in each thread you don't take advantage of the event scheduling inside Pth. pth_select() is for if 1 thread wants to poll many filedescriptors, but not if 1 thread polls for 1 filedescriptor. Then you just use pth_read(). And the timeout you achieve by using pth_read_ev() instead of passing it a timeout event. Same for the wrappers pth_readline() and pth_readline_ev(). > Is there a more efficient approach than this? And should I put a sleep in > that loop, or will the scheduler automatically handle everything? (I'll > have about 150 threads in this loop simultaneously, each reading from its > own socket, with each socket delivering about 1 line of input per second.) You don't need an explicit sleep there, because Pth's event manager will automatically suspend your thread and schedule others if an I/O operation would block. But keep in mind that this is only true if you use pth_xxx() functions. If you use read(2), sleep(3), etc. directly, Pth has to chance to perform context switches between the threads. You have to give Pth a chance to do this by always going through the Pth API. That's the price for true portability and non-preemtive scheduling. But usually that's just a matter of programming discipline... ;-) Ralf S. Engelschall [EMAIL PROTECTED] www.engelschall.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
Re: Line-oriented blocking input from sockets?
On Sun, Jul 13, 2003, Damon Hastings wrote: > [...] > So it copies the old stack out and the new stack in during every context > switch? I don't know much about thread implementation, but I guess I > thought you could just swap out the stack pointer instead of copying the > whole stack. > [...] Sure, Pth just swaps the stack pointer, of course. Nevertheless what here was mentioned is the fact that each stack consumes memory. If you have a large number of threads in your system, just the allocated stacks already accumulate to a rather large memory consumption. > It's good that you guys tell me these things during the > planning stage -- I guess that's an argument for using heap allocation > instead of stack allocation, eh? In Pth only the (original) stack of the main thread is auto-growing (done by the OS), while the other stacks are fixed size stacks. If you don't have very high recursion levels or other functions uses large buffers on the stack, this is no problem. But if you require really lots of stack space, you should be careful or at least spawn the Pth threads with a larger stack size. Ralf S. Engelschall [EMAIL PROTECTED] www.engelschall.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]
RE: Line-oriented blocking input from sockets?
--- David Schwartz <[EMAIL PROTECTED]> wrote: > > > If the context-switching overhead turns out to be too high, then I will > do > > exactly that. But it will mean maintaining state for each connection, > and > > that state will only grow more complex with future enhancements by > myself > > and others. > > Umm, huh?! If you don't maintain state for each connection, how will you > know what to do with the data you get? Ah, well, I meant that a state machine must store state explicitly, whereas with threaded code the state is implied in the code flow (in effect, the thread system itself is a state machine.) If each thread executes a simple function like "void foo() {A; B; C;}", then the equivalent state machine is simple enough -- it just has to remember whether each "thread" is at step A, B, or C, using an array of state variables or some such. But now throw in a few nested for's, if's, and local data into the above function... well, you get the picture. I could certainly implement my program as a state machine, but that may make my code harder for others to understand/maintain. __ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.com __ GNU Portable Threads (Pth)http://www.gnu.org/software/pth/ Development Site http://www.ossp.org/pkg/lib/pth/ Distribution Files ftp://ftp.gnu.org/gnu/pth/ Distribution Snapshots ftp://ftp.ossp.org/pkg/lib/pth/ User Support Mailing List[EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]