Program Listing for File managers.hpp

Return to documentation for file (/tmp/ws/src/ecl_lite/ecl_sigslots_lite/include/ecl/sigslots_lite/managers.hpp)

/*****************************************************************************
** Ifdefs
*****************************************************************************/

#ifndef ECL_SIGSLOTS_LITE_MANAGERS_HPP_
#define ECL_SIGSLOTS_LITE_MANAGERS_HPP_

/*****************************************************************************
** Includes
*****************************************************************************/

#include "slot.hpp"

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace ecl {
namespace lite {

/*****************************************************************************
** Forward Declarations
*****************************************************************************/

template <typename Data, unsigned int Capacity> class Signal;

/*****************************************************************************
** Managers
*****************************************************************************/

namespace sigslots {
template <typename Data, typename FunctionClass>
class MemberSlotsBase {
public:
    virtual unsigned int stored() const { return 0; }
    virtual unsigned int capacity() const { return 0; }
    virtual sigslots::MemberSlot<Data,FunctionClass>* addSlot(void (FunctionClass::*func)(Data), FunctionClass &instance) = 0;
};

template <typename FunctionClass>
class MemberSlotsBase<void,FunctionClass> {
public:
    virtual unsigned int stored() const { return 0; }
    virtual unsigned int capacity() const { return 0; }
    virtual sigslots::MemberSlot<void,FunctionClass>* addSlot(void (FunctionClass::*func)(), FunctionClass &instance) = 0;
};

} // namespace sigslots

/******************************************
** Member Manager
*******************************************/
template <typename Data, typename FunctionClass, unsigned int Capacity = 1>
class MemberSlots : public sigslots::MemberSlotsBase<Data,FunctionClass> {
public:
    /*********************
    ** Friends
    **********************/
    // allow connect to use addSlot
    template <typename Data_, unsigned int Capacity_, typename FunctionClass_>
    friend sigslots::Error connect(Signal<Data_,Capacity_> &signal, void(FunctionClass_::*f)(Data_), FunctionClass_ &o);

    // needs access to stored()
    template <typename Data_, typename FunctionClass_>
    friend unsigned int member_slots_stored(const FunctionClass_ &object);

    // needs access to capacity()
    template <typename Data_, typename FunctionClass_>
    friend unsigned int member_slots_capacity(const FunctionClass_ &object);


protected:
    MemberSlots() : size(0) {};

private:
    unsigned int stored() const { return size; }
    unsigned int capacity() const { return Capacity; }

    sigslots::MemberSlot<Data,FunctionClass>* addSlot(void (FunctionClass::*func)(Data), FunctionClass &instance) {
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( func == slots[i].member_function ) {
                return &(slots[i]);
            }
        }
        if ( size < Capacity ) {
            slots[size] = sigslots::MemberSlot<Data,FunctionClass>(func,instance);
            ++size;
            return &(slots[size-1]);
        } else {
            return NULL;
        }
    }

    unsigned int size;
    sigslots::MemberSlot<Data,FunctionClass> slots[Capacity];
};

/******************************************
** Global Manager
*******************************************/

template <typename Data, typename Dummy = int>
class GlobalSlots {
public:
    static const unsigned int capacity;
    /*********************
    ** Friends
    **********************/
    // needs access to addSlot()
    template <typename Data_, unsigned int Capacity_>
    friend sigslots::Error connect(Signal<Data_, Capacity_> &signal, void (*function)(Data_));

    // needs access to stored()
    template <typename Data_>
    friend unsigned int global_slots_stored();

private:
    static unsigned int stored(const bool increment = false) {
        static unsigned int stored_slots = 0;
        if ( increment ) { ++stored_slots; }
        return stored_slots;
    }
    static sigslots::GlobalSlot<Data>* addSlot(void (*func)(Data)) {
        unsigned int size = stored();
        static sigslots::GlobalSlot<Data> slots[capacity];
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( func == slots[i].global_function ) {
                return &(slots[i]);
            }
        }
        if ( size < capacity ) {
            slots[size] = sigslots::GlobalSlot<Data>(func);
            bool inc = true;
            stored(inc); // increment the number of stored slots variable
            return &(slots[size]);
        } else {
            return NULL;
        }
    }
};

/*****************************************************************************
** Specialisations
*****************************************************************************/
template <typename FunctionClass, unsigned int Capacity>
class MemberSlots<void, FunctionClass, Capacity> : public sigslots::MemberSlotsBase<void,FunctionClass> {
public:
    /*********************
    ** Friends
    **********************/
    // allow connect to use addSlot
    template <unsigned int Capacity_, typename FunctionClass_>
    friend sigslots::Error connect(Signal<void,Capacity_> &signal, void(FunctionClass_::*f)(void), FunctionClass_ &o);
    // needs access to stored()
    template <typename Data_, typename FunctionClass_>
    friend unsigned int member_slots_stored(const FunctionClass_ &object);

    // needs access to capacity()
    template <typename Data_, typename FunctionClass_>
    friend unsigned int member_slots_capacity(const FunctionClass_ &object);

protected:
    MemberSlots() : size(0) {};

private:
    unsigned int stored() const { return size; }

    unsigned int capacity() const { return Capacity; }

    sigslots::MemberSlot<void,FunctionClass>* addSlot(void (FunctionClass::*func)(void), FunctionClass &instance) {
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( func == slots[i].member_function ) {
                return &(slots[i]);
            }
        }
        if ( size < Capacity ) {
            slots[size] = sigslots::MemberSlot<void,FunctionClass>(func,instance);
            ++size;
            return &(slots[size-1]);
        } else {
            return NULL;
        }
    }

    unsigned int size;
    sigslots::MemberSlot<void,FunctionClass> slots[Capacity];
};

template <typename Dummy>
class GlobalSlots<void, Dummy> {
public:
    static const unsigned int capacity;
    /*********************
    ** Friends
    **********************/
    // needs access to addSlot()
    template <unsigned int Capacity_>
    friend sigslots::Error connect(Signal<void,Capacity_> &signal, void (*function)(void));

    // needs access to stored()
    template <typename Data> friend unsigned int global_slots_stored();

private:
    static unsigned int stored(const bool increment = false) {
        static unsigned int stored_slots = 0;
        if ( increment ) { ++stored_slots; }
        return stored_slots;
    }

    static sigslots::GlobalSlot<void>* addSlot(void (*func)(void)) {
        unsigned int size = stored();
        static sigslots::GlobalSlot<void> slots[capacity];
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( func == slots[i].global_function ) {
                return &(slots[i]);
            }
        }
        if ( size < capacity ) {
            slots[size] = sigslots::GlobalSlot<void>(func);
            bool inc = true;
            stored(inc); // increment the number of stored slots variable
            return &(slots[size]);
        } else {
            return NULL;
        }
    }
};


} // namespace lite
} // namespace ecl

#endif /* ECL_SIGSLOTS_LITE_MANAGERS_HPP_ */