#include "DLLDateien.h"

// Inhalt der DLLDateien Klasse aus DLLDateien.h
// Konstruktor
DLLDateien::DLLDateien() noexcept
{
    try
    {
        dlls = new Array< DLLDatei* >();
        ref = 1;
    }
    catch( std::exception e )
    {

    }
}

// Destruktor
DLLDateien::~DLLDateien()
{
    cs.lock();
    int anz = dlls->getEintragAnzahl();
    for( int i = 0; i < anz; i++ )
    {
        DLLDatei *tmp = dlls->get( i );
        if( tmp )
        {
            tmp->name->release();
            FreeLibrary( tmp->handle );
        }
        delete tmp;
    }
    dlls->release();
    cs.unlock();
}

// nicht constant
HINSTANCE DLLDateien::ladeDLL( char *name, char *pfad )
{
    cs.lock();
    int anz = dlls->getEintragAnzahl();
    for( int i = 0; i < anz; i++ )
    {
        DLLDatei *tmp = dlls->get( i );
        if( tmp && tmp->name->istGleich( name ) )
        {
            tmp->ref++;
            cs.unlock();
            return tmp->handle;
        }
    }
    HINSTANCE h = LoadLibrary( pfad );
    if( !h )
    {
        cs.unlock();
        return 0;
    }
    DLLDatei *dll = new DLLDatei();
    dll->name = new Text( name );
    dll->handle = h;
    dll->ref = 1;
    dlls->add( dll );
    cs.unlock();
    return h;
}

void DLLDateien::releaseDLL( char *name )
{
    cs.lock();
    int anz = dlls->getEintragAnzahl();
    for( int i = 0; i < anz; i++ )
    {
        DLLDatei *tmp = dlls->get( i );
        if( tmp && tmp->name->istGleich( name ) )
        {
            tmp->ref--;
            if( !tmp->ref )
            {
                tmp->name->release();
                FreeLibrary( tmp->handle );
                delete tmp;
                dlls->remove( i );
            }
            cs.unlock();
            return;
        }
    }
    cs.unlock();
}

// Reference Counting
DLLDateien *DLLDateien::getThis()
{
    ref++;
    return this;
}

DLLDateien *DLLDateien::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}