Changes between Initial Version and Version 1 of Group_Lock


Ignore:
Timestamp:
Feb 13, 2013 7:22:38 AM (11 years ago)
Author:
bennylp
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Group_Lock

    v1 v1  
     1{{{ 
     2#!html 
     3<!-- MAIN TABLE START --> 
     4<table border=0 width="90%" align="center"><tr><td> 
     5}}} 
     6 
     7= Group Lock = 
     8 
     9'''Table of Contents''' 
     10[[PageOutline(2-3,,inline)]] 
     11 
     12Group Lock ({{{pj_grp_lock_t}}}) is a new synchronization object in PJLIB for deadlock avoidance and session management. 
     13 
     14[[BR]] 
     15 
     16== Introduction == 
     17 
     18 
     19Group lock is a synchronization object to manage concurrency among members within the same logical group. Example of such groups are: 
     20 
     21    - dialog, which has members such as the dialog itself, an invite session, and several transactions 
     22    - ICE, which has members such as ICE stream transport, ICE session, STUN socket, TURN socket, and down to ioqueue key 
     23 
     24 
     25Group lock has three functions: 
     26 
     27    - mutual exclusion: to protect resources from being accessed by more than one threads at the same time 
     28    - session management: to make sure that the resource is not destroyed while others are still using or about to use it. 
     29    - lock coordinator: to provide uniform lock ordering among more than one lock objects, which is necessary to avoid deadlock. 
     30 
     31 
     32The requirements of the group lock are: 
     33 
     34    - must satisfy all the functions above 
     35    - must allow members to join or leave the group (for example, transaction may be added or removed from a dialog) 
     36    - must be able to synchronize with external lock (for example, a dialog lock must be able to sync itself with PJSUA lock) 
     37 
     38 
     39== Usage ==  
     40 
     41=== Creation === 
     42 
     43The group lock can be created either by the first member in the group or by the higher object that manages the members. Once created, the ownership of the group lock will be shared by the members, using a reference counter. The group lock will have its own pool. Also a group lock is a pj_lock_t object, hence lock API can be used. 
     44 
     45{{{ 
     46typedef struct pj_grp_lock_config  
     47{ 
     48   unsigned flags; 
     49}; 
     50 
     51PJ_DECL(pj_status_t) pj_grp_lock_create(pj_pool_t *pool, 
     52                                       const pj_grp_lock_config *cfg, 
     53                                       pj_grp_lock_t **p_grp_lock); 
     54}}} 
     55 
     56=== Lock and Unlock === 
     57 
     58The group lock is a lock that can be used as mutex. You can use lock API {{{pj_lock_acquire()}}}, {{{pj_lock_tryacquire()}}}, and {{{pj_lock_release()}}}, or the group lock's own API {{{pj_grp_lock_acquire()}}}, {{{pj_grp_lock_tryacquire()}}}, and {{{pj_grp_lock_release()}}}. Locking the group lock temporarily increases the reference counter to prevent it from being destroyed. The side effect is, the {{{pj_grp_lock_release()}}} may cause the group to be destroyed, if it is the last one that holds the reference counter. In that case, it returns PJ_EGONE. 
     59 
     60=== Destroy === 
     61 
     62The group lock lifetime is governed by an internal reference counter (see [#session Session Management] below). It will be destroyed once the reference counter reaches zero. 
     63 
     64Since group lock is a lock object, it can be destroyed with {{{pj_lock_destroy()}}} API. This will forcefully destroy the group lock without adhering to the reference counter, thus should be avoided. 
     65 
     66=== Registering Member to The Group Lock === 
     67 
     68The purpose of registering a member to the group lock is to prevent that member from being destroyed prematurely, when other threads are referencing the member. To achieve that, the member registers a callback to be called by the group lock to destroy itself when the reference counter of the group reaches zero. In other words, once registered, a member must not allow itself to be destroyed unless the request comes from the group lock's destroy callback. 
     69 
     70The API to register a member: 
     71 
     72{{{ 
     73PJ_DECL(pj_status_t) pj_grp_lock_add_handler(pj_grp_lock_t *grp_lock, 
     74                                             pj_pool_t *pool, 
     75                                             void *member, 
     76                                             void (*destroy)(void *member)); 
     77}}} 
     78 
     79Sometimes a member needs to die early (for example, transactions may come and go in a dialog). A member may unregister the handler using this API: 
     80 
     81{{{ 
     82PJ_DECL(pj_status_t) pj_grp_lock_del_handler(pj_grp_lock_t *grp_lock, 
     83                                             void *member, 
     84                                             void (*destroy)(void *member)); 
     85}}} 
     86 
     87=== Session Management === #session 
     88 
     89This API manages the reference counter of the group: 
     90 
     91{{{ 
     92PJ_DECL(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *grp_lock); 
     93PJ_DECL(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *grp_lock); 
     94}}} 
     95 
     96The {{{pj_grp_lock_dec_ref()}}} returns PJ_EGONE when that operation causes the group lock to be destroyed (because the reference counter reaches zero). 
     97 
     98 
     99=== Synchronization with External Locks === 
     100 
     101Often it is necessary to synchronize the group lock with an external lock. By external, it means a lock owned by object outside the group, and it’s not possible to to add that object to the group. The PJSUA lock and ioqueue locks are examples of such locks. Synchronizing these locks will guarantee the lock ordering of the locks hence deadlock will be avoided. 
     102 
     103Use the API below to synchronize an external lock with the group lock: 
     104 
     105{{{ 
     106PJ_DECL(pj_status_t) pj_grp_lock_chain_lock(pj_grp_lock_t *grp_lock, 
     107                                            pj_lock_t *external_lock, 
     108                                            int pos); 
     109}}} 
     110 
     111The ''pos'' argument specifies the lock order and also the relative position with regard to lock ordering against the group lock. Lock with lower ''pos'' value will be locked first, and those with negative value will be locked before the group lock (the group lock's ''pos'' value is zero). 
     112 
     113This is the API to unregister external lock: 
     114 
     115{{{ 
     116PJ_DECL(pj_status_t) pj_grp_lock_unchain_lock(pj_grp_lock_t *grp_lock, 
     117                                              pj_lock_t *external_lock); 
     118}}} 
     119 
     120 
     121=== Lock Replace === 
     122 
     123This API is used to move things from the old lock to the new lock and close the old lock. It is especially useful  
     124 
     125{{{ 
     126PJ_DECL(pj_status_t) pj_grp_lock_replace(pj_grp_lock_t *old_lock, 
     127                                         pj_grp_lock_t *new_lock); 
     128}}} 
     129 
     130 
     131{{{ 
     132#!html 
     133<!-- MAIN TABLE END --> 
     134</td></tr></table> 
     135}}} 
     136