Margo instance lifetime

In the previous sections, we have used margo_init (or one of its variant) to initialize a Margo instance, and margo_finalize to destroy it. When doing so, we have to understand that the actual destruction of the Margo instance may not happen in margo_finalize itself: if margo_finalize is called from an RPC, or if another ULT is blocked on margo_wait_for_finalize, then the Margo instance will be destroyed respectively after the RPC, and in margo_wait_for_finalize.

This lifetime management may not be suitable when wrapping Margo code in a higher-level language that uses destructors or garbage collection. Even in C, it may be useful to ensure that the Margo instance remains valid after its finalization, for instance to be able to cleanup Argobots or Mercury objects (e.g. ABT_mutex or hg_addr_t) after the Mercury progress loop has been stopped.

To help with such lifetime management, Margo instances have an internal reference count. This reference count is initialize at 1 when the instance is created. It is decreased by 1 when the instance is finalized, and the instance is destroyed when the reference count goes to 0.

This reference count can be increased and decreased by the user by calling margo_instance_ref_incr and margo_instance_release, respectively. If the program calls margo_finalize on an instance with a reference count greater than 1, the progress loop will be stopped, making the instance unable to send and receive RPCs, but the instance itself won’t be destroyed until margo_instance_release has been called as many times as needed to make the reference count go to 0.