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

📄 ema.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 4 页
字号:
 * purpose: Mark an element in EMA for use, not letting anyone delete
 *          this element until it is release.
 *          This automatically locks the EMA object.
 * input  : elem    - Element to mark
 * output : none
 * return : Negative value on failure
 ************************************************************************/
#ifdef RV_EMA_DEBUG
int emaMarkDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
int emaMark(IN EMAElement elem)
#endif
{
    emaObject* ema;
    emaElem* rElem;

    if (elem == NULL) return RV_ERROR_UNKNOWN;

    /* Find out our element information */
    rElem = (emaElem *)((char*)elem - sizeof(emaElem));
    ema = rElem->ema;

#ifdef RV_EMA_DEBUG
    RvLogDebug(&ema->log,
        (&ema->log, "emaMark (%s): Marking 0x%p, refCount=%d (%s:%d)",
             raGetName(ema->ra), rElem, EMA_GET_REFERENCE(rElem), filename, lineno));

    if ((rElem->debug1 != EMA_DEBUG_BYTES) || (rElem->debug2 != EMA_DEBUG_BYTES))
    {
        RvLogExcep(&ema->log,
            (&ema->log, "emaMark (%s): Someone is messing with memory 0x%p", raGetName(ema->ra), rElem));
    }
#endif

    /* Increase the reference count */
    switch (ema->lockType)
    {
        case emaNoLocks:        break;
        case emaNormalLocks:    RvMutexLock((RvMutex *)((char*)elem + ema->elemSize)); break;
        case emaLinkedLocks:
            emaLock(*((EMAElement*)((char*)elem + ema->elemSize)));
            emaMark(*((EMAElement*)((char*)elem + ema->elemSize)));
            break;
    }

    EMA_INC_REFERENCE(rElem,1);

    switch (ema->lockType)
    {
        case emaNoLocks:        break;
        case emaNormalLocks:    RvMutexUnlock((RvMutex *)((char*)elem + ema->elemSize)); break;
        case emaLinkedLocks:    emaUnlock(*((EMAElement*)((char*)elem + ema->elemSize))); break;
    }

    return 0;
}


/************************************************************************
 * emaRelease
 * purpose: Release an element in EMA after it was marked using
 *          emaMark(), returning an indication if this element
 *          still exists.
 *          This automatically locks the EMA object.
 * input  : elem    - Element to mark
 * output : none
 * return : RV_TRUE    if element still exists
 *          RV_FALSE   if element was deleted and is not valid anymore
 *          Negative value on failure
 ************************************************************************/
#ifdef RV_EMA_DEBUG
int emaReleaseDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
int emaRelease(IN EMAElement elem)
#endif
{
    emaObject* ema;
    emaElem* rElem;
    int elemExists;

    if (elem == NULL) return RV_ERROR_UNKNOWN;

    /* Find out our element information */
    rElem = (emaElem *)((char*)elem - sizeof(emaElem));
    ema = rElem->ema;

#ifdef RV_EMA_DEBUG
    RvLogDebug(&ema->log, (&ema->log,
        "emaRelease (%s): Releasing 0x%p, refCount=%d (%s:%d)",
             raGetName(ema->ra), rElem, EMA_GET_REFERENCE(rElem), filename, lineno));

    if (EMA_GET_REFERENCE(rElem) == 0)
    {
        RvLogExcep(&ema->log, (&ema->log,
            "emaRelease (%s): Releasing 0x%p (%s:%d) when it's not marked!",
            raGetName(ema->ra), rElem, filename, lineno));
    }

    if ((rElem->debug1 != EMA_DEBUG_BYTES) || (rElem->debug2 != EMA_DEBUG_BYTES))
    {
        RvLogExcep(&ema->log, (&ema->log,
            "emaRelease (%s): Someone is messing with memory 0x%p", raGetName(ema->ra), rElem));
    }
#else
    RvLogDebug(&ema->log,
        (&ema->log, "emaRelease (%s): Releasing 0x%p, refCount=%d", raGetName(ema->ra), rElem, EMA_GET_REFERENCE(rElem)));
#endif

    /* Decrease the reference count */
    switch (ema->lockType)
    {
        case emaNoLocks:        break;
        case emaNormalLocks:    RvMutexLock((RvMutex *)((char*)elem + ema->elemSize)); break;
        case emaLinkedLocks:
            emaLock(*((EMAElement*)((char*)elem + ema->elemSize)));
            emaRelease(*((EMAElement*)((char*)elem + ema->elemSize)));
            break;
    }

    EMA_DEC_REFERENCE(rElem,1);
    elemExists = ((rElem->flags & EMA_ALREADY_DELETED) == 0);

    /* Delete element if we're done with it */
    if (rElem->flags == EMA_ALREADY_DELETED)
    {
        int location = raGetByPtr(ema->ra, rElem);
        emaDeleteElement(ema, rElem, location, RV_TRUE, "emaRelease");
    }

    switch (ema->lockType)
    {
        case emaNoLocks:        break;
        case emaNormalLocks:    RvMutexUnlock((RvMutex *)((char*)elem + ema->elemSize)); break;
        case emaLinkedLocks:
            emaUnlock(*((EMAElement*)((char*)elem + ema->elemSize)));
            break;
    }

    return elemExists;
}


/************************************************************************
 * emaWasDeleted
 * purpose: Check if an element in EMA was deleted after a call to
 *          emaMark().
 * input  : elem    - Element to mark
 * output : none
 * return : RV_TRUE    if element was deleted
 *          RV_FALSE   if element still exists
 ************************************************************************/
RvBool emaWasDeleted(IN EMAElement elem)
{
    emaObject* ema;
    emaElem* rElem;

    /* Find out our element information */
    rElem = (emaElem *)((char*)elem - sizeof(emaElem));
    ema = rElem->ema;

    RvLogDebug(&ema->log,
        (&ema->log, "emaWasDeleted (%s): Checking 0x%p (refCount=%d)",
             raGetName(ema->ra), rElem, EMA_GET_REFERENCE(rElem)));

#ifdef RV_EMA_DEBUG
    if ((rElem->debug1 != EMA_DEBUG_BYTES) || (rElem->debug2 != EMA_DEBUG_BYTES))
    {
        RvLogExcep(&ema->log,
            (&ema->log, "emaWasDeleted (%s): Someone is messing with memory 0x%p", raGetName(ema->ra), rElem));
    }
#endif

    /* Check if element was deleted */
    return ((rElem->flags & EMA_ALREADY_DELETED) != 0);
}


/************************************************************************
 * emaPrepareForCallback
 * purpose: Prepare an element in EMA for use in a callback to the app.
 *          This function will make sure the element is unlocked the necessary
 *          number of times, and then marked once (so the app won't delete
 *          this element).
 *          emaReturnFromCallback() should be called after the callback,
 *          with the return value of this function.
 * input  : elem    - Element to prepare
 * output : none
 * return : Number of times the element was locked on success
 *          Negative value on failure
 ************************************************************************/
#ifdef RV_EMA_DEBUG
int emaPrepareForCallbackDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
int emaPrepareForCallback(IN EMAElement elem)
#endif
{
    emaObject*  ema;
    emaElem*    rElem;
    int         numLocks;

    if (elem == NULL) return RV_ERROR_UNKNOWN;

    /* Find out our element information */
    rElem = (emaElem *)((char*)elem - sizeof(emaElem));
    ema = rElem->ema;

    /* Make sure we've got an element */
    if (ema == NULL) return RV_ERROR_UNKNOWN;

#ifdef RV_EMA_DEBUG
    if (EMA_GET_LOCKS(rElem) == 0)
    {
        RvLogInfo(&ema->log, (&ema->log,
            "emaPrepareForCallback (%s): on 0x%p (%s:%d) when not locked!",
                 raGetName(ema->ra), rElem, filename, lineno));
    }
#endif

    /* Increase the reference count */
    EMA_INC_REFERENCE(rElem,1);

    /* See where the do we have to unlock */
    switch (ema->lockType)
    {
        case emaNormalLocks:
        {
            /* We unlock the element */
            int i;
            numLocks = EMA_GET_LOCKS(rElem);

            /* First we decrease the number of locks, and then we actually exit them... */
            EMA_DEC_LOCKS(rElem,numLocks);
            for (i = 0; i < numLocks; i++)
            {
                RvMutexUnlock((RvMutex *)((char*)elem + ema->elemSize));
            }
            break;
        }
        case emaLinkedLocks:
        {
            /* We must prepare the parent */
            EMAElement  parent = *((EMAElement*)((char*)elem + ema->elemSize));
            if (parent != NULL)
                numLocks = emaPrepareForCallback(parent);
            else
                numLocks = RV_ERROR_UNKNOWN;

            if (numLocks < 0)
            {
                RvLogWarning(&ema->log,
                    (&ema->log, "emaPrepareForCallback (%s): Couldn't prepare parent=0x%p of 0x%p for some reason",
                         raGetName(ema->ra), parent, elem));
            }
            break;
        }
        default:
            numLocks = 0;
            break;
    }

#ifdef RV_EMA_DEBUG
    RvLogDebug(&ema->log,
        (&ema->log, "emaPrepareForCallback (%s): on 0x%p - locked %d times (%s:%d)",
             raGetName(ema->ra), rElem, numLocks, filename, lineno));
#endif
    return numLocks;
}


/************************************************************************
 * emaReturnFromCallback
 * purpose: Make sure the EMA element knows it has returned from a
 *          callback. This function will ensure that the element is
 *          locked again with the specified number of times. It will also
 *          release the element, and if timersLocked==0, and the element
 *          was deleted by the app in the callback, the element will also
 *          be permanently deleted.
 * input  : elem    - Element to prepare
 * output : none
 * return : RV_TRUE    if element still exists
 *          RV_FALSE   if element was deleted and is not valid anymore
 *          Negative value on failure
 ************************************************************************/
#ifdef RV_EMA_DEBUG
int emaReturnFromCallbackDebug(IN EMAElement elem, IN int timesLocked, IN const char* filename, IN int lineno)
#else
int emaReturnFromCallback(IN EMAElement elem, IN int timesLocked)
#endif
{
    emaObject*  ema;
    emaElem*    rElem;
    int         status = RV_ERROR_UNKNOWN;

    if (elem == NULL) return RV_ERROR_UNKNOWN;

    /* Find out our element information */
    rElem = (emaElem *)((char*)elem - sizeof(emaElem));
    ema = rElem->ema;

    /* Make sure we've got an element */
    if (ema == NULL) return RV_ERROR_UNKNOWN;

#ifdef RV_EMA_DEBUG
    RvLogDebug(&ema->log,
        (&ema->log, "emaReturnFromCallback (%s): on 0x%p, %d times (%s:%d)",
             raGetName(ema->ra), rElem, timesLocked, filename, lineno));
#endif

    /* See where the do we have to unlock */
    switch (ema->lockType)
    {
        case emaNormalLocks:
        {
            /* We unlock the element */
            int i;

            /* First we should lock, and only then: increase the number of locks */
            for (i = 0; i < timesLocked; i++)
            {
                RvMutexLock((RvMutex *)((char*)elem + ema->elemSize));
            }
            EMA_INC_LOCKS(rElem,timesLocked);
            status = 0;
            break;
        }
        case emaLinkedLocks:
        {
            /* We must prepare the parent */
            EMAElement  parent = *((EMAElement*)((char*)elem + ema->elemSize));
            if (parent != NULL)
                status = emaReturnFromCallback(parent, timesLocked);
            else
                status = RV_ERROR_UNKNOWN;

            if (status < 0)
            {
                RvLogWarning(&ema->log,
                    (&ema->log, "emaReturnFromCallback (%s): Couldn't return parent=0x%p of 0x%p for some reason",
                         raGetName(ema->ra), parent, elem));
            }
            break;
        }
        default:
            break;
    }

    /* Decrease the reference count */
    EMA_DEC_REFERENCE(rElem,1);

    /* Delete element if we're done with it */
    if (rElem->flags == EMA_ALREADY_DELETED)
    {
        int location = raGetByPtr(ema->ra, rElem);
        emaDeleteElement(ema, rElem, location, RV_TRUE, "emaReturnFromCallback");
    }
    else
    {
        /* We didn't delete this element... */
        status = RV_TRUE;
    }

    return status;
}


/************************************************************************
 * emaSetApplicationHandle
 * purpose: Set the application handle of an element in EMA
 * input  : elem        - Element in EMA
 *          appHandle   - Application's handle for the element

⌨️ 快捷键说明

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