root/src/kits/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.cpp
/*
 * Copyright 2014, Rene Gollent, rene@gollent.com.
 * Distributed under the terms of the MIT License.
 */


#include "ImageDebugLoadingStateHandlerRoster.h"

#include <new>

#include <AutoDeleter.h>
#include <AutoLocker.h>

#include "DwarfLoadingStateHandler.h"
#include "ImageDebugInfoLoadingState.h"
#include "ImageDebugLoadingStateHandler.h"
#include "SpecificImageDebugInfoLoadingState.h"


/*static*/ ImageDebugLoadingStateHandlerRoster*
        ImageDebugLoadingStateHandlerRoster::sDefaultInstance = NULL;


ImageDebugLoadingStateHandlerRoster::ImageDebugLoadingStateHandlerRoster()
        :
        fLock("loading state handler roster"),
        fStateHandlers(20)
{
}


ImageDebugLoadingStateHandlerRoster::~ImageDebugLoadingStateHandlerRoster()
{
        for (int32 i = 0; ImageDebugLoadingStateHandler* handler
                        = fStateHandlers.ItemAt(i); i++) {
                handler->ReleaseReference();
        }
}


/*static*/ ImageDebugLoadingStateHandlerRoster*
ImageDebugLoadingStateHandlerRoster::Default()
{
        return sDefaultInstance;
}


/*static*/ status_t
ImageDebugLoadingStateHandlerRoster::CreateDefault()
{
        if (sDefaultInstance != NULL)
                return B_OK;

        ImageDebugLoadingStateHandlerRoster* roster
                = new(std::nothrow) ImageDebugLoadingStateHandlerRoster;
        if (roster == NULL)
                return B_NO_MEMORY;
        ObjectDeleter<ImageDebugLoadingStateHandlerRoster> rosterDeleter(roster);

        status_t error = roster->Init();
        if (error != B_OK)
                return error;

        error = roster->RegisterDefaultHandlers();
        if (error != B_OK)
                return error;

        sDefaultInstance = rosterDeleter.Detach();
        return B_OK;
}


/*static*/ void
ImageDebugLoadingStateHandlerRoster::DeleteDefault()
{
        ImageDebugLoadingStateHandlerRoster* roster = sDefaultInstance;
        sDefaultInstance = NULL;
        delete roster;
}


status_t
ImageDebugLoadingStateHandlerRoster::Init()
{
        return fLock.InitCheck();
}


status_t
ImageDebugLoadingStateHandlerRoster::RegisterDefaultHandlers()
{
        ImageDebugLoadingStateHandler* handler;
        BReference<ImageDebugLoadingStateHandler> handlerReference;

        handler = new(std::nothrow) DwarfLoadingStateHandler();
        if (handler == NULL)
                return B_NO_MEMORY;
        handlerReference.SetTo(handler, true);

        if (!RegisterHandler(handler))
                return B_NO_MEMORY;

        return B_OK;
}


status_t
ImageDebugLoadingStateHandlerRoster::FindStateHandler(
        SpecificImageDebugInfoLoadingState* state,
        ImageDebugLoadingStateHandler*& _handler)
{
        AutoLocker<BLocker> locker(fLock);

        bool found = false;
        ImageDebugLoadingStateHandler* handler = NULL;
        for (int32 i = 0; (handler = fStateHandlers.ItemAt(i)); i++) {
                if ((found = handler->SupportsState(state)))
                        break;
        }

        if (!found)
                return B_ENTRY_NOT_FOUND;

        handler->AcquireReference();
        _handler = handler;
        return B_OK;
}


bool
ImageDebugLoadingStateHandlerRoster::RegisterHandler(
        ImageDebugLoadingStateHandler* handler)
{
        if (!fStateHandlers.AddItem(handler))
                return false;

        handler->AcquireReference();
        return true;
}


void
ImageDebugLoadingStateHandlerRoster::UnregisterHandler(
        ImageDebugLoadingStateHandler* handler)
{
        if (fStateHandlers.RemoveItem(handler))
                handler->ReleaseReference();
}