Re: Async communication



Daniel Nilsson wrote:

Hi,

I'm working on a program in GTK+ that has a need to communicate with a
slow device (a power supply connected to a serial port). While this
might not be so difficult to achieve what complicates matters is that
the main program consists of two state machines that each needs to be
able to read and write over the serial port. These state machines are
kicked once every 500mS in the gtk_main loop by using
g_timeout_add, as far as I can tell that means that the two
statemachines will never be executed at the same time. Seems like
gtk_main runs all functions added by g_timeout_add sequentially.
Controls on the UI are also require action in the
statemachines to happen so I can't block inside the statemachine code
waiting for input from the serial port (this would make the UI
non-responsive for up to 2 seconds or so which is the time it takes to
get an answer over the serial port). Hence I need to have the serial
communication happen in the background (separate thread). The serial
communication basically consists of; send a command, wait in a select
for a response if the command suceeded or not and any data
associated. Since there are no IDs with these commands I can't just
have each statemachine send the commands directly, because then I
don't know what responce goes with which command when I go the read
off the serial port.

I've been trying to come up with what the best solution is here, and
it seems like the best I have come up with is still a complicated
solution. What I thought of was to have a third function that would
execute using timeout_add, this function would maintain a FIFO queue
of commands from the two statemachines to be sent to the serial
port. The function would then decide what command to send, prepare a
memory location for the response and then hand this over to actually
complete in a separate thread. The complicated portion of this is to
get the results (the data payload) back to the statemachine that sent
a measurement command to the power supply (for example, a voltage
measurement request). Since I can't block in the stateamachine code I
then somehow need to first send the command and then come back later
and check for a response. In addition, each measurement done over the
serial port also needs a timestamp which should be correct down to +/-
1s or so. Error handling also becomes interesting...

Any thoughts of a easier way to do this ? Could I use the glib
GIOChannel somehow or coud the glib Asynchronous Queues help in any
way ?

I'm not certain I understand all the details of how your application has to work; but i'm willing to take a shot at how I might approach a similar problem. Basically, you have a task that needs to be accomplished and you want to display in a graphical window the progress of that task. You may also, want to send commands to the task triggered by a user. I would break this up into two seperate threads one for the GUI and one for the task. In the GUI thread I would have a function that is called every 100 ms or so and check if there is any payload in an async queue. This function might
look something like:

g_timeout_add( 100, (GSourceFunc)process_command, queue );

struct Payload{
   int msg_id;
   /// .. other important parts of the message.
};
gboolean
process_command(  GAsyncQueue *queue )
{
   Payload*msg = (GMsg*)g_async_queue_try_pop( queue );
   if( msg ){
      switch( msg->msg_id ){
      // process each message
      }
   }
   return TRUE; // keep the timeout going
}

So, I can use a similar loop in both the GUI thread and the Task thread if I need two way communication.

Hope this helps,
todd




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