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

📄 ema.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 4 页
字号:
 ************************************************************************/
EMAElement emaAdd(IN HEMA emaH, IN void* appHandle)
{
    emaObject* ema = (emaObject *)emaH;
    emaElem* elem;
    char* ptr;
    int location;

    /* Use RA for our purposes */
    RvLockGet(&ema->lock);
    location = raAdd(ema->ra, (RAElement*)&elem);
    RvLockRelease(&ema->lock);

    /* Make sure it was allocated */
    if (location < 0)
    {
        RvLogError(&ema->log,
            (&ema->log, "emaAdd (%s): Out of resources", raGetName(ema->ra)));
        return NULL;
    }

    /* Set the element's OO information */
    elem->ema = ema;
    elem->flags = 0;
    elem->appHandle = appHandle;
#ifdef RV_EMA_DEBUG
    elem->debug1 = EMA_DEBUG_BYTES;
    elem->debug2 = EMA_DEBUG_BYTES;
#endif

    RvLogDebug(&ema->log,
        (&ema->log, "emaAdd (%s): Got 0x%p (location=%d)", raGetName(ema->ra), elem, location));

    ptr = (char*)elem + sizeof(emaElem);

    /* Allocate a mutex if necessary */
    switch (ema->lockType)
    {
        case emaLinkedLocks: memset(ptr + ema->elemSize, 0, sizeof(EMAElement*)); break;
        default:             break;
    }

    /* Calculate and return the position of the true element */
    return (EMAElement*)ptr;
}


/************************************************************************
 * emaDelete
 * purpose: Delete an element from EMA
 * input  : elem    - Element to delete
 * return : Negative value on failure
 ************************************************************************/
#ifdef RV_EMA_DEBUG
int emaDeleteDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
int emaDelete(IN EMAElement elem)
#endif
{
    emaObject* ema;
    emaElem* rElem;
    int location;

    if (elem == NULL) return RV_ERROR_UNKNOWN;

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

    /* Find the location */
    location = raGetByPtr(ema->ra, rElem);

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

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

    /* Check the reference count */
    if (rElem->flags == 0)
    {
        /* No one is looking for this guy - we can delete it */
        emaDeleteElement(ema, rElem, location, RV_FALSE, "emaDelete");
    }
    else
    {
        RvLockGet(&ema->lock);

#ifdef RV_EMA_DEBUG
        if ((rElem->flags & EMA_ALREADY_DELETED) != 0)
        {
            RvLogExcep(&ema->log,
                (&ema->log, "emaDelete (%s): Deleting an element 0x%p for the second time",
                     raGetName(ema->ra), rElem));
        }
#endif
        ema->markCount++;
        rElem->flags |= EMA_ALREADY_DELETED;

        RvLockRelease(&ema->lock);
    }


    return 0;
}


/************************************************************************
 * emaLinkToElement
 * purpose: Link an EMA element to another element, from a different
 *          EMA construct. This function should be used when the EMA we're
 *          dealing with was created with emaLinkedLocks. This function
 *          allows the element to use a different element's lock.
 *          This function will only work if the element has no reference
 *          count at present.
 * input  : elem        - Element to link
 *          otherElem   - Element we're linking to. Should be constructed
 *                        with emaNormalLocks or linked to such element.
 * output : none
 * return : Non-negative value on success
 *          Negative value on failure
 ************************************************************************/
int emaLinkToElement(IN EMAElement elem, IN EMAElement otherElem)
{
    emaObject*  ema;
    emaElem*    rElem;
    EMAElement* parent;

    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 the element */
    if (ema == NULL) return RV_ERROR_UNKNOWN;

    RvLogDebug(&ema->log,
        (&ema->log, "emaLinkToElement (%s): Linking 0x%p to 0x%p", raGetName(ema->ra), rElem, otherElem));

#ifdef RV_EMA_DEBUG
    if (ema->lockType != emaLinkedLocks)
    {
        RvLogExcep(&ema->log,
            (&ema->log, "emaLinkToElement (%s): This EMA cannot be linked", raGetName(ema->ra)));
        return RV_ERROR_UNKNOWN;
    }
#endif

    /* Find place of parent */
    parent = (EMAElement*)((char*)elem + ema->elemSize);
    if (EMA_GET_REFERENCE(rElem) > 0)
    {
        RvLogError(&ema->log,
            (&ema->log, "emaLinkToElement (%s): Cannot link 0x%p - has a positive reference count",
                 raGetName(ema->ra), rElem));
        return RV_ERROR_UNKNOWN;
    }

    *parent = otherElem;
    return 0;
}


/************************************************************************
 * emaLock
 * purpose: Lock an element in EMA for use from the executing thread only
 *          This function will succeed only if the element exists
 * input  : elem    - Element to lock
 * output : none
 * return : RV_TRUE    - When the element exists and was locked
 *          RV_FALSE   - When the element doesn't exist (NULL are was deleted)
 *                    In this case, there's no need to call emaUnlock().
 ************************************************************************/
#ifdef RV_EMA_DEBUG
RvBool emaLockDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
RvBool emaLock(IN EMAElement elem)
#endif
{
    emaObject*  ema;
    emaElem*    rElem;
    RvBool      status = RV_TRUE;
    EMAElement  parent = NULL;
#ifdef RV_EMA_DEBUG_DEADLOCKS
    RvThreadId  curThreadId = RvThreadCurrentId();
#endif

    if (elem == NULL) return RV_FALSE;

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

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

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

    switch (ema->lockType)
    {
#ifdef RV_EMA_DEBUG
        case emaNoLocks:
            RvLogExcep(&ema->log,
                (&ema->log, "emaLock (%s): This EMA cannot be locked", raGetName(ema->ra)));
            break;
#endif
        case emaNormalLocks:
            /* We lock it */
            RvMutexLock((RvMutex *)((char*)elem + ema->elemSize));

            /* Now that it's locked, see if the element still exists */
            if (rElem->ema == NULL)
            {
                /* Seems like someone has deleted this element when we were trying to lock it */
#ifdef RV_EMA_DEBUG
                RvLogDebug(&ema->log,
                    (&ema->log, "emaLock (%s): Unlocking deleted element 0x%p", raGetName(ema->ra), rElem));
#endif
                status = RV_FALSE;

                /* Release the lock - we shouldn't go on with it */
                RvMutexUnlock((RvMutex *)((char*)elem + ema->elemSize));
            }
            break;

        case emaLinkedLocks:
        {
            /* We lock the parent */
            parent = *((EMAElement*)((char*)elem + ema->elemSize));
            if (parent != NULL)
                status = emaLock(parent);
            else
                status = RV_FALSE;

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

    /* Make sure we increment the reference count on this one */
    if (status == RV_TRUE)
    {
#ifdef RV_EMA_DEBUG_DEADLOCKS
        rElem->lockedThread = curThreadId;
#ifdef RV_EMA_DEBUG
        rElem->filename = filename;
        rElem->lineno = lineno;
#endif
#endif
        EMA_INC_REFERENCE(rElem,1);
        EMA_INC_LOCKS(rElem,1);
    }

    return status;
}


/************************************************************************
 * emaUnlock
 * purpose: Unlock an element in EMA that were previously locked by
 *          emaLock() from the same thread
 * input  : elem    - Element to unlock
 * 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 emaUnlockDebug(IN EMAElement elem, IN const char* filename, IN int lineno)
#else
int emaUnlock(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,
        "emaUnlock (%s): Unlocking 0x%p (%s:%d)", raGetName(ema->ra), rElem, filename, lineno));

    if (EMA_GET_LOCKS(rElem) == 0)
    {
        RvLogExcep(&ema->log, (&ema->log,
            "emaUnlock (%s): Element 0x%p (%s:%d) is not locked!", raGetName(ema->ra), rElem, filename, lineno));
        return RV_OK;
    }
#endif

    EMA_DEC_REFERENCE(rElem,1);
    EMA_DEC_LOCKS(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, "emaUnlock");
    }

    switch (ema->lockType)
    {
#ifdef RV_EMA_DEBUG
        case emaNoLocks:
            RvLogExcep(&ema->log,
                (&ema->log, "emaUnlock (%s): This EMA cannot be unlocked", raGetName(ema->ra)));
            break;
#endif
        case emaNormalLocks:
            /* We lock it */
            RvMutexUnlock((RvMutex *)((char*)elem + ema->elemSize));
            break;
        case emaLinkedLocks:
        {
            /* We lock the parent */
            int result = RV_ERROR_UNKNOWN;
            EMAElement  parent = *((EMAElement*)((char*)elem + ema->elemSize));
            if (parent != NULL)
                result = emaUnlock(parent);

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

    return elemExists;
}


/************************************************************************
 * emaMark

⌨️ 快捷键说明

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