⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ema.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 4 页
字号:

/*
***********************************************************************************

NOTICE:
This document contains information that is proprietary to RADVISION LTD..
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD..

RADVISION LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.

***********************************************************************************
*/

#include "rvstdio.h"
#include "rvmutex.h"
#include "rvlock.h"
#include "rvmemory.h"
#include "rvlog.h"
#include "ra.h"
#include "ema.h"
#ifdef RV_EMA_DEBUG_DEADLOCKS
#include "rvthread.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif


/************************************************************************
 * emaObject struct
 * Holds the information of an emaObject
 ************************************************************************/
typedef struct
{
    HRA         ra; /* Handle to RA we're using */
    RvLogSource log; /* Log to use for messages */
    RvLock      lock; /* Lock we're using */
    emaLockType lockType; /* Type of locking mechanism to use */
    RvUint32    elemSize; /* Size of each element inside EMA */
    RvUint32    type; /* Integer representing the type of objects stored in EMA */
    void*       userData; /* User related information associated with this EMA object */
    void const* instance; /* Instance associated with this EMA object */
    RvUint32    markCount; /* Number of items currently deleted and marked */

    RvWatchdog* watchdog; /* Watchdog used (if not NULL) */
    RvUint32    watchdogResource; /* Resource index value in the watchdog */
} emaObject;


/************************************************************************
 * emaElem struct
 * Holds the information of an ema element
 *
 * Note: The mutex for the element is held in the end of the allocation
 *       if using emaNormalLocks. If emaLinkedLocks is used, then in the
 *       end of the allocation we'll have to pointer to the linked element
 *       in another EMA construct.
 ************************************************************************/
typedef struct
{
    emaObject*      ema; /* Pointer to the EMA object.
                            When this pointer is NULL, it indicates that the element
                            was deleted. We use this for emaLock().
                            THIS MUST BE THE FIRST FIELD IN THIS STRUCT! */
#ifdef RV_EMA_DEBUG
    RvUint32        debug1; /* Debugging bytes == EMA_DEBUG_BYTES */
#endif

    RvUint32        flags; /* Reference count and locks count.
                              It also holds a bit indicating if element was deleted */
    void*           appHandle; /* Application's handle of the EMA object */

#ifdef RV_EMA_DEBUG_DEADLOCKS
    RvThreadId      lockedThread; /* Indication who's the thread that locked this object */
#ifdef RV_EMA_DEBUG
    char*           filename; /* Filename that locked this object */
    int             lineno; /* Line number that locked this object */
#endif
#endif
#ifdef RV_EMA_DEBUG
    RvUint32        debug2; /* Debugging bytes == EMA_DEBUG_BYTES */
#endif
} emaElem;



/* Bytes used when debuging memory allocations */
#define EMA_DEBUG_BYTES (0xdeadbeef)

/* Indication in the reference count that this element was deleted */
#define EMA_ALREADY_DELETED     0x80000000

/* Indication of the reference count's actual value */
#define EMA_GET_REFERENCE(elem)         ((elem)->flags & 0x0000ffff)
#define EMA_INC_REFERENCE(elem,count)   ((elem)->flags += (RvUint16)(count))
#define EMA_DEC_REFERENCE(elem,count)   ((elem)->flags -= (RvUint16)(count))

/* Indication of the locks count's actual value */
#define EMA_GET_LOCKS(elem)             (((elem)->flags & 0x7fff0000) >> 16)
#define EMA_INC_LOCKS(elem,count)       ((elem)->flags += (((RvUint32)(count)) << 16))
#define EMA_DEC_LOCKS(elem,count)       ((elem)->flags -= (((RvUint32)(count)) << 16))



/************************************************************************
 *
 *                              Private functions
 *
 ************************************************************************/


/************************************************************************
 * emaDeleteElement
 * purpose: Delete an element used by ema.
 * input  : ema         - EMA object used
 *          rElem       - Element to delete
 *          location    - Location of element deleted
 *          decCount    - RV_TRUE if we need to decrease count of marked/deleted elements
 *          functionName- Name of function that called this one - used for log
 * output : none
 * return : none
 ************************************************************************/
static void emaDeleteElement(
    IN emaObject*   ema,
    IN emaElem*     rElem,
    IN int          location,
    IN RvBool       decCount,
    IN const char*  functionName)
{
    RvBool locked = RV_TRUE;
    EMAElement parent = NULL;
    if (functionName);

    /* First of all, let's lock the element and remove the reference to ema on it.
       Doing this, allows us to stay blocked on an emaLock() call while trying to
       delete the element */
    switch (ema->lockType)
    {
        case emaNoLocks:        break;
        case emaNormalLocks:    RvMutexLock((RvMutex *)((char*)rElem + sizeof(emaElem) + ema->elemSize)); break;
        case emaLinkedLocks:
        {
            parent = *((EMAElement*)((char*)rElem + sizeof(emaElem) + ema->elemSize));
            if (parent != NULL)
                locked = emaLock(parent);
            else
                locked = RV_FALSE;
            break;
        }
    }
    rElem->ema = NULL;
    if (locked)
    {
        switch (ema->lockType)
        {
            case emaNoLocks:        break;
            case emaNormalLocks:    RvMutexUnlock((RvMutex *)((char*)rElem + sizeof(emaElem) + ema->elemSize)); break;
            case emaLinkedLocks:    emaUnlock(parent); break;
        }
    }

    /* Do all the rest here */
    RvLockGet(&ema->lock);

    if (decCount)
        ema->markCount--;

    raDeleteLocation(ema->ra, location);

    RvLockRelease(&ema->lock);

    RvLogDebug(&ema->log,
        (&ema->log, "%s (%s): 0x%p deleted (location=%d)", functionName, raGetName(ema->ra), rElem, location));
}


/******************************************************************************
 * emaWatchdogResourceCallback
 * ----------------------------------------------------------------------------
 * General: Watchdog callback for accessing an EMA instance.
 *          This function is an accessory function to make the handling of
 *          EMA resources easier for the watchdog.
 *
 * Return Value: RV_OK  - if successful.
 *               Other on failure
 * ----------------------------------------------------------------------------
 * Arguments:
 * Input:  context      - EMA instance handle.
 *         resource     - The requested resource's enumeration.
 *         type         - The type of information requested.
 * Output: value        - The actual resource value.
 *****************************************************************************/
static int RVCALLCONV EmaWatchdogResourceCallback(
    IN  void*                   context,
    IN  RvUint32                resource,
    IN  RvWatchdogResourceType  type,
    OUT RvUint32*               value)
{
    emaObject* ema = (emaObject *)context;

    RV_UNUSED_ARG(resource);

    switch (type)
    {
    case RvWatchdogMaxVal:
        *value = raMaxSize(ema->ra);
        break;
    case RvWatchdogMaxUsage:
        *value = raMaxUsage(ema->ra);
        break;
    case RvWatchdogCurrent:
        *value = raCurSize(ema->ra);
        break;
    default:
        return RV_ERROR_UNKNOWN;
    }

    return RV_OK;
}





/************************************************************************
 *
 *                              Public functions
 *
 ************************************************************************/


/************************************************************************
 * emaConstruct
 * purpose: Create an EMA object
 * input  : elemSize            - Size of elements in the EMA in bytes
 *          maxNumOfElements    - Number of elements in EMA
 *          lockType            - Type of locking mechanism to use
 *          name                - Name of EMA (used in log messages)
 *          type                - Integer representing the type of objects
 *                                stored in this EMA.
 *          userData            - User related information associated with
 *                                this EMA object.
 *          instance            - Instance associated with this EMA object.
 * output : none
 * return : Handle to RA constructed on success
 *          NULL on failure
 ************************************************************************/
HEMA emaConstruct(
    IN int          elemSize,
    IN int          maxNumOfElements,
    IN emaLockType  lockType,
    IN const char*  name,
    IN RvUint32     type,
    IN void*        userData,
    IN void const*  instance)
{
    emaObject* ema;
    int allocSize = 0;

    /* Allocate the object */
    if(RvMemoryAlloc(NULL, (void**)&ema, sizeof(emaObject)) != RV_OK)
        return NULL;

    /* Remember the type of elements stored */
    ema->type = type;
    ema->userData = userData;
    ema->instance = instance;

    /* Create a log handle for our use */
    RvLogSourceConstruct(RvLogGet(), &ema->log, RV_LOG_LIBCODE_ASN1, "EMA", "Enhanced Memory Allocator");

    /* Calculate the size of each element (platform-aligned) */
    ema->elemSize = RvRoundToSize(elemSize, RV_ALIGN_SIZE);

    /* See if we need a lock for each element */
    switch (lockType)
    {
        case emaNoLocks:        allocSize = (int)(ema->elemSize + sizeof(emaElem)); break;
        case emaNormalLocks:    allocSize = (int)(ema->elemSize + sizeof(emaElem) + sizeof(RvMutex)); break;
        case emaLinkedLocks:    allocSize = (int)(ema->elemSize + sizeof(emaElem) + sizeof(EMAElement*)); break;
    }

    /* Create the RA */
    ema->ra = raConstruct(allocSize, maxNumOfElements, RV_FALSE, name);

    /* Create the mutex */
    RvLockConstruct(&ema->lock);
    ema->lockType = lockType;

#ifndef NOTHREADS
    if (lockType == emaNormalLocks)
    {
        int i;

        /* Initialize all the mutexes we need */
        for (i = 0; i < maxNumOfElements; i++)
        {
            RvMutexConstruct((RvMutex *) (RV_RA_ELEM_DATA(ema->ra, i) + sizeof(emaElem) + ema->elemSize));
        }
    }
#endif

    ema->markCount = 0;
    ema->watchdog = NULL;

    return (HEMA)ema;
}


/************************************************************************
 * emaDestruct
 * purpose: Free an EMA object, deallocating all of its used memory
 * input  : emaH   - Handle of the EMA object
 * output : none
 * return : none
 ************************************************************************/
void emaDestruct(IN HEMA emaH)
{
    emaObject* ema = (emaObject *)emaH;
    int numElems;

    if (ema == NULL) return;

    numElems = raCurSize(ema->ra);
    if (numElems > 0)
    {
        RvLogWarning(&ema->log,
            (&ema->log, "emaDestruct (%s): %d elements not deleted", raGetName(ema->ra), numElems));
    }

    /* Remove lock */
    RvLockDestruct(&ema->lock);

#ifndef NOTHREADS
    if (ema->lockType == emaNormalLocks)
    {
        int i;

        /* End all the mutexes we initialized */
        for (i = 0; i < raMaxSize(ema->ra); i++)
        {
            RvMutexDestruct((RvMutex *) (RV_RA_ELEM_DATA(ema->ra, i) + sizeof(emaElem) + ema->elemSize));
        }
    }
#endif

    /* Remove watchdog resource if we have to */
    if (ema->watchdog != NULL)
        RvWatchdogDeleteResource(ema->watchdog, ema->watchdogResource);

    /* Free any used memory and RA */
    raDestruct(ema->ra);
    RvLogSourceDestruct(RvLogGet(), &ema->log);
    RvMemoryFree(ema);
}


/************************************************************************
 * emaAdd
 * purpose: Allocate an element in EMA for use, without initializing its
 *          value.
 *          This automatically locks the EMA object.
 * input  : emaH       - Handle of the EMA object
 *          appHandle   - Application's handle for the EMA object
 * output : none
 * return : Pointer to element added on success
 *          NULL on failure

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -