Ignore:
Timestamp:
Feb 21, 2013 11:18:36 AM (11 years ago)
Author:
bennylp
Message:

Fixed #1616: Implementation of Group lock and other foundation in PJLIB for fixing synchronization issues

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/lock.h

    r3553 r4359  
    148148/** @} */ 
    149149 
     150 
     151/** 
     152 * @defgroup PJ_GRP_LOCK Group Lock 
     153 * @ingroup PJ_LOCK 
     154 * @{ 
     155 * 
     156 * Group lock is a synchronization object to manage concurrency among members 
     157 * within the same logical group. Example of such groups are: 
     158 * 
     159 *   - dialog, which has members such as the dialog itself, an invite session, 
     160 *     and several transactions 
     161 *   - ICE, which has members such as ICE stream transport, ICE session, STUN 
     162 *     socket, TURN socket, and down to ioqueue key 
     163 * 
     164 * Group lock has three functions: 
     165 * 
     166 *   - mutual exclusion: to protect resources from being accessed by more than 
     167 *     one threads at the same time 
     168 *   - session management: to make sure that the resource is not destroyed 
     169 *     while others are still using or about to use it. 
     170 *   - lock coordinator: to provide uniform lock ordering among more than one 
     171 *     lock objects, which is necessary to avoid deadlock. 
     172 * 
     173 * The requirements of the group lock are: 
     174 * 
     175 *    - must satisfy all the functions above 
     176 *    - must allow members to join or leave the group (for example, 
     177 *      transaction may be added or removed from a dialog) 
     178 *    - must be able to synchronize with external lock (for example, a dialog 
     179 *      lock must be able to sync itself with PJSUA lock) 
     180 * 
     181 * Please see https://trac.pjsip.org/repos/wiki/Group_Lock for more info. 
     182 */ 
     183 
     184/** 
     185 * Settings for creating the group lock. 
     186 */ 
     187typedef struct pj_grp_lock_config 
     188{ 
     189    /** 
     190     * Creation flags, currently must be zero. 
     191     */ 
     192    unsigned    flags; 
     193 
     194} pj_grp_lock_config; 
     195 
     196 
     197/** 
     198 * Initialize the config with the default values. 
     199 * 
     200 * @param cfg           The config to be initialized. 
     201 */ 
     202PJ_DECL(void) pj_grp_lock_config_default(pj_grp_lock_config *cfg); 
     203 
     204/** 
     205 * Create a group lock object. Initially the group lock will have reference 
     206 * counter of one. 
     207 * 
     208 * @param pool          The group lock only uses the pool parameter to get 
     209 *                      the pool factory, from which it will create its own 
     210 *                      pool. 
     211 * @param cfg           Optional configuration. 
     212 * @param p_grp_lock    Pointer to receive the newly created group lock. 
     213 * 
     214 * @return              PJ_SUCCESS or the appropriate error code. 
     215 */ 
     216PJ_DECL(pj_status_t) pj_grp_lock_create(pj_pool_t *pool, 
     217                                        const pj_grp_lock_config *cfg, 
     218                                        pj_grp_lock_t **p_grp_lock); 
     219 
     220/** 
     221 * Forcibly destroy the group lock, ignoring the reference counter value. 
     222 * 
     223 * @param grp_lock      The group lock. 
     224 * 
     225 * @return              PJ_SUCCESS or the appropriate error code. 
     226 */ 
     227PJ_DECL(pj_status_t) pj_grp_lock_destroy( pj_grp_lock_t *grp_lock); 
     228 
     229/** 
     230 * Move the contents of the old lock to the new lock and destroy the 
     231 * old lock. 
     232 * 
     233 * @param old_lock      The old group lock to be destroyed. 
     234 * @param new_lock      The new group lock. 
     235 * 
     236 * @return              PJ_SUCCESS or the appropriate error code. 
     237 */ 
     238PJ_DECL(pj_status_t) pj_grp_lock_replace(pj_grp_lock_t *old_lock, 
     239                                         pj_grp_lock_t *new_lock); 
     240 
     241/** 
     242 * Acquire lock on the specified group lock. 
     243 * 
     244 * @param grp_lock      The group lock. 
     245 * 
     246 * @return              PJ_SUCCESS or the appropriate error code. 
     247 */ 
     248PJ_DECL(pj_status_t) pj_grp_lock_acquire( pj_grp_lock_t *grp_lock); 
     249 
     250/** 
     251 * Acquire lock on the specified group lock if it is available, otherwise 
     252 * return immediately wihout waiting. 
     253 * 
     254 * @param grp_lock      The group lock. 
     255 * 
     256 * @return              PJ_SUCCESS or the appropriate error code. 
     257 */ 
     258PJ_DECL(pj_status_t) pj_grp_lock_tryacquire( pj_grp_lock_t *grp_lock); 
     259 
     260/** 
     261 * Release the previously held lock. This may cause the group lock 
     262 * to be destroyed if it is the last one to hold the reference counter. 
     263 * In that case, the function will return PJ_EGONE. 
     264 * 
     265 * @param grp_lock      The group lock. 
     266 * 
     267 * @return              PJ_SUCCESS or the appropriate error code. 
     268 */ 
     269PJ_DECL(pj_status_t) pj_grp_lock_release( pj_grp_lock_t *grp_lock); 
     270 
     271/** 
     272 * Add a destructor handler, to be called by the group lock when it is 
     273 * about to be destroyed. 
     274 * 
     275 * @param grp_lock      The group lock. 
     276 * @param pool          Pool to allocate memory for the handler. 
     277 * @param member        A pointer to be passed to the handler. 
     278 * @param handler       The destroy handler. 
     279 * 
     280 * @return              PJ_SUCCESS or the appropriate error code. 
     281 */ 
     282PJ_DECL(pj_status_t) pj_grp_lock_add_handler(pj_grp_lock_t *grp_lock, 
     283                                             pj_pool_t *pool, 
     284                                             void *member, 
     285                                             void (*handler)(void *member)); 
     286 
     287/** 
     288 * Remove previously registered handler. All parameters must be the same 
     289 * as when the handler was added. 
     290 * 
     291 * @param grp_lock      The group lock. 
     292 * @param member        A pointer to be passed to the handler. 
     293 * @param handler       The destroy handler. 
     294 * 
     295 * @return              PJ_SUCCESS or the appropriate error code. 
     296 */ 
     297PJ_DECL(pj_status_t) pj_grp_lock_del_handler(pj_grp_lock_t *grp_lock, 
     298                                             void *member, 
     299                                             void (*handler)(void *member)); 
     300 
     301/** 
     302 * Increment reference counter to prevent the group lock grom being destroyed. 
     303 * 
     304 * @param grp_lock      The group lock. 
     305 * 
     306 * @return              PJ_SUCCESS or the appropriate error code. 
     307 */ 
     308#if !PJ_GRP_LOCK_DEBUG 
     309PJ_DECL(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *grp_lock); 
     310 
     311#define pj_grp_lock_add_ref_dbg(grp_lock, x, y) pj_grp_lock_add_ref(grp_lock) 
     312 
     313#else 
     314 
     315#define pj_grp_lock_add_ref(g)  pj_grp_lock_add_ref_dbg(g, __FILE__, __LINE__) 
     316 
     317PJ_DECL(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *grp_lock, 
     318                                             const char *file, 
     319                                             int line); 
     320#endif 
     321 
     322/** 
     323 * Decrement the reference counter. When the counter value reaches zero, the 
     324 * group lock will be destroyed and all destructor handlers will be called. 
     325 * 
     326 * @param grp_lock      The group lock. 
     327 * 
     328 * @return              PJ_SUCCESS or the appropriate error code. 
     329 */ 
     330#if !PJ_GRP_LOCK_DEBUG 
     331PJ_DECL(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *grp_lock); 
     332 
     333#define pj_grp_lock_dec_ref_dbg(grp_lock, x, y) pj_grp_lock_dec_ref(grp_lock) 
     334#else 
     335 
     336#define pj_grp_lock_dec_ref(g)  pj_grp_lock_dec_ref_dbg(g, __FILE__, __LINE__) 
     337 
     338PJ_DECL(pj_status_t) pj_grp_lock_dec_ref_dbg(pj_grp_lock_t *grp_lock, 
     339                                             const char *file, 
     340                                             int line); 
     341 
     342#endif 
     343 
     344/** 
     345 * Get current reference count value. This normally is only used for 
     346 * debugging purpose. 
     347 * 
     348 * @param grp_lock      The group lock. 
     349 * 
     350 * @return              The reference count value. 
     351 */ 
     352PJ_DECL(int) pj_grp_lock_get_ref(pj_grp_lock_t *grp_lock); 
     353 
     354 
     355/** 
     356 * Dump group lock info for debugging purpose. If group lock debugging is 
     357 * enabled (via PJ_GRP_LOCK_DEBUG) macro, this will print the group lock 
     358 * reference counter value along with the source file and line. If 
     359 * debugging is disabled, this will only print the reference counter. 
     360 * 
     361 * @param grp_lock      The group lock. 
     362 */ 
     363PJ_DECL(void) pj_grp_lock_dump(pj_grp_lock_t *grp_lock); 
     364 
     365 
     366/** 
     367 * Synchronize an external lock with the group lock, by adding it to the 
     368 * list of locks to be acquired by the group lock when the group lock is 
     369 * acquired. 
     370 * 
     371 * The ''pos'' argument specifies the lock order and also the relative 
     372 * position with regard to lock ordering against the group lock. Locks with 
     373 * lower ''pos'' value will be locked first, and those with negative value 
     374 * will be locked before the group lock (the group lock's ''pos'' value is 
     375 * zero). 
     376 * 
     377 * @param grp_lock      The group lock. 
     378 * @param ext_lock      The external lock 
     379 * @param pos           The position. 
     380 * 
     381 * @return              PJ_SUCCESS or the appropriate error code. 
     382 */ 
     383PJ_DECL(pj_status_t) pj_grp_lock_chain_lock(pj_grp_lock_t *grp_lock, 
     384                                            pj_lock_t *ext_lock, 
     385                                            int pos); 
     386 
     387/** 
     388 * Remove an external lock from group lock's list of synchronized locks. 
     389 * 
     390 * @param grp_lock      The group lock. 
     391 * @param ext_lock      The external lock 
     392 * 
     393 * @return              PJ_SUCCESS or the appropriate error code. 
     394 */ 
     395PJ_DECL(pj_status_t) pj_grp_lock_unchain_lock(pj_grp_lock_t *grp_lock, 
     396                                              pj_lock_t *ext_lock); 
     397 
     398 
     399/** @} */ 
     400 
     401 
    150402PJ_END_DECL 
    151403 
Note: See TracChangeset for help on using the changeset viewer.