Web lists-archives.com

Re: [GLIB] Async calls to Sync calls with g_main_context_iteration






On 27 August 2015 at 17:33, Frederik Lotter <frederik.lotter@xxxxxxxxx> wrote:
On 26 August 2015 at 12:13, Frederik Lotter <frederik.lotter@xxxxxxxxx> wrote:
Hi,

I am very new to GLIB so please excuse me if I made any stupid assumptions...

I did a lot of reading and testing my understanding but I feel a bit stuck. I feel like I am missing something obvious, or trying to use GLIB in the wrong way.

I am using GLIB in my applications (consisting of 3 separate processes) originally because I need DBUS access to Ofono and Connman (and between each other to implement shared variables) on our embedded Linux environment. 

(1) The first issue came when I realised that making synchronous DBUS calls between processes can result in a deadlock when two processes make DBUS requests to each other each waiting for the synchronous call to complete, which is preventing the GLIB event loop from servicing the DBUS request. 

   generated_com_mixtelematics_parameters_call_get_parameter_sync(..)

   =>

   generated_com_mixtelematics_parameters_call_get_parameter(..)

I changed all the DBUS calls to use the asynchronous calls. 

(2) The second issue came when I realized our application framework requires synchronous calls mapping to the underlying asynchronous GLIB requests, so I implemented wrapper functions which waits on an async_queue_pop() to wait for the result, before returning to the caller.

   // Async
   generated_com_mixtelematics_parameters_call_get_parameter(..)
   
   g_async_queue_pop(callbackParameters.semaphore);

However, this introduced another issue. If this synchronous wrapper is called from the GLIB main context thread, it would deadlock. The blocking call to pop() would not release the event loop to service the async DBUS call.

(3) This is where I am getting stuck chasing my own tail ... 

The problem is I would like the API call to be possible _from_ the GLIB event thread, but also _outside_ from another thread. The case in (2) only works from outside threads. 

So I added this (please do not shoot me):

   while(g_async_queue_try_pop(context.semaphore) == NULL)
   {
      g_main_context_iteration(NULL,TRUE/FALSE);
   }

(A) It seems like this call can not work from outside the GLIB event thread.

(B) If I call it work TRUE=blocking, it gets stuck in an outside thread

(C) If I call it with FALSE=non blocking, it spins

So it looks like I am going down the wrong path here. In the event thread it would work, and in an outside thread I need to use (2).

Any hints would me very much appreciated.

Kind Regards,
Frederik Lotter

MiX Telematics
South Africa


I think I am now heading in a better direction, but would be very grateful if someone could give me a hint.

I am working with:

g_main_context_push_thread_default() and g_main_context_pop_thread_default().

The main aim for me is to have the ability to make an ASYNC call, which is currently being called inside thread-default context X, have it's callback handled in thread-default context Y.

Example:

(A) DBUS incoming calls (server thread) handled in thread-default context X (TID=0x01)
(B) DBUS incoming call makes ASYNC call (DBUS outgoing call), with callback handled in thread-default context Y (TID=0x02)

In order to have ASYNC calls made from TID=0x01 direct their callbacks to TID=0x02, the thread-default context must be set in TID=0x01

The issue:

(1) For incoming calls I can register the source on a default context before starting the main loop g_main_loop_run(). This works.

(2) However, for ASYNC calls that happens during the lifetime of the g_main_loop_run() used in (A) above, it seems g_main_context_push_thread_default() and g_main_context_pop_thread_default() around the main loop in (A) keeps the context locked and prevents dispatching from the second loop running in TID=0x02.

      g_main_context_push_thread_default(Y);
      
      g_main_loop_run(X);

      g_main_context_pop_thread_default(Y);

Only after the pop is made will the other thread process the events which got added during the lifetime of the main loop above.

(3) If the push and pop is made around the ASYNC function call:

      g_main_context_push_thread_default(Y);

      g_dbus_connection_call(...) //  ASYNC with callback

      g_main_context_pop_thread_default(Y);

The push fails to acquire the context because the main loop running context (Y) is already in action and locking the context.

So I think my question is: How can I, at runtime, direct an ASYNC callback to a custom context (Y) when the ASYNC call is made inside code that was invoked by the GLIB main loop in the first place (from another context X).

Kind Regards,
Frederik Lotter


I have formulated my question differently with a working example on stackoverflow:

_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
https://mail.gnome.org/mailman/listinfo/gtk-list