Correct connection sequence to maximize chances of e.g.: getting connected :)

Aleksander Morgado aleksander at aleksander.es
Thu Apr 30 14:24:14 UTC 2020


Hey Enrico,

>
> So - i was considering using a GList of my own structs to track down objects and maintain it when observing state transitions.
> Now I was wondering how to manage:
> - async operation concurrency: am I guaranteed only a single async operation runs? Or should I lock somehow the list?

If your program doesn't use multiple explicit threads, i.e. if you
just have a main loop in the main thread, you're totally safe and
there is absolutely no need to do any sync or locking to access that
list.

> - software shutdown:
>         - I will have to unref all my objects somehow
>         - mainloop exiting should be the last thing I do

If you want to provide a "clean program exit", then all your async
operations must be finished before you quit the mainloop, otherwise
the program would exit with pending async operations (which may be
fine anyway). If you have a list of structs and each struct holds
object references, what you need to do is cleanup each of the structs
(the list items) one by one, unref-ing whatever full references you
had stored there, and then free the list itself.

>
> but I should be sure all async operations are complete when I quit my program, and I know the answer: GCAncellable. :) :)

That is a way to do that, yes. If you want to do a clean exit like
you're describing, you could have a "program wide cancellable" that is
passed around to all async operations you execute, and once the
cancellable is cancelled, the async operations should (if they support
it) get cancelled all. But beware, cancelling the cancellabel doesn't
necessarily mean that all async operations are cancelled instantly;
and the cancellation process itself may need further main loop
iterations to complete!

> But at the moment it's not clear to me how I might use that to make sure that when the program quits, all async operations are cancelled, and no other are pending.

My question is, why do you really want to make sure all async
operations are finished when the program quits. Do you truly need
that? If you do need that, then once the program is told to quit, you
should launch the "program cancellation logic" which would cancel the
program-wide cancellable, and then wait until all async operations are
finished. You may for example keep a counter of the async operations
you're running concurrently, and once it reaches 0 (meaning all async
operations finished) then you would be able to cleanly stop the
mainloop at that point. Don't know, something like that.

> I did have a look at mmcli use of GCancellables, but it's not clear to me how I might use them when I only use, and not implement, async ops, amongst other things.

If the async operation doesn't support GCancellable, you cannot do
anything. If the async operation supports GCancellable, it is
(usually) guaranteed that the async operation will finish with a
G_IO_ERROR_CANCELLED error. But, there is no guarantee that cancelling
a cancellable will make the async operation actually get cancelled
earlier! Some operations allow that (e.g. a network scan) but some
others will just wait for the operation to finish normally but then
returning a cancelled error instead of whatever the result of the
async operation was.

-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list