blob: 65de868e863ac33d5c6a6543230babdde6f0419c [file] [log] [blame]
/* $Id$ */
/*
* Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/lock.h>
#include <pj/os.h>
#include <pj/assert.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/errno.h>
typedef void LOCK_OBJ;
/*
* Lock structure.
*/
struct pj_lock_t
{
LOCK_OBJ *lock_object;
pj_status_t (*acquire) (LOCK_OBJ*);
pj_status_t (*tryacquire) (LOCK_OBJ*);
pj_status_t (*release) (LOCK_OBJ*);
pj_status_t (*destroy) (LOCK_OBJ*);
};
typedef pj_status_t (*FPTR)(LOCK_OBJ*);
/******************************************************************************
* Implementation of lock object with mutex.
*/
static pj_lock_t mutex_lock_template =
{
NULL,
(FPTR) &pj_mutex_lock,
(FPTR) &pj_mutex_trylock,
(FPTR) &pj_mutex_unlock,
(FPTR) &pj_mutex_destroy
};
static pj_status_t create_mutex_lock( pj_pool_t *pool,
const char *name,
int type,
pj_lock_t **lock )
{
pj_lock_t *p_lock;
pj_status_t rc;
PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
if (!p_lock)
return PJ_ENOMEM;
pj_memcpy(p_lock, &mutex_lock_template, sizeof(pj_lock_t));
rc = pj_mutex_create(pool, name, type, (pj_mutex_t**)&p_lock->lock_object);
if (rc != PJ_SUCCESS)
return rc;
*lock = p_lock;
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pj_lock_create_simple_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock )
{
return create_mutex_lock(pool, name, PJ_MUTEX_SIMPLE, lock);
}
PJ_DEF(pj_status_t) pj_lock_create_recursive_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock )
{
return create_mutex_lock(pool, name, PJ_MUTEX_RECURSE, lock);
}
/******************************************************************************
* Implementation of NULL lock object.
*/
static pj_status_t null_op(void *arg)
{
PJ_UNUSED_ARG(arg);
return PJ_SUCCESS;
}
static pj_lock_t null_lock_template =
{
NULL,
&null_op,
&null_op,
&null_op,
&null_op
};
PJ_DEF(pj_status_t) pj_lock_create_null_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock )
{
PJ_UNUSED_ARG(name);
PJ_UNUSED_ARG(pool);
PJ_ASSERT_RETURN(lock, PJ_EINVAL);
*lock = &null_lock_template;
return PJ_SUCCESS;
}
/******************************************************************************
* Implementation of semaphore lock object.
*/
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
static pj_lock_t sem_lock_template =
{
NULL,
(FPTR) &pj_sem_wait,
(FPTR) &pj_sem_trywait,
(FPTR) &pj_sem_post,
(FPTR) &pj_sem_destroy
};
PJ_DEF(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,
const char *name,
unsigned initial,
unsigned max,
pj_lock_t **lock )
{
pj_lock_t *p_lock;
pj_status_t rc;
PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
if (!p_lock)
return PJ_ENOMEM;
pj_memcpy(p_lock, &sem_lock_template, sizeof(pj_lock_t));
rc = pj_sem_create( pool, name, initial, max,
(pj_sem_t**)&p_lock->lock_object);
if (rc != PJ_SUCCESS)
return rc;
*lock = p_lock;
return PJ_SUCCESS;
}
#endif /* PJ_HAS_SEMAPHORE */
PJ_DEF(pj_status_t) pj_lock_acquire( pj_lock_t *lock )
{
PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
return (*lock->acquire)(lock->lock_object);
}
PJ_DEF(pj_status_t) pj_lock_tryacquire( pj_lock_t *lock )
{
PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
return (*lock->tryacquire)(lock->lock_object);
}
PJ_DEF(pj_status_t) pj_lock_release( pj_lock_t *lock )
{
PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
return (*lock->release)(lock->lock_object);
}
PJ_DEF(pj_status_t) pj_lock_destroy( pj_lock_t *lock )
{
PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
return (*lock->destroy)(lock->lock_object);
}