Re: Still confused on new thread starting idle functions to update UI.





On Thu, Dec 5, 2013 at 2:00 AM, David Buchan <pdbuchan yahoo com> wrote:

Things I've learned yesterday are:

1. strdup() (I've never seen or used it before)
2. what the heck heap and stack mean (still more to learn there)
3. a more general and flexible solution is probably to use asynchronous message queuing

"Heap" and "stack" are technically terms for particular data
structures, but "the heap" and "the stack" generally refer to two
particular memory stores: one that's global and from which memory can
be (de)allocated arbitrarily, and one that's a strict queue and
deallocates everything as things unwind. The stack is used for local
variables (including function parameters) and function return values.
The heap is used only by functions like malloc/free and their
equivalents (including the C++ new/delete operators, though not alloca
if you have it). There are other places stuff can be stuffed, like the
static data segment for globals, and CPU registers, and such, but in
terms of allocating strings like this, your options are limited there.
I'll come back to the data segment later though.

Everything allocated on the stack disappears when the current function
returns. You can pass pointers around, but they'll be dangling (and
very dangerous) once the function returns, so this is not thread-safe.
Something allocated on the heap, on the other hand, stays around until
it's explicitly freed. That means you have to put extra work into
managing allocations and deallocations, but you can pass data around
between threads this way. The rule is: Every successful allocation
must be matched by exactly one deallocation. Anything else will give
you either memory leaks or a corrupted heap, both of which are
comparable to aiming a shotgun at your foot and pulling the trigger.

As a general rule, you'll want to put temporary/working storage on the
stack, and use the heap only when you need something to outlive the
current function. That way, you minimize allocations/deallocations,
which have run-time cost and (more importantly) need to be kept track
of. Use the easy way unless you need the harder way.

If you could manage the idle message with just a pointer to the
string, that would be a lot easier. Does the message need to specify
which of multiple textviews should be used, or is the info always
going to go into the same one? If the latter, you can simply record
that pointer in a global variable, which is stored in the data
segment. That pointer is a fixed size, and it wants to outlive the
function that puts it there (probably your initialization function),
so the data segment (globals) is a good place for it. Something like
this:



static GtkWidget *textview;

/****** thread *****/
void thread(int socket)
{
    while (1)
    {
        char message[256];
        size_t len=recv(socket,message,sizeof message-1,0);
        message[len]=0;
        g_idle_add((GSourceFunc)message_idle, strdup(message));
    }
}

/****** idle handler, cribbed from your post earlier *****/
gboolean message_idle(char *message)
{
  GtkTextBuffer *textbuffer;
  GtkTextIter end;

  textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
  gtk_text_buffer_get_end_iter (textbuffer, &end);
  gtk_text_buffer_insert (textbuffer, &end, message, -1);
  free(message);
}

/***** initialization *****/
int main()
{
    /* ... */
    textview = gtk_text_view_new();
    /* start the thread etc */
}



The textview doesn't actually matter to the worker thread - messages
do. It shouldn't need to pass the textview to the idle handler. I've
done this example as a very VERY simple socket handler; in a separate
post I'll knock together a working example in Pike, to show how much
easier this is in a high level language with asynchronous handlers.
You can do similar things in Python, too, though for good async
support in Python you might want to wait for version 3.4, which is now
on its way (beta 1 released last week, estimated final release in
February).

ChrisA

_______________________________________________

Hi Chris,

Thanks for writing this. Definitely a keeper.

Making the pointer to textview global would indeed simplify things enormously. I guess I avoid global 
variables like the plague, having been told to for years. Also wanted to make the idle function generic.

Thanks again,
Dave

PS. Socket programming is great fun! ( http://pdbuchan.com/rawsock/rawsock.html )


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]