"James M. Cape" <jcape@xxxxxxxxxxxxxx> writes: > For the exact case of GObject::notify, you can use the GParamSpec* > argument in the signal prototype to get that info... I *think* most > other detailed signals somehow or other include the detail as an > argument somewhere. Hi James, Thanks for the reply, which makes sense, and thanks for the wonderful GNetwork Library. :-) It's funny, the reason I asked this was actually because I was fooling around with GNetwork. I was considering adding a detail to the "received" signal, and then I got curious as to how you usually find out what the detail was. Though I haven't got any particularly clear ideas yet, I might as well tell you about what I'm trying to do now that I have the chance. First, the use case: I'm building a thin wrapper called Messenger around GNetworkConnection to send and receive messages using a very simple message protocol in which each message looks like this (where selector is a string and body is an opaque blob): [message size][selector][0][body size][body] The reason I'm doing this is to have an easy way to implement an RPC-style thing. (Arguably this *is* an RPC-style, thing, but it doesn't serialize and unserialize data, etc.) The logic in Messenger's signal handler for "received" looks like this: * If we got a complete message, and didn't have any internal buffers, emit a "message-receieved" signal, with the selector as detail, and parameters being the body and the body's size (and, according to your reply, also the selector). * If we didn't get a complete message, and didn't have any internal buffers, create internal buffers large enough to hold the fields that we *did* get (some part of), and copy the data there. * If we already had some internal buffers, remember where we left off and continue filling buffers, creating new ones as needed. If we got enough data to complete the message, emit a "message-received" signal. Now, I realize that efficiency is not your primary concern with this library, nor in fact is it mine with what I'm doing. But it seemed to me that by pulling some of this bookkeping out of my signal handler and up into the GNetwork Library, we could both make the GNetwork Library significantly easier to use for similar applications (i.e., applications that want to read X bytes of data), *and* increase the performance of said applications. In addition, I believe we could still retain most of the beautiful simplicity of the GNetwork API. As I see it, the essential problem is that there is no way to control how much data a GNetworkConnection reads before it emits a "received" signal. I've thought about two ways to fix this, one quite serious and one not quite so serious, but of course there might be other even better ones I haven't thought about. The buffer size solution (quite serious) ======================================== This solution requires two changes to the GNetworkConnection API: * Introduce a boolean property "await-full-buffer" that tells the connection not to emit a signal until its incoming buffer is full. This is relatively unproblematic. In fact, I've implemented it and as far as I can tell it preserves both source and binary compatibility. I haven't got around to testing it though, as the tests in libgnetwork/tests/ seem pretty outdated. (They provoke numerous assertion failures and segfaults on the current CVS head.) * Make it possible to change the "buffer-size" property on-the-fly. (Although this should probably never deallocate memory -- analogously to how GString works.) We obviously need to make sure this works in a deterministic fashion, and I was a little unsure of how to do this with all the signal emitting and stuff going on. If someone changes the buffer size while the buffer is being filled in, an error should probably be produced. However, I'm not sure whether there are any other problematic cases. Perhaps you can find the time to help me? :-) With this in place, the logic in Messenger's signal handler could be reduced to the following: * If the state is READ_MESSAGE, emit a "message-received" signal and set the connection's "buffer-size" property to 4 (the width of the message size field). * Otherwise, the state is READ_MESSAGE_SIZE, so set the connection's "buffer-size" property to the number we just receieved. No more buffers or copying data! The explicit receive solution (not quite so serious) ==================================================== I noted that when using "await-full-buffer", Messenger's signal handler had become reduced to a simple state machine. What if this bookkeping, too, could be pulled into GNetwork? I realized that it probably shouldn't, but I wanted to know what it might look like. The idea of this solution is to introduce a receive method, reminiscent of the COME FROM command featured in INTERCAL. We'll need to add a boolean property too, "explicit-receives", that can be set upon creation to turn on this behvaior. The receive method takes two parameters, a byte count and a tag, and adds that pair to what I call the ``receieve queue''. If the queue was previously empty, the method makes sure the incoming buffer is large enough to hold the specified number of byte, and sets the connection to start listening to the network. When in "explicit-receives" mode, the connection appends any data it gets from the network to the incoming buffer. When the buffer is full, it emits a "received" signal with the detail set to the tag that's first in the queue. (Also, according to your reply, we'd need to add a parameter to the receieved signal to hold the tag.) It then dequeues the first item, and if that empties the queue, it might stop listening to the network. The logic in Messenger's signal handler now looks like this: * If we got a message size, receieve a message with this size. * Otherwise, we got a message, so emit a "message-receieved" signal and receieve another message size. Apologies for the long message (no pun intended); I didn't realize I had so much to say. Anyway, I'd love to hear what you (and others) think about this. I'm attaching a patch against the current CVS head that implements "await-full-buffer". Oh, a few more things, before I forget. * I'm using Automake 1.8, so I had to create a symlink called `automake-1.7' to bootstrap. Not sure how to best fix this. * My editor usually only fits 80 columns of code, so it's a little annoying that the GNetwork sources uses up to 100 columns. In some cases (like GType macros), the code isn't any more unreadable when wrapped at an arbitrary column, so it's not really worth it to fit them in 80 columns -- especially since that kind of code often isn't really meant to be read by humans anyway. However, in most cases the source could easily fit 80 columns without trouble; it's just a matter of breaking the lines. I would be glad to go through all of the source files and change this. I wouldn't do it unless you agreed to apply the patch, though, since I don't want to maintain my own personal branch that changes every third line in the entire source tree using a line-based diff. :-) * The pattern `foo->_priv->baz' occurs extremely often, and `foo' is usually about 10 characters long. Since it's very unlikely for `foo->_priv->baz' and `bar->_priv->baz' to occur in the same function, I like to define a variable FooPrivate *priv = foo->_priv; at the top of functions that uses `foo->_priv' a lot. In fact, the attached patch does this to a few functions that I had to modify anyway. Again, I'd be happy to go through all source files and perform this change where it makes sense if you agree. (It's confusing to use this idiom in some large functions but not other large functions.) * Tab characters are used instead of eight spaces, except in the following cases: - In the /* **** ... Public API ... **** */-style headers. - In some source code in documentation comments. - In the marshal.{c,h} files (which of course are generated). - Around ten random places where you obviously meant to use tabs. Tabs are fine with me (although I personally never use them), but in my opinion there should either be no tabs, or no eight-consecutive-spaces, so that you can use your editor's tabify and untabify commands to make sure you didn't mess up some file. What's your opinion on this one? * Is there a mailing list or other public forum that's used for GNetwork discussion -- other than this one? Again, thanks heaps for the awesome library. Best regards, -- Daniel Brockman drlion@xxxxxxxxxxxx _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list