#include "sdolist.h"

#include <iostream.h>

ClassImp(PendingSDO);
ClassImp(PendingSDOList);

PendingSDOList::PendingSDOList()
{
    fFirst = new PendingSDO;
    fLast  = fFirst;

    pthread_mutex_init(&fMux, NULL);
}

PendingSDOList::~PendingSDOList()
{
    // pthread_mutex_lock(&fMux);

    DelAll();
    delete fFirst;

    pthread_mutex_destroy(&fMux);
}

void PendingSDOList::DelAll()
{
    pthread_mutex_lock(&fMux);

    PendingSDO *prev = fFirst;
    PendingSDO *sdo;

    do
    {
        sdo = prev->Next;
        delete prev;

    } while((prev=sdo));

    fFirst = new PendingSDO;
    fLast  = fFirst;

    pthread_mutex_unlock(&fMux);
}

void PendingSDOList::Add(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    PendingSDO *sdo = fFirst;

    pthread_mutex_lock(&fMux);
    while ((sdo=sdo->Next))
        if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx)
        {
            cout << "Warning: SDO Node #" << dec << (int)node << ", 0x";
            cout << hex << idx << "/" << (int)subidx;
            cout << " still pending." << endl;
            break;
        }

    fLast->Next = new PendingSDO(node, idx, subidx);
    fLast = fLast->Next;
    pthread_mutex_unlock(&fMux);
}

void PendingSDOList::Del(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    PendingSDO *prev = fFirst;
    PendingSDO *sdo;

    pthread_mutex_lock(&fMux);
    while ((sdo=prev->Next))
    {
        if (sdo->Node!=node || sdo->Idx!=idx || sdo->Subidx!=subidx)
        {
            prev = sdo;
            continue;
        }

        prev->Next = sdo->Next;

        delete sdo;

        if (!prev->Next)
            fLast = prev;

        break;
    }
    pthread_mutex_unlock(&fMux);
}

int PendingSDOList::IsPending() const
{
    return (int)fFirst->Next;
}

int PendingSDOList::IsPending(BYTE_t node)
{
    int rc = FALSE;
    PendingSDO *sdo = fFirst;

    pthread_mutex_lock(&fMux);
    while ((sdo=sdo->Next))
        if (sdo->Node==node)
        {
            rc = TRUE;
            break;
        }
    pthread_mutex_unlock(&fMux);

    return rc;
}

int PendingSDOList::IsPending(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    int rc = FALSE;
    PendingSDO *sdo = fFirst;

    pthread_mutex_lock(&fMux);
    while ((sdo=sdo->Next))
        if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx)
        {
            rc = TRUE;
            break;
        }
    pthread_mutex_unlock(&fMux);

    return rc;
}
