Skip to content
This repository
tree: a76b1c4915
Fetching contributors…

Cannot retrieve contributors at this time

file 114 lines (84 sloc) 2.507 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
#ifndef _XSCRIPT_COMPONENT_H_
#define _XSCRIPT_COMPONENT_H_

#include <string>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/checked_delete.hpp>
#include "xscript/resource_holder.h"

namespace xscript {

class Loader;
class Config;


template<typename Type>
class ComponentRegisterer {
public:
    ComponentRegisterer(Type *var);
};


class ComponentBase : private boost::noncopyable {
public:
    ComponentBase();
    virtual ~ComponentBase();

    inline boost::shared_ptr<Loader> loader() const {
        return loader_;
    }

    virtual void init(const Config *config) {
        (void)config;
    }

private:
    boost::shared_ptr<Loader> loader_;
};


template<typename Type>
class Component : public ComponentBase {
public:
    static Type* instance();

    struct ResourceTraits {
        static Type* const DEFAULT_VALUE;
        static void destroy(Type * ptr);
    };

    typedef ResourceHolder<Type*, ResourceTraits> Holder;

private:
    static void attachImpl(Holder helper);
    friend class ComponentRegisterer<Type>;

private:
    static Holder holder_;

    static Type* createImpl();

};


/**
* Implementation of ResourceHolderTraits used in ComponentHolder
*/
template<typename Type>
void Component<Type>::ResourceTraits::destroy(Type *component) {
    // Acquire loader to avoid premature unload of shared library.
    boost::shared_ptr<Loader> loader = component->loader();
    boost::checked_delete(component);
};

template<typename Type>
Type* const Component<Type>::ResourceTraits::DEFAULT_VALUE = static_cast<Type*>(NULL);

template<typename Type>
typename Component<Type>::Holder
Component<Type>::holder_(Component<Type>::createImpl());

template<typename Type> inline Type*
Component<Type>::instance() {
    assert(Holder::Traits::DEFAULT_VALUE != holder_.get());
    return holder_.get();
}

template<typename Type> inline void
Component<Type>::attachImpl(typename Component<Type>::Holder holder) {
    assert(Holder::Traits::DEFAULT_VALUE != holder.get());
    holder_ = holder;
}

template<typename Type>
ComponentRegisterer<Type>::ComponentRegisterer(Type *var) {
    Component<Type>::attachImpl(typename Component<Type>::Holder(var));
}

#define REGISTER_COMPONENT(TYPE) \
template<> \
TYPE * Component<TYPE>::createImpl() { \
return new TYPE(); \
}


#define REGISTER_COMPONENT2(TYPE, IMPL) \
template<> \
TYPE * Component<TYPE>::createImpl() { \
return new IMPL(); \
}

} // namespace xscript

#endif // _XSCRIPT_COMPONENT_H_
Something went wrong with that request. Please try again.