Permalink
Browse files

update

Signed-off-by: yayanyang <yayanyang@gmail.com>
  • Loading branch information...
1 parent 0e1e8d7 commit bec66878dabe558894974a273d547dfb40e72baa yayanyang committed Sep 29, 2012
View
BIN .DS_Store
Binary file not shown.
View
285 io/abi.cpp
@@ -0,0 +1,285 @@
+#include <lemon/io/io_service.hpp>
+
+using namespace lemon::io::impl;
+
+LEMON_IO_API
+ void
+ LemonCloseIO(
+ __lemon_free LemonIO io)
+{
+ reinterpret_cast<object*>(io)->release();
+}
+
+LEMON_IO_API
+ LemonIOService
+ LemonCreateIOService(
+ __lemon_inout LemonErrorInfo * errorCode)
+{
+ try
+ {
+ return reinterpret_cast<LemonIOService>(new io_service());
+ }
+ catch(const lemon::error_info & e)
+ {
+ *errorCode = e;
+
+ return LEMON_HANDLE_NULL_VALUE;
+ }
+}
+
+LEMON_IO_API
+ void LemonCloseIOService(
+ __lemon_free LemonIOService service)
+{
+ delete reinterpret_cast<io_service*>(service);
+}
+
+LEMON_IO_API
+ LemonIO
+ LemonSock(
+ __lemon_in int af,
+ __lemon_in int type,
+ __lemon_in int protocol,
+ __lemon_in LemonIOService service,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ try
+ {
+ io_service::socket_type * socket = new(reinterpret_cast<io_service*>(service)) io_service::socket_type();
+
+ socket->create(af,type,protocol,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) { delete socket; socket = LEMON_HANDLE_NULL_VALUE; }
+
+ return reinterpret_cast<LemonIO>(socket);
+ }
+ catch(const lemon::error_info & e)
+ {
+ *errorCode = e;
+
+ return LEMON_HANDLE_NULL_VALUE;
+ }
+}
+
+LEMON_IO_API
+ void LemonBind(
+ __lemon_in LemonIO sock,
+ __lemon_in const struct sockaddr * name,
+ __lemon_in socklen_t nameLength,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ reinterpret_cast<io_service::socket_type*>(sock)->bind(name,nameLength,errorCode);
+}
+
+LEMON_IO_API
+ void LemonShutdown(
+ __lemon_in __lemon_in LemonIO sock,
+ __lemon_in __lemon_in int how,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ reinterpret_cast<io_service::socket_type*>(sock)->shutdown(how,errorCode);
+}
+
+LEMON_IO_API
+ void LemonGetSockName(
+ __lemon_in LemonIO sock,
+ __lemon_inout struct sockaddr * name,
+ __lemon_inout socklen_t* bufferSize,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ reinterpret_cast<io_service::socket_type*>(sock)->sockname(name,bufferSize,errorCode);
+}
+
+LEMON_IO_API
+ size_t
+ LemonSend(
+ __lemon_in LemonIO socket,
+ __lemon_in const lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ return reinterpret_cast<io_service::socket_type*>(socket)->send(buffer,bufferSize,flags,errorCode);
+}
+
+LEMON_IO_API
+ size_t
+ LemonRecv(
+ __lemon_in LemonIO socket,
+ __lemon_in lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ return reinterpret_cast<io_service::socket_type*>(socket)->recv(buffer,bufferSize,flags,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonConnect(
+ __lemon_in LemonIO socket,
+ __lemon_in const struct sockaddr * addr,
+ __lemon_in socklen_t addrlen,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ reinterpret_cast<io_service::socket_type*>(socket)->connect(addr,addrlen,errorCode);
+}
+
+LEMON_IO_API
+ void LemonListen(
+ __lemon_in LemonIO socket,
+ __lemon_in int backlog,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ reinterpret_cast<io_service::socket_type*>(socket)->listen(backlog,errorCode);
+}
+
+
+LEMON_IO_API
+ LemonIO LemonAccept(
+ __lemon_in LemonIO socket,
+ __lemon_inout struct sockaddr * addr,
+ __lemon_inout socklen_t * addrlen,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ try
+ {
+ io_service::socket_type * peer = new(reinterpret_cast<io_service::socket_type*>(socket)->io_service()) io_service::socket_type();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->accept(peer,addr,addrlen,errorCode);
+
+ return reinterpret_cast<LemonIO>(peer);
+ }
+ catch(const lemon::error_info &e)
+ {
+ *errorCode = e;
+
+ return LEMON_HANDLE_NULL_VALUE;
+ }
+}
+
+LEMON_IO_API
+ size_t
+ LemonSendTo(
+ __lemon_in LemonIO socket,
+ __lemon_in const lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in const struct sockaddr * address,
+ __lemon_in socklen_t addressSize,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ return reinterpret_cast<io_service::socket_type*>(socket)->sendto(buffer,bufferSize,flags,address,addressSize,errorCode);
+}
+
+LEMON_IO_API
+ size_t
+ LemonReceiveFrom(
+ __lemon_in LemonIO socket,
+ __lemon_in lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in struct sockaddr * address,
+ __lemon_in socklen_t *addressSize,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ return reinterpret_cast<io_service::socket_type*>(socket)->recvfrom(buffer,bufferSize,flags,address,addressSize,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncSend(
+ __lemon_in LemonIO socket,
+ __lemon_in const lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in LemonIOCallback callback,
+ __lemon_in void *userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_send(service,buffer,bufferSize,flags,callback,userData,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncRecv(
+ __lemon_in LemonIO socket,
+ __lemon_in lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in LemonIOCallback callback,
+ __lemon_in void *userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_recv(service,buffer,bufferSize,flags,callback,userData,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncConnect(
+ __lemon_in LemonIO socket,
+ __lemon_in const struct sockaddr * addr,
+ __lemon_in socklen_t addrlen,
+ __lemon_in LemonIOCallback callback,
+ __lemon_in void * userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_connect(service,addr,addrlen,callback,userData,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncAccept(
+ __lemon_in LemonIO socket,
+ __lemon_inout struct sockaddr * addr,
+ __lemon_inout socklen_t * addrlen,
+ __lemon_in LemonAcceptCallback callback,
+ __lemon_in void * userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_accept(service,addr,addrlen,callback,userData,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncSendTo(
+ __lemon_in LemonIO socket,
+ __lemon_in const lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in const struct sockaddr * address,
+ __lemon_in socklen_t addressSize,
+ __lemon_in LemonIOCallback callback,
+ __lemon_in void *userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_sendto(service,buffer,bufferSize,flags,address,addressSize,callback,userData,errorCode);
+}
+
+LEMON_IO_API
+ void
+ LemonAsyncReceiveFrom(
+ __lemon_in LemonIO socket,
+ __lemon_in lemon_byte_t * buffer __lemon_buffer(bufferSize),
+ __lemon_in size_t bufferSize,
+ __lemon_in int flags,
+ __lemon_in struct sockaddr * address,
+ __lemon_in socklen_t *addressSize,
+ __lemon_in LemonIOCallback callback,
+ __lemon_in void *userData,
+ __lemon_inout LemonErrorInfo *errorCode)
+{
+ io_service * service = reinterpret_cast<io_service::socket_type*>(socket)->io_service();
+
+ reinterpret_cast<io_service::socket_type*>(socket)->async_recvfrom(service,buffer,bufferSize,flags,address,addressSize,callback,userData,errorCode);
+}
View
4 io/allocator.hpp
@@ -31,9 +31,9 @@ namespace lemon{namespace io{namespace impl{
{
public:
- typedef typename mpl::deref<B> current_type;
+ typedef typename mpl::deref<B>::type current_type;
- typedef struct {current_type val;void * context;} block_type;
+ typedef struct {current_type val;void * context;} block_type;
typedef memory::fixed::allocator<sizeof(block_type)> allocator_type;
View
28 io/basic_io_object.hpp
@@ -15,30 +15,48 @@
namespace lemon{namespace io{namespace impl{
+ struct object
+ {
+ virtual void release() = 0;
+
+ protected:
+
+ object(){}
+
+ ~object(){}
+ };
+
template<typename IOService, class ObjectService>
- class basic_io_object : public ObjectService, private lemon::nocopyable
+ class basic_io_object : public ObjectService , public object
{
public:
typedef ObjectService object_service;
typedef IOService io_service_type;
- typedef basic_io_object<io_service_type,object_service> self_type;
-
- typedef struct {object_service unused; io_service_type* service;} block_type;
+ typedef basic_io_object<io_service_type,object_service> self_type;
public:
io_service_type * io_service()
{
+ typedef struct {self_type unused; io_service_type* service;} block_type;
+
return reinterpret_cast<block_type*>(this)->service;
}
+ void release()
+ {
+ delete this;
+ }
+
public:
static void * operator new (size_t blocksize,io_service_type * service)
{
+ typedef struct {self_type unused; io_service_type* service;} block_type;
+
assert(blocksize == sizeof(self_type));
block_type* block = (block_type*)service->allocator().template alloc<self_type>();
@@ -50,6 +68,8 @@ namespace lemon{namespace io{namespace impl{
static void operator delete(void * block,size_t blocksize)
{
+ typedef struct {self_type unused; io_service_type* service;} block_type;
+
assert(blocksize == sizeof(self_type));
reinterpret_cast<block_type*>(block)->service->allocator().template free<self_type>(block);
View
40 io/basic_io_service.hpp
@@ -1,40 +0,0 @@
-/**
-*
-* @file basic_io_service
-* @brief Copyright (C) 2012 yayanyang All Rights Reserved
-* @author yayanyang
-* @version 1.0.0.0
-* @date 2012/09/27
-*/
-#ifndef LEMON_IO_BASIC_IO_SERVICE_HPP
-#define LEMON_IO_BASIC_IO_SERVICE_HPP
-#include <lemon/io/abi.h>
-#include <lemonxx/sys/sys.hpp>
-#include <lemon/io/allocator.hpp>
-#include <lemonxx/utility/utility.hpp>
-#include <lemon/io/basic_socket.hpp>
-
-namespace lemon{namespace io{namespace impl{
-
- template<typename Impl> class basic_io_service : private lemon::nocopyable
- {
- public:
-
- typedef basic_io_service<Impl> self_type;
-
- typedef basic_io_object<self_type,typename Impl::socket_service> socket_type;
-
- typedef typename mpl::make_list<socket_type>::type io_object_list;
-
- typedef basic_allocator<io_object_list> allocator_type;
-
- allocator_type & allocator() { return _allocator; }
-
- private:
-
- allocator_type _allocator;
- };
-
-}}}
-#endif //LEMON_IO_BASIC_IO_SERVICE_HPP
-
View
143 io/basic_socket.hpp
@@ -9,18 +9,155 @@
#ifndef LEMON_IO_BASIC_SOCKET_HPP
#define LEMON_IO_BASIC_SOCKET_HPP
+#include <lemon/io/io.hpp>
#include <lemon/io/basic_io_object.hpp>
namespace lemon{namespace io{namespace impl{
- template<class T, class IOService> class basic_socket_service : private lemon::nocopyable
+ template<class SocketServiceImpl>
+ class basic_socket_service : protected SocketServiceImpl
{
public:
- typedef IOService io_service_type;
+
+ typedef SocketServiceImpl socket_service_impl;
- basic_socket_service(__lemon_native_socket handle) : _handle(handle) {}
+ typedef basic_socket_service<socket_service_impl> self_type;
+ void create(__lemon_native_socket native){ _handle = native; }
+ void create(int af, int type, int protocol, LemonErrorInfo * errorCode)
+ {
+ _handle = socket_service_impl::create(af, type, protocol, errorCode);
+ }
+
+ bool is_open() {return _handle != __lemon_invalid_socket; }
+
+ void bind(const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ socket_service_impl::bind(_handle, name, nameLength, errorCode);
+ }
+
+ void shutdown(int how, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ socket_service_impl::shutdown(_handle, how, errorCode);
+ }
+
+ void sockname(sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ socket_service_impl::sockname(_handle, name, namelength, errorCode);
+ }
+
+ size_t send(const byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ return socket_service_impl::send(_handle, buffer, bufferSize, flag, errorCode);
+ }
+
+ template<typename IOService>
+ void async_send( IOService * service, const byte_t * buffer, std::size_t bufferSize,
+ int flag, LemonIOCallback callback, void *userData, LemonErrorInfo * errorCode)
+ {
+ service->async_send(buffer,bufferSize,flag,callback,userData,errorCode);
+ }
+
+ size_t sendto(const byte_t * buffer, std::size_t bufferSize, int flag, const sockaddr * name, socklen_t nameLength,LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ return socket_service_impl::sendto(_handle, buffer, bufferSize, flag, name, nameLength, errorCode);
+ }
+
+ template<typename IOService>
+ void async_sendto(
+ IOService * service, const byte_t * buffer, std::size_t bufferSize,
+ int flag, const sockaddr * name, socklen_t nameLength,
+ LemonIOCallback callback, void *userData, LemonErrorInfo * errorCode)
+ {
+ service->async_sendto(buffer,bufferSize,flag,name,nameLength, callback,userData,errorCode);
+ }
+
+ size_t recv(byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ return socket_service_impl::recv(_handle, buffer, bufferSize, flag, errorCode);
+ }
+
+ template<typename IOService>
+ void async_recv( IOService * service, byte_t * buffer, std::size_t bufferSize,
+ int flag, LemonIOCallback callback, void *userData, LemonErrorInfo * errorCode)
+ {
+ service->async_recv(buffer,bufferSize,flag,callback,userData,errorCode);
+ }
+
+ size_t recvfrom(byte_t * buffer, std::size_t bufferSize, int flag, sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ return socket_service_impl::recvfrom(_handle, buffer, bufferSize, flag, name, namelength, errorCode);
+ }
+
+ template<typename IOService>
+ void async_recvfrom(
+ IOService * service, byte_t * buffer, std::size_t bufferSize,
+ int flag, sockaddr * name, socklen_t *nameLength,
+ LemonIOCallback callback, void *userData, LemonErrorInfo * errorCode)
+ {
+ service->async_recvfrom(buffer,bufferSize,flag,name, nameLength, callback,userData,errorCode);
+ }
+
+ void connect(const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ socket_service_impl::connect(_handle, name, nameLength, errorCode);
+ }
+
+ template<typename IOService>
+ void async_connect(IOService *service, const sockaddr * name, socklen_t nameLength,LemonIOCallback callback, void * userdata, LemonErrorInfo * errorCode)
+ {
+ service->async_connect(name,nameLength,callback, userdata, errorCode);
+ }
+
+ void listen(int backlog, LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ socket_service_impl::listen(_handle, backlog, errorCode);
+ }
+
+
+ void accept(self_type * peer,sockaddr * name, socklen_t * namelength,LemonErrorInfo * errorCode)
+ {
+ assert(is_open());
+
+ assert(!peer->is_open());
+
+ __lemon_native_socket newsocket = socket_service_impl::accept(_handle, name, namelength, errorCode);
+
+ if(LEMON_SUCCESS(*errorCode)) peer->create(newsocket);
+ }
+
+ template<typename IOService>
+ void async_accept(IOService * service, sockaddr * name, socklen_t * namelength, LemonAcceptCallback callback, void * userData, LemonErrorInfo * errorCode)
+ {
+ service->async_accept(name,namelength,callback,userData,errorCode);
+ }
+
+ basic_socket_service():_handle(__lemon_invalid_socket) {}
+
+ ~basic_socket_service() { if( is_open() ) socket_service_impl::close(_handle); }
+
+ public:
+
+ __lemon_native_socket handle() { return _handle; }
private:
View
1 io/configure.h.in
@@ -1,3 +1,4 @@
+#cmakedefine LEMON_IO_SELECT
#cmakedefine LEMON_IO_IOCP
#cmakedefine LEMON_IO_EPOLL
#cmakedefine LEMON_IO_KQUEUE
View
173 io/io.hpp
@@ -0,0 +1,173 @@
+/**
+ *
+ * @file io
+ * @brief Copyright (C) 2012 yayanyang All Rights Reserved
+ * @author yayanyang
+ * @version 1.0.0.0
+ * @date 2012/09/28
+ */
+#ifndef LEMON_IO_IO_HPP
+#define LEMON_IO_IO_HPP
+
+#include <cassert>
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemonxx/utility/utility.hpp>
+
+#ifdef WIN32
+# define __lemon_invalid_socket INVALID_SOCKET
+
+# define __lemon_socket_error SOCKET_ERROR
+
+# define LEMON_IO_SOCKET_ERROR(info) LEMON_WIN32_ERROR(info,WSAGetLastError())
+
+# define __LEMON_IO_NATIVE_ERROR(e) e
+
+# define __LEMON_IO_SOCKET_ERROR(e) WSA ## e
+
+# define __LEMON_IO_NETDB_ERROR(e) WSA ## e
+
+# define __LEMON_IO_GETADDRINFO_ERROR(e) WSA ## e
+
+# define __LEMON_IO_WIN_OR_POSIX(e_win, e_posix) e_win
+#else
+# include <fcntl.h>
+
+# include <unistd.h>
+
+# include <sys/select.h>
+
+# define __lemon_invalid_socket -1
+
+# define __lemon_socket_error -1
+
+# define closesocket ::close
+
+# define LEMON_IO_SOCKET_ERROR(info) LEMON_POSIX_ERROR(info,errno)
+
+# define __LEMON_IO_NATIVE_ERROR(e) e
+
+# define __LEMON_IO_SOCKET_ERROR(e) e
+
+# define __LEMON_IO_NETDB_ERROR(e) e
+
+# define __LEMON_IO_GETADDRINFO_ERROR(e) e
+
+# define __LEMON_IO_WIN_OR_POSIX(e_win, e_posix) e_posix
+#endif //WIN32
+
+namespace lemon{namespace io{namespace impl{enum{
+
+ /// Permission denied.
+ access_denied = __LEMON_IO_SOCKET_ERROR(EACCES),
+
+ /// Address family not supported by protocol.
+ address_family_not_supported = __LEMON_IO_SOCKET_ERROR(EAFNOSUPPORT),
+
+ /// Address already in use.
+ address_in_use = __LEMON_IO_SOCKET_ERROR(EADDRINUSE),
+
+ /// Transport endpoint is already connected.
+ already_connected = __LEMON_IO_SOCKET_ERROR(EISCONN),
+
+ /// Operation already in progress.
+ already_started = __LEMON_IO_SOCKET_ERROR(EALREADY),
+
+ /// Broken pipe.
+ broken_pipe = __LEMON_IO_WIN_OR_POSIX(
+ __LEMON_IO_NATIVE_ERROR(ERROR_BROKEN_PIPE),
+ __LEMON_IO_NATIVE_ERROR(EPIPE)),
+
+ /// A connection has been aborted.
+ connection_aborted = __LEMON_IO_SOCKET_ERROR(ECONNABORTED),
+
+ /// Connection refused.
+ connection_refused = __LEMON_IO_SOCKET_ERROR(ECONNREFUSED),
+
+ /// Connection reset by peer.
+ connection_reset = __LEMON_IO_SOCKET_ERROR(ECONNRESET),
+
+ /// Bad file descriptor.
+ bad_descriptor = __LEMON_IO_SOCKET_ERROR(EBADF),
+
+ /// Bad address.
+ fault = __LEMON_IO_SOCKET_ERROR(EFAULT),
+
+ /// No route to host.
+ host_unreachable = __LEMON_IO_SOCKET_ERROR(EHOSTUNREACH),
+
+ /// Operation now in progress.
+ in_progress = __LEMON_IO_SOCKET_ERROR(EINPROGRESS),
+
+ /// Interrupted system call.
+ interrupted = __LEMON_IO_SOCKET_ERROR(EINTR),
+
+ /// Invalid argument.
+ invalid_argument = __LEMON_IO_SOCKET_ERROR(EINVAL),
+
+ /// Message too long.
+ message_size = __LEMON_IO_SOCKET_ERROR(EMSGSIZE),
+
+ /// The name was too long.
+ name_too_long = __LEMON_IO_SOCKET_ERROR(ENAMETOOLONG),
+
+ /// Network is down.
+ network_down = __LEMON_IO_SOCKET_ERROR(ENETDOWN),
+
+ /// Network dropped connection on reset.
+ network_reset = __LEMON_IO_SOCKET_ERROR(ENETRESET),
+
+ /// Network is unreachable.
+ network_unreachable = __LEMON_IO_SOCKET_ERROR(ENETUNREACH),
+
+ /// Too many open files.
+ no_descriptors = __LEMON_IO_SOCKET_ERROR(EMFILE),
+
+ /// No buffer space available.
+ no_buffer_space = __LEMON_IO_SOCKET_ERROR(ENOBUFS),
+
+ /// Cannot allocate memory.
+ no_memory = __LEMON_IO_WIN_OR_POSIX(
+ __LEMON_IO_NATIVE_ERROR(ERROR_OUTOFMEMORY),
+ __LEMON_IO_NATIVE_ERROR(ENOMEM)),
+
+ /// Operation not permitted.
+ no_permission = __LEMON_IO_WIN_OR_POSIX(
+ __LEMON_IO_NATIVE_ERROR(ERROR_ACCESS_DENIED),
+ __LEMON_IO_NATIVE_ERROR(EPERM)),
+
+ /// Protocol not available.
+ no_protocol_option = __LEMON_IO_SOCKET_ERROR(ENOPROTOOPT),
+
+ /// Transport endpoint is not connected.
+ not_connected = __LEMON_IO_SOCKET_ERROR(ENOTCONN),
+
+ /// Socket operation on non-socket.
+ not_socket = __LEMON_IO_SOCKET_ERROR(ENOTSOCK),
+
+ /// Operation cancelled.
+ operation_aborted = __LEMON_IO_WIN_OR_POSIX(
+ __LEMON_IO_NATIVE_ERROR(ERROR_OPERATION_ABORTED),
+ __LEMON_IO_NATIVE_ERROR(ECANCELED)),
+
+ /// Operation not supported.
+ operation_not_supported = __LEMON_IO_SOCKET_ERROR(EOPNOTSUPP),
+
+ /// Cannot send after transport endpoint shutdown.
+ shut_down = __LEMON_IO_SOCKET_ERROR(ESHUTDOWN),
+
+ /// Connection timed out.
+ timed_out = __LEMON_IO_SOCKET_ERROR(ETIMEDOUT),
+
+ /// Resource temporarily unavailable.
+ try_again = __LEMON_IO_WIN_OR_POSIX(
+ __LEMON_IO_NATIVE_ERROR(ERROR_RETRY),
+ __LEMON_IO_NATIVE_ERROR(EAGAIN)),
+
+ /// The socket is marked non-blocking and the requested operation would block.
+ would_block = __LEMON_IO_SOCKET_ERROR(EWOULDBLOCK)
+
+};}}}
+
+#endif // LEMON_IO_IO_HPP
+
View
54 io/io_service.hpp
@@ -0,0 +1,54 @@
+/**
+*
+* @file basic_io_service
+* @brief Copyright (C) 2012 yayanyang All Rights Reserved
+* @author yayanyang
+* @version 1.0.0.0
+* @date 2012/09/27
+*/
+#ifndef LEMON_IO_IO_SERVICE_HPP
+#define LEMON_IO_IO_SERVICE_HPP
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemon/io/allocator.hpp>
+#include <lemonxx/utility/utility.hpp>
+
+#include <lemon/io/basic_socket.hpp>
+#include <lemon/io/select_reactor.hpp>
+#include <lemon/io/socket_reactor.hpp>
+#include <lemon/io/reactor_io_service.hpp>
+
+namespace lemon{namespace io{namespace impl{
+
+#ifndef LEMON_IO_IOCP
+ typedef basic_socket_service<socket_reactor> socket_service;
+#else
+ typedef basic_socket_service<socket_iocp> socket_service;
+#endif //LEMON_IO_SELECT
+
+ class io_service
+#ifdef LEMON_IO_SELECT
+ : public reactor_io_service<io_service,select_reactor>
+#else
+
+#endif
+ {
+ public:
+
+ typedef basic_io_object<io_service,socket_service> socket_type;
+
+ typedef mpl::make_list<socket_type>::type io_object_list;
+
+ typedef basic_allocator<io_object_list> allocator_type;
+
+ allocator_type & allocator() { return _allocator; }
+
+ private:
+
+ allocator_type _allocator;
+ };
+
+}}}
+
+#endif //LEMON_IO_IO_SERVICE_HPP
+
View
115 io/reactor_io_service.hpp
@@ -0,0 +1,115 @@
+/**
+ *
+ * @file reactor_io_service
+ * @brief Copyright (C) 2012 yayanyang All Rights Reserved
+ * @author yayanyang
+ * @version 1.0.0.0
+ * @date 2012/09/29
+ */
+#ifndef LEMON_IO_REACTOR_IO_SERVICE_HPP
+#define LEMON_IO_REACTOR_IO_SERVICE_HPP
+
+#include <cassert>
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemon/io/allocator.hpp>
+#include <lemonxx/utility/utility.hpp>
+#include <lemon/io/reactor_options.hpp>
+#include <lemon/io/basic_io_object.hpp>
+
+namespace lemon{namespace io{namespace impl{
+
+ template<typename T,typename Poll>
+ class reactor_io_service : private lemon::nocopyable
+ {
+ public:
+
+ typedef Poll poll_device;
+
+ typedef reactor_io_service<T,poll_device> self_type;
+
+ typedef basic_reactor_connect_option<self_type> reactor_connect_option;
+
+ typedef typename mpl::make_list<reactor_connect_option>::type reactor_options;
+
+ typedef basic_allocator<reactor_options> allocator_type;
+
+ void async_accept(sockaddr * /*name*/, socklen_t * /*namelength*/, LemonAcceptCallback /*callback*/, void * /*userData*/, LemonErrorInfo * /*errorCode*/)
+ {
+ new(this) reactor_connect_option();
+ }
+
+ void async_connect(const sockaddr * /*name*/, socklen_t /*nameLength*/,LemonIOCallback /*callback*/, void * /*userdata*/, LemonErrorInfo * /*errorCode*/)
+ {
+
+ }
+
+ void async_recvfrom
+ (
+
+ byte_t * /*buffer*/, std::size_t /*bufferSize*/,
+
+ int /*flag*/, sockaddr * /*name*/, socklen_t * /*nameLength*/,
+
+ LemonIOCallback /*callback*/, void * /*userData*/,
+
+ LemonErrorInfo * /*errorCode*/
+ )
+ {
+
+ }
+
+ void async_recv
+ (
+ byte_t * /*buffer*/, std::size_t /*bufferSize*/,
+
+ int /*flag*/, LemonIOCallback /*callback*/, void * /*userData*/,
+
+ LemonErrorInfo * /*errorCode*/
+ )
+ {
+
+ }
+
+ void async_sendto
+ (
+
+ const byte_t * /*buffer*/, std::size_t /*bufferSize*/,
+
+ int /*flag*/, const sockaddr * /*name*/, socklen_t /*nameLength*/,
+
+ LemonIOCallback /*callback*/, void * /*userData*/,
+
+ LemonErrorInfo * /*errorCode*/
+ )
+ {
+
+ }
+
+ void async_send
+ (
+ const byte_t * /*buffer*/, std::size_t /*bufferSize*/,
+
+ int /*flag*/, LemonIOCallback /*callback*/, void * /*userData*/,
+
+ LemonErrorInfo * /*errorCode*/
+ )
+ {
+
+ }
+
+ public:
+
+ allocator_type & reactor_option_allocator() { return _reactor_option_allocator; }
+
+ private:
+
+ poll_device _poll;
+
+ allocator_type _reactor_option_allocator;
+ };
+
+}}}
+
+#endif // LEMON_IO_REACTOR_IO_SERVICE_HPP
+
View
0 io/reactor_options.cpp
No changes.
View
75 io/reactor_options.hpp
@@ -0,0 +1,75 @@
+/**
+ *
+ * @file reactor_options
+ * @brief Copyright (C) 2012 yayanyang All Rights Reserved
+ * @author yayanyang
+ * @version 1.0.0.0
+ * @date 2012/09/29
+ */
+#ifndef LEMON_IO_REACTOR_OPTIONS_HPP
+#define LEMON_IO_REACTOR_OPTIONS_HPP
+
+#include <cassert>
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemonxx/utility/utility.hpp>
+
+namespace lemon{namespace io{namespace impl{
+
+ struct reactor_option : private nocopyable
+ {
+ virtual void do_perform() = 0;
+
+ virtual void release() = 0;
+
+ protected:
+
+ ~reactor_option(){}
+ };
+
+ template<typename T,typename IOService> struct basic_reactor_option : public reactor_option
+ {
+ typedef T self_type;
+
+ typedef IOService io_service_type;
+
+ void release(){ delete this; }
+
+ static void * operator new (size_t blocksize,io_service_type * service)
+ {
+ typedef struct {self_type unused; io_service_type* service;} block_type;
+
+ assert(blocksize == sizeof(self_type));
+
+ block_type* block = (block_type*)service->reactor_option_allocator().template alloc<self_type>();
+
+ block->service = service;
+
+ return block;
+ }
+
+ static void operator delete(void * block,size_t blocksize)
+ {
+ typedef struct {self_type unused; io_service_type* service;} block_type;
+
+ assert(blocksize == sizeof(self_type));
+
+ reinterpret_cast<block_type*>(block)->service->reactor_option_allocator().template free<self_type>(block);
+ }
+
+ static void operator delete(void * block,io_service_type * service)
+ {
+ service->reactor_option_allocator().template free<self_type>(block);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ template<typename IOService>
+ struct basic_reactor_connect_option : public basic_reactor_option<basic_reactor_connect_option<IOService>,IOService>
+ {
+ void do_perform() {}
+ };
+}}}
+
+#endif // LEMON_IO_REACTOR_OPTIONS_HPP
+
View
0 io/select_reactor.cpp
No changes.
View
33 io/select_reactor.hpp
@@ -0,0 +1,33 @@
+/**
+ *
+ * @file select_reactor
+ * @brief Copyright (C) 2012 yayanyang All Rights Reserved
+ * @author yayanyang
+ * @version 1.0.0.0
+ * @date 2012/09/29
+ */
+#ifndef LEMON_IO_SELECT_REACTOR_HPP
+#define LEMON_IO_SELECT_REACTOR_HPP
+
+#include <cassert>
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemonxx/utility/utility.hpp>
+
+#ifdef LEMON_IO_SELECT
+
+namespace lemon{namespace io{namespace impl{
+
+ class select_reactor : private nocopyable
+ {
+ public:
+ select_reactor(){}
+
+ ~select_reactor(){}
+ };
+}}}
+
+#endif //LEMON_IO_SELECT
+
+#endif // LEMON_IO_SELECT_REACTOR_HPP
+
View
237 io/socket_reactor.cpp
@@ -0,0 +1,237 @@
+#include <errno.h>
+#include <lemon/io/socket_reactor.hpp>
+
+#ifndef LEMON_IO_IOCP
+
+namespace lemon{namespace io{namespace impl{
+
+ inline void __lemon_noblocking_socket(__lemon_native_socket handle, LemonErrorInfo * errorCode)
+ {
+#ifdef WIN32
+ u_long mode = 1;
+
+ if(__lemon_socket_error == ioctlsocket(handle,FIONBIO, &mode)) LEMON_WIN32_ERROR(*errorCode,WSAGetLastError());
+#else
+ int flag = fcntl(handle,F_GETFL,0);
+
+ if(-1 == flag) { LEMON_POSIX_ERROR(errorCode,errno); return; }
+
+ if( -1 == fcntl(handle,F_SETFL,flag | O_NONBLOCK) ) LEMON_POSIX_ERROR(*errorCode,errno);
+#endif //WIN32
+ }
+
+ inline void __lemon_poll_write(__lemon_native_socket handle, LemonErrorInfo * errorCode)
+ {
+ assert(__lemon_invalid_socket != handle);
+
+ LEMON_RESET_ERRORINFO(*errorCode);
+
+ fd_set fds;
+
+ FD_ZERO(&fds);
+
+ FD_SET(handle, &fds);
+
+ if(__lemon_socket_error == ::select(1,0,&fds,0,NULL)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ inline void __lemon_poll_read(__lemon_native_socket handle, LemonErrorInfo * errorCode)
+ {
+ assert(__lemon_invalid_socket != handle);
+
+ LEMON_RESET_ERRORINFO(*errorCode);
+
+ fd_set fds;
+
+ FD_ZERO(&fds);
+
+ FD_SET(handle, &fds);
+
+ if(__lemon_socket_error == ::select(1,&fds,0,0,NULL)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ inline void __lemon_poll_connect(__lemon_native_socket handle, LemonErrorInfo * errorCode)
+ {
+ assert(__lemon_invalid_socket != handle);
+
+ LEMON_RESET_ERRORINFO(*errorCode);
+
+ fd_set fds;
+
+ FD_ZERO(&fds);
+
+ FD_SET(handle, &fds);
+
+ fd_set except_fds;
+
+ FD_ZERO(&except_fds);
+
+ FD_SET(handle, &except_fds);
+
+ if(__lemon_socket_error == ::select(1,0,&fds,&except_fds,NULL)) { LEMON_IO_SOCKET_ERROR(*errorCode); return; }
+
+ if(FD_ISSET(handle,&except_fds))
+ {
+ int connect_error = 0;
+
+ int connect_error_len = (int)sizeof(connect_error);
+
+ if(__lemon_socket_error == ::getsockopt(handle,SOL_SOCKET, SO_ERROR, (char*)&connect_error, &connect_error_len))
+ {
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+ else
+ {
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ errorCode->Error.Code = connect_error;
+ }
+ }
+ }
+}}}
+
+
+namespace lemon{namespace io{namespace impl{
+
+ __lemon_native_socket socket_reactor::create(int af, int type, int protocol, LemonErrorInfo * errorCode)
+ {
+ __lemon_native_socket handle =::socket(af, type, protocol);
+
+ if(__lemon_invalid_socket == handle) LEMON_IO_SOCKET_ERROR(*errorCode);
+ // set the socket to nonblocking mode
+ __lemon_noblocking_socket(handle, errorCode);
+
+ if(LEMON_FAILED(*errorCode)) { close(handle); return __lemon_invalid_socket; }
+
+ return handle;
+ }
+
+ void socket_reactor::close(__lemon_native_socket handle)
+ {
+ closesocket(handle);
+ }
+
+ void socket_reactor::bind(__lemon_native_socket handle, const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode)
+ {
+ if(__lemon_socket_error == ::bind(handle, name, nameLength)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ void socket_reactor::shutdown(__lemon_native_socket handle, int how, LemonErrorInfo * errorCode)
+ {
+ if(__lemon_socket_error == ::shutdown(handle, how)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ void socket_reactor::sockname(__lemon_native_socket handle, sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode)
+ {
+ if(__lemon_socket_error == ::getsockname(handle, name, namelength)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ size_t socket_reactor::send(__lemon_native_socket handle, const byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode)
+ {
+ for(;;)
+ {
+ int length = ::send(handle, (const char*)buffer, (int)bufferSize, flag);
+
+ if(length != __lemon_socket_error) return length;
+
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code != would_block && errorCode->Error.Code != try_again) return (size_t)-1;
+
+ __lemon_poll_write(handle,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) return (size_t)-1;
+ }
+ }
+
+ size_t socket_reactor::sendto(__lemon_native_socket handle, const byte_t * buffer, std::size_t bufferSize, int flag, const sockaddr * name, socklen_t nameLength,LemonErrorInfo * errorCode)
+ {
+ for(;;)
+ {
+ int length = ::sendto(handle, (const char*)buffer, (int)bufferSize, flag,name,nameLength);
+
+ if(length != __lemon_socket_error) return length;
+
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code != would_block && errorCode->Error.Code != try_again) return (size_t)-1;
+
+ __lemon_poll_write(handle,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) return (size_t)-1;
+ }
+ }
+
+ size_t socket_reactor::recv(__lemon_native_socket handle, byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode)
+ {
+ for(;;)
+ {
+ int length = ::recv(handle, (char*)buffer, (int)bufferSize, flag);
+
+ if(length != __lemon_socket_error) return length;
+
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code != would_block && errorCode->Error.Code != try_again) return (size_t)-1;
+
+ __lemon_poll_read(handle,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) return (size_t)-1;
+ }
+ }
+
+ size_t socket_reactor::recvfrom(__lemon_native_socket handle, byte_t * buffer, std::size_t bufferSize, int flag, sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode)
+ {
+ for(;;)
+ {
+ int length = ::recvfrom(handle, (char*)buffer, (int)bufferSize, flag, name, namelength);
+
+ if(length != __lemon_socket_error) return length;
+
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code != would_block && errorCode->Error.Code != try_again) return (size_t)-1;
+
+ __lemon_poll_read(handle,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) return (size_t)-1;
+ }
+ }
+
+ void socket_reactor::connect(__lemon_native_socket handle, const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode)
+ {
+ if(__lemon_socket_error == ::connect(handle, name, nameLength)) LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code == would_block || errorCode->Error.Code == in_progress)
+ {
+ __lemon_poll_connect(handle,errorCode);
+ }
+ }
+
+ void socket_reactor::listen(__lemon_native_socket handle, int backlog, LemonErrorInfo * errorCode)
+ {
+ if(__lemon_socket_error == ::listen(handle, backlog)) LEMON_IO_SOCKET_ERROR(*errorCode);
+ }
+
+ __lemon_native_socket socket_reactor::accept(__lemon_native_socket handle, sockaddr * name, socklen_t * namelength,LemonErrorInfo * errorCode)
+ {
+ for(;;)
+ {
+ __lemon_native_socket newhandle = ::accept(handle, name, namelength);
+
+ if(__lemon_invalid_socket != newhandle) return newhandle;
+
+ LEMON_IO_SOCKET_ERROR(*errorCode);
+
+ if(errorCode->Error.Code != would_block && errorCode->Error.Code != try_again) return newhandle;
+
+ __lemon_poll_read(handle,errorCode);
+
+ if(LEMON_FAILED(*errorCode)) return newhandle;
+ }
+ }
+
+}}}
+
+
+#endif //LEMON_IO_IOCP
View
55 io/socket_reactor.hpp
@@ -0,0 +1,55 @@
+/**
+ *
+ * @file socket_reactor
+ * @brief Copyright (C) 2012 yayanyang All Rights Reserved
+ * @author yayanyang
+ * @version 1.0.0.0
+ * @date 2012/09/28
+ */
+#ifndef LEMON_IO_SOCKET_REACTOR_HPP
+#define LEMON_IO_SOCKET_REACTOR_HPP
+#include <cassert>
+#include <lemon/io/abi.h>
+#include <lemonxx/sys/sys.hpp>
+#include <lemonxx/utility/utility.hpp>
+
+#include <lemon/io/basic_socket.hpp>
+
+#ifndef LEMON_IO_IOCP
+
+namespace lemon{namespace io{namespace impl{
+
+ class socket_reactor : private lemon::nocopyable
+ {
+ public:
+
+ __lemon_native_socket create(int af, int type, int protocol, LemonErrorInfo * errorCode);
+
+ void close(__lemon_native_socket handle);
+
+ void bind(__lemon_native_socket handle, const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode);
+
+ void shutdown(__lemon_native_socket handle, int how, LemonErrorInfo * errorCode);
+
+ void sockname(__lemon_native_socket handle, sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode);
+
+ size_t send(__lemon_native_socket handle, const byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode);
+
+ size_t sendto(__lemon_native_socket handle, const byte_t * buffer, std::size_t bufferSize, int flag, const sockaddr * name, socklen_t nameLength,LemonErrorInfo * errorCode);
+
+ size_t recv(__lemon_native_socket handle, byte_t * buffer, std::size_t bufferSize, int flag, LemonErrorInfo * errorCode);
+
+ size_t recvfrom(__lemon_native_socket handle, byte_t * buffer, std::size_t bufferSize, int flag, sockaddr * name, socklen_t * namelength, LemonErrorInfo * errorCode);
+
+ void connect(__lemon_native_socket handle, const sockaddr * name, socklen_t nameLength, LemonErrorInfo * errorCode);
+
+ void listen(__lemon_native_socket handle, int backlog, LemonErrorInfo * errorCode);
+
+ __lemon_native_socket accept(__lemon_native_socket handle, sockaddr * name, socklen_t * namelength,LemonErrorInfo * errorCode);
+ };
+
+}}}
+
+#endif //LEMON_IO_IOCP
+
+#endif // LEMON_IO_SOCKET_REACTOR_HPP

0 comments on commit bec6687

Please sign in to comment.