메시지 enum에 따른 message 콜백 함수 자동생성
일단 message에 대한 기본 type과 각 message을 구분하기 위한 enum이 있다.
struct message_base_t {};
enum message_enum {
message1,
message2,
message3,
message_count,
};
message과 enum 값을 쉽게 연결하기 위해 중간 층을 도입한다.
template <int code>
struct message_enum_t : public message_base_t {
enum {
enum_value = code
};
};
이제 message을 만든다.
struct message_struct_1 : public message_enum_t<message1> {};
struct message_struct_2 : public message_enum_t<message2> {};
struct message_struct_3 : public message_enum_t<message3> {};
기본적인 handler는 다음과 같이 단순하게 정의할 수 있다.
typedef void (*base_handler_t)(const message_base_t&);
dispatch를 위해 handler에 대한 table을 하나 만들어둔다.
typedef std::array<base_handler_t, message_count> handler_table_t;
static handler_table_t _handler_table_t;
일단 등록된 handler가 없어도 서버 동작에 문제가 없도록 하기 위해 빈 handler로 초기화를 해준다.
static void empty_handler(const message_base_t&) {}
static struct handler_init_t {
handler_init_t() {
for (int index = 0; index < message_count; ++index)
_handler_table_t[index] = empty_handler;
}
} _init;
각 handler를 쉽게 등록하기 위한 register를 만든다.
struct handler_register_t {
handler_register_t(int index, base_handler_t handler) {
_handler_table_t[index] = handler;
}
};
handler의 귀찮은 함수 선언, casting, register 등록 부분의 코드를 생성해줄 macro를 정의한다.
#define HANDLER(messageName) \
static void handler_##messageName(const messageName& msg); \
static void _base_##messageName##_handler(const message_base_t& msg) { \
handler_##messageName(static_cast<const messageName&>(msg)); \
} \
static handler_register_t _register_##messageName( \
messageName::enum_value, _base_##messageName##_handler); \
static void handler_##messageName(const messageName& msg)
위 macro를 사용해서 handler를 구현한다.
HANDLER(message_struct_1) {
std::cout << typeid(msg).name() << std::endl;
}
dispatch를 구현한다.
template <typename _msgTy>
inline void dispatch_message(const _msgTy& msg) {
_handler_table_t[_msgTy::enum_value](msg);
}
모든 구현이 끝났으니 사용하면 된다.
void main() {
dispatch_message(message_struct_1());
return 0;
}
Loading script...