GIO context object (was: GVfs status report)



Alexander Larsson wrote:
On Thu, 2007-09-13 at 11:02 +0200, nf2 wrote:
Alexander Larsson wrote:
and what about the gvfs dbus connections? they also need a session object to live in. even for sync io in a separate thread: can you use the same dbus connections like in the main thread?
What about it? It works fine. With the current system there is a single
one for async i/o, and per-thread ones for sync i/o. One could add
per-thread ones for async i/o (it had that once, but I removed it).
i see. so you have a per-thread pool of dbus connections?

One connection per thread per mountpoint for sync ops. No need for
multiple ones since there can be at most one message outstanding.
I don't agree. I think nobody would use this, and there will be more
than one horribly complicated bug caused by it. Can you come up with an
sane example usecase where you want to do async i/o in a worker thread?
i think there are situations where a second gmain context is useful:

using async operations which recurse the mainloop (pseudo blocking) in a thread - for instance for downloading a complete file like KIO::NetAccess. or using a library with async design (internally using gio) in a thread.

Well, in this case the library (gio) does have an sync design, so there
is no need to emulate a sync call using a mainloop.

The initial multi-context work in gio was done by passing a GMainContext
to all the async ops. This is bloating the API way to much for normal
use. However, it could be extended (at a later point even) with a way to
set the default i/o context on a per thread basis. (Or even for all uses
of the default context?)

I don't think its especially important though, and it certainly does
make implementations a lot harder. (For instance, the
multiple-async-dbus-connections code was a pain).

however - i guess for 90% of the use cases you are right. i just thought that a universal file io-library, which competes with open, opendir and stat should be quite low-level and not make decisions about the default context or the main thread (KIO and Gnome-VFS have been designed too high level - and that's IMHO their crucial mistake). i believe it's good that glib allows to have different gmain contexts and doesn't use global variables extensively. i would expect that a file-io interface which comes with glib is fitting into this model.

I belive the real number i far larger than 90%, more like very near to
100%.


Sure, but if the 1 or 2% eccentric use cases are for instance using GIO from Java etc it might still be worthwhile. In some cases you can't have Glib Main Loop in the main thread but you still want to use GIO's async operations like file/directory monitoring, mounting etc. You might want a second thread having its own GMainContext.

Of course passing different GmainContext objects to every async operation sounds like an overkill, but having a GIO context object to carry all global state, which is initialized with a GMainContext and a D-Bus Sessionbus connection might be an option:

GioContext * gio_context_new();  // default gmain/session bus connection
GioContext * gio_context_new_with_gmain(GmainContext * gmain_context, gpointer dbus_sessionbus_connection);

In case gmain_context is NULL and dbus_sessionbus_connection is NULL it will use the default context and default session bus connection. If gmain_context is != NULL and dbus_sessionbus_connection == NULL it will create a new private session bus connection.

The dbus_sessionbus_connection is casted to a gpointer, therefore the dbus headers don't have to be included.

To keep the API simple, every GFile instance could belong to a certain GioContext (carry a reference). Therefore GioContext is only needed when instantiating a new GFile object or when cloning it.

I just believe that GIO shouldn't be too GTK+ biased from design (in GTK+, there is always a main thread which iterates the default gmain).


Perhaps there should be a design pattern for writing async libraries which use GLib Main Loop and D-BUS in general. Or a kind of generic "bag" object, which carries a GMainContext, the session bus connection and connection/context objects of other async libraries which are watched by this gmain. This object could be passed from one library to the next. For instance when your application uses the async libraries A and B, where library B internally also uses library A.

GAsyncContext * g_async_context_new(GmainContext * gmain, GThread * thread_for_this_gmain);

g_async_context_attach(GAsyncContext * ctxt, char * lib_ctxt_name, gpointer lib_ctxt);

gpointer g_async_context_get(GAsyncContext * ctxt, char * lib_ctxt_name);

// where lib_ctxt_name = "dbus_session_bus_connection" or "gio_context" for instance

When initializing an async library, you would always pass the GAsyncContext object - therefore it can reuse existing sockets like the dbus session bus connection internally - or initialize new ones when none are present.

Just some thoughts,

regards,
Norbert



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