// // mp::multiplex // // Copyright (C) 2008 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef MP_MULTIPLEX_H__ #define MP_MULTIPLEX_H__ #include "mp/event.h" #include "mp/source.h" #include "mp/zone.h" #include namespace mp { namespace multiplex { class handler; class manager { public: static void initialize(); static void destroy(); public: template static void add(int fd); MP_ARGS_BEGIN template static void add(int fd, MP_ARGS_PARAMS); MP_ARGS_END static handler& data(int fd); static void send_data(int fd, const char* buf, size_t len); static int run(); static void end(); static bool is_end(); private: template void add_impl(int fd); MP_ARGS_BEGIN template void add_impl(int fd, MP_ARGS_PARAMS); MP_ARGS_END handler& data_impl(int fd); void send_data_impl(int fd, const char* buf, size_t len); //void send_message_impl(int fd, callback_message* msg); int run_impl(); private: class cb_t { public: cb_t(handler* h, short ev); ~cb_t(); public: short event() const; void event(short ev); handler& get(); private: handler* m_handler; short m_event; private: char* m_wbuffer; size_t m_allocated; size_t m_used; public: void append_buffer(const char* buf, size_t len); void consume_buffer(size_t len); const char* wbuffer() const; size_t length() const; bool empty() const; }; typedef event ev_t; ev_t m_ev; zone m_zone; private: typedef std::vector wswitch_ctx_t; wswitch_ctx_t m_wswitch_ctx; private: void try_read(cb_t& cb); bool try_write(cb_t& cb); void rswitch(cb_t& cb); void wswitch(cb_t& cb); void close_connection(cb_t& cb); private: volatile sig_atomic_t m_end_flag; private: static std::auto_ptr s_instance; static manager& instance() { return *s_instance; } public: manager(); ~manager(); }; class handler { public: handler(int fd); virtual ~handler(); public: virtual void read_event() = 0; virtual void connected() {} public: int fd() const { return m_fd; } void send_data(const void* buf, size_t len) { return manager::send_data(m_fd, buf, len); } private: int m_fd; private: handler(); handler(const handler&); }; inline void initialize() { manager::initialize(); } inline void destroy() { manager::destroy(); } inline int run() { return manager::run(); } inline void end() { manager::end(); } inline bool is_end() { return manager::is_end(); } template inline void add(int fd) { manager::add(fd); } MP_ARGS_BEGIN template inline void add(int fd, MP_ARGS_PARAMS) { manager::add(fd, MP_ARGS_FUNC); } MP_ARGS_END inline void send_data(int fd, const void* buf, size_t len) { manager::send_data(fd, buf, len); } template inline void submit(R (*func)(void*), T* obj) { (*func)(obj); } MP_ARGS_BEGIN template inline void submit(R (*func)(void*, MP_ARGS_PARAMS), T* obj, MP_ARGS_PARAMS) { (*func)(obj, MP_ARGS_FUNC); } MP_ARGS_END } // namespace multiplex } // namespace mp #include "mp/multiplex_impl.h" #include "mp/multiplex/listen.h" #include "mp/multiplex/timer.h" #endif /* mp/multiplex.h */