Program Listing for File managers.hpp

Return to documentation for file (include/ecl/sigslots_lite/managers.hpp)

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

#ifndef ECL_SIGSLOTS_LITE_MANAGERS_HPP_
#define ECL_SIGSLOTS_LITE_MANAGERS_HPP_

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

#include <array>

#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;
};

template <typename Data, typename GlobalClass>
class GlobalSlotsBase {
public:
    virtual unsigned int stored() const { return 0; }
    virtual unsigned int capacity() const { return 0; }
    virtual sigslots::GlobalSlot<Data>* addSlot( void (*function)(Data) ) = 0;
};

template <typename GlobalClass>
class GlobalSlotsBase<void, GlobalClass> {
public:
    virtual unsigned int stored() const { return 0; }
    virtual unsigned int capacity() const { return 0; }
    virtual sigslots::GlobalSlot<void>* addSlot( void (*function)() ) = 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 GlobalClass, unsigned int Capacity = 1>
class GlobalSlots : public sigslots::GlobalSlotsBase<Data, GlobalClass> {
public:
    /*********************
    ** Friends
    **********************/
    // allow connect to use addSlot
    template <typename Data_, unsigned int Capacity_, typename GlobalClass_>
    friend sigslots::Error connect(Signal<Data_,Capacity_> &signal, void(*function)(Data_), GlobalClass_ &g);

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

    // needs access to capacity()
    template <typename Data_, typename GlobalClass_>
    friend unsigned int global_slots_capacity();

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

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

    sigslots::GlobalSlot<Data>* addSlot(void (*function)(Data)) {
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( function == slots[i].global_function ) {
                return &(slots[i]);
            }
        }
        if ( size < Capacity ) {
            slots[size] = sigslots::GlobalSlot<Data>(function);
            ++size;
            return &(slots[size-1]);
        } else {
            return NULL;
        }
    }

    unsigned int size;
    sigslots::GlobalSlot<Data> slots[Capacity];
};

/*****************************************************************************
** 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 GlobalClass, unsigned int Capacity>
class GlobalSlots<void, GlobalClass, Capacity> : public sigslots::GlobalSlotsBase<void, GlobalClass> {
public:
    /*********************
    ** Friends
    **********************/
    // allow connect to use addSlot
    template <unsigned int Capacity_, typename GlobalClass_>
    friend sigslots::Error connect(Signal<void,Capacity_> &signal, void(*function)(void), GlobalClass_ &g);

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

    // needs access to capacity()
    template <typename Data_, typename GlobalClass_>
    friend unsigned int global_slots_capacity();

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

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

    sigslots::GlobalSlot<void>* addSlot(void (*function)()) {
        for ( unsigned int i = 0; i < size; ++i ) {
            if ( function == slots[i].global_function ) {
                return &(slots[i]);
            }
        }
        if ( size < Capacity ) {
            slots[size] = sigslots::GlobalSlot<void>(function);
            ++size;
            return &(slots[size-1]);
        } else {
            return NULL;
        }
    }

    unsigned int size;
    sigslots::GlobalSlot<void> slots[Capacity];
};


class Joe {
public:
    static inline void addSlot() {
        // static std::array<float, GlobalSlots<void>::capacity> dods;
        static std::array<float, 5> dods;
        dods[0] = 3.0;
        // std::cout << "Capacity: " << GlobalSlots<void>::capacity << std::endl;
        std::cout << dods[0] << std::endl;
    }
};


//template <typename Data, unsigned int Capacity>
//struct GlobalManager : public GlobalSlots<Data, GlobalManager, Capacity> {};

// template <typename Data, unsigned int Capacity = 1>
// const GlobalManager<Data>& global_manager() {
//     static GlobalManager<Data> god{};
//     return god;
// }

//template <>
//const GlobalManager<void>& global_manager() {
//    static GlobalManager<void> god{};
//    return god;
//}


} // namespace lite
} // namespace ecl

#endif /* ECL_SIGSLOTS_LITE_MANAGERS_HPP_ */