[svn:parrot] r37769 - in trunk: examples/io include/parrot src/io src/ops src/pmc

Infinoid at svn.parrot.org Infinoid at svn.parrot.org
Fri Mar 27 22:07:08 UTC 2009


Author: Infinoid
Date: Fri Mar 27 22:07:05 2009
New Revision: 37769
URL: https://trac.parrot.org/parrot/changeset/37769

Log:
Apply patch from bacek++ in TT #514:
* Add a PMC* argument to Parrot_io_socket methods, to prevent spurious reallocation
* Add a Socket.socket() method, use it in the httpd.pir example
* Add a SockAddr.sockaddr() method, use it in the httpd.pir example
* Remove a bunch of unused socket ops from io.ops and ops.num
* Fix up the Socket PMC some, use more inheritance, add POD documentation

Modified:
   trunk/examples/io/httpd.pir
   trunk/include/parrot/io.h
   trunk/include/parrot/io_unix.h
   trunk/include/parrot/io_win32.h
   trunk/src/io/socket_api.c
   trunk/src/io/socket_unix.c
   trunk/src/io/socket_win32.c
   trunk/src/ops/io.ops
   trunk/src/ops/ops.num
   trunk/src/pmc/socket.pmc

Modified: trunk/examples/io/httpd.pir
==============================================================================
--- trunk/examples/io/httpd.pir	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/examples/io/httpd.pir	Fri Mar 27 22:07:05 2009	(r37769)
@@ -111,11 +111,13 @@
     port = 1234
 
     # TODO provide sys/socket constants
-    listener = socket 2, 1, 6	# PF_INET, SOCK_STREAM, tcp
+    .local pmc sock
+    sock = new 'Socket'
+    listener = sock.'socket'(2, 1, 6)	# PF_INET, SOCK_STREAM, tcp
     unless listener goto ERR_NO_SOCKET
 
     # Pack a sockaddr_in structure with IP and port
-    address = sockaddr host, port
+    address = sock.'sockaddr'(host, port)
     ret = listener.'bind'(address)
     if ret == -1 goto ERR_bind
     $S0 = port

Modified: trunk/include/parrot/io.h
==============================================================================
--- trunk/include/parrot/io.h	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/include/parrot/io.h	Fri Mar 27 22:07:05 2009	(r37769)
@@ -829,8 +829,13 @@
 PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
-PMC * Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
-        __attribute__nonnull__(1);
+PMC * Parrot_io_socket(PARROT_INTERP,
+    ARGMOD_NULLOK(PMC * socket),
+    INTVAL fam,
+    INTVAL type,
+    INTVAL proto)
+        __attribute__nonnull__(1)
+        FUNC_MODIFIES(* socket);
 
 PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT

Modified: trunk/include/parrot/io_unix.h
==============================================================================
--- trunk/include/parrot/io_unix.h	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/include/parrot/io_unix.h	Fri Mar 27 22:07:05 2009	(r37769)
@@ -1,7 +1,7 @@
 /* io_unix.h
  *  Copyright (C) 2001-2003, Parrot Foundation.
  *  SVN Info
- *     $Id$
+ *     $Id: io_unix.h 36833 2009-02-17 20:09:26Z allison $
  *  Overview:
  *      Parrot IO subsystem
  *  Data Structure and Algorithms:
@@ -220,8 +220,13 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
-        __attribute__nonnull__(1);
+PMC * Parrot_io_socket_unix(PARROT_INTERP,
+    ARGIN(PMC *s),
+    int fam,
+    int type,
+    int proto)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
 
 #define ASSERT_ARGS_Parrot_io_accept_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
@@ -249,7 +254,8 @@
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(addr)
 #define ASSERT_ARGS_Parrot_io_socket_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(s)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/io/socket_unix.c */
 
@@ -275,8 +281,8 @@
 
 #define PIO_POLL(interp, pmc, which, sec, usec) \
     Parrot_io_poll_unix((interp), (pmc), (which), (sec), (usec))
-#define PIO_NEW_SOCKET(interp, fam, type, proto) \
-    Parrot_io_socket_unix((interp), (fam), (type), (proto))
+#define PIO_SOCKET(interp, socket, fam, type, proto) \
+    Parrot_io_socket_unix((interp), (socket), (fam), (type), (proto))
 #define PIO_RECV(interp, pmc, buf) \
     Parrot_io_recv_unix((interp), (pmc), (buf))
 #define PIO_SEND(interp, pmc, buf) \

Modified: trunk/include/parrot/io_win32.h
==============================================================================
--- trunk/include/parrot/io_win32.h	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/include/parrot/io_win32.h	Fri Mar 27 22:07:05 2009	(r37769)
@@ -199,8 +199,13 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-PMC * Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
-        __attribute__nonnull__(1);
+PMC * Parrot_io_socket_win32(PARROT_INTERP,
+    ARGIN(PMC * s),
+    int fam,
+    int type,
+    int proto)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
 
 #define ASSERT_ARGS_Parrot_io_accept_win32 __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
@@ -228,7 +233,8 @@
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(addr)
 #define ASSERT_ARGS_Parrot_io_socket_win32 __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(s)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/io/socket_win32.c */
 
@@ -252,8 +258,8 @@
 
 #define PIO_POLL(interp, pmc, which, sec, usec) \
     Parrot_io_poll_win32((interp), (pmc), (which), (sec), (usec))
-#define PIO_NEW_SOCKET(interp, fam, type, proto) \
-    Parrot_io_socket_win32((interp), (fam), (type), (proto))
+#define PIO_SOCKET(interp, socket, fam, type, proto) \
+    Parrot_io_socket_win32((interp), (socket), (fam), (type), (proto))
 #define PIO_RECV(interp, pmc, buf) \
     Parrot_io_recv_win32((interp), (pmc), (buf))
 #define PIO_SEND(interp, pmc, buf) \

Modified: trunk/src/io/socket_api.c
==============================================================================
--- trunk/src/io/socket_api.c	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/io/socket_api.c	Fri Mar 27 22:07:05 2009	(r37769)
@@ -83,10 +83,19 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
 PMC *
-Parrot_io_socket(PARROT_INTERP, INTVAL fam, INTVAL type, INTVAL proto)
+Parrot_io_socket(PARROT_INTERP, ARGMOD_NULLOK(PMC * socket), INTVAL fam,
+            INTVAL type, INTVAL proto)
 {
     ASSERT_ARGS(Parrot_io_socket)
-    return PIO_NEW_SOCKET(interp, fam, type, proto);
+    PMC *new_socket;
+
+    if (PMC_IS_NULL(socket))
+        new_socket = Parrot_io_new_socket_pmc(interp,
+                PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
+    else
+        new_socket = socket;
+
+    return PIO_SOCKET(interp, socket, fam, type, proto);
 }
 
 /*

Modified: trunk/src/io/socket_unix.c
==============================================================================
--- trunk/src/io/socket_unix.c	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/io/socket_unix.c	Fri Mar 27 22:07:05 2009	(r37769)
@@ -127,17 +127,16 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
 PMC *
-Parrot_io_socket_unix(PARROT_INTERP, int fam, int type, int proto)
+Parrot_io_socket_unix(PARROT_INTERP, ARGIN(PMC *s), int fam, int type, int proto)
 {
     ASSERT_ARGS(Parrot_io_socket_unix)
     int i;
     const int sock = socket(fam, type, proto);
     if (sock >= 0) {
-        PMC * io = Parrot_io_new_socket_pmc(interp, PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
-        PARROT_SOCKET(io)->os_handle = sock;
-        setsockopt(PARROT_SOCKET(io)->os_handle, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
-        SOCKADDR_REMOTE(io)->sin_family = fam;
-        return io;
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+        Parrot_io_set_os_handle(interp, s, sock);
+        SOCKADDR_REMOTE(s)->sin_family = fam;
+        return s;
     }
     return PMCNULL;
 }

Modified: trunk/src/io/socket_win32.c
==============================================================================
--- trunk/src/io/socket_win32.c	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/io/socket_win32.c	Fri Mar 27 22:07:05 2009	(r37769)
@@ -73,15 +73,14 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
 PMC *
-Parrot_io_socket_win32(PARROT_INTERP, int fam, int type, int proto)
+Parrot_io_socket_win32(PARROT_INTERP, ARGIN(PMC * s), int fam, int type, int proto)
 {
     ASSERT_ARGS(Parrot_io_socket_win32)
     int i;
     const int sock = socket(fam, type, proto);
     if (sock >= 0) {
-        PMC * io = Parrot_io_new_socket_pmc(interp, PIO_F_SOCKET|PIO_F_READ|PIO_F_WRITE);
-        PARROT_SOCKET(io)->os_handle = (void*)sock;
-        setsockopt((int)PARROT_SOCKET(io)->os_handle, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
+        Parrot_io_set_os_handle(interp, s, sock);
         SOCKADDR_REMOTE(io)->sin_family = fam;
         return io;
     }

Modified: trunk/src/ops/io.ops
==============================================================================
--- trunk/src/ops/io.ops	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/ops/io.ops	Fri Mar 27 22:07:05 2009	(r37769)
@@ -508,62 +508,12 @@
 
 =item B<socket>(out PMC, in INT, in INT, in INT)
 
-Create new socket
+Create new Socket PMC
 
 =cut
 
 op socket(out PMC, in INT, in INT, in INT) {
-    $1 = Parrot_io_socket(interp, $2, $3, $4);
-}
-
-=item B<bind>(out INT, in PMC, in PMC)
-
-Bind socket to address
-
-=cut
-
-op bind(out INT, in PMC, in PMC) {
-    $1 = Parrot_io_bind(interp, $2, $3);
-}
-
-=item B<listen>(out INT, in PMC, in INT)
-
-Start listening on previously bound socket
-
-=cut
-
-op listen(out INT, in PMC, in INT) {
-    $1 = Parrot_io_listen(interp, $2, $3);
-}
-
-=item B<accept>(out PMC, in PMC)
-
-Accept incoming connection
-
-=cut
-
-op accept(out PMC, in PMC) {
-    $1 = Parrot_io_accept(interp, $2);
-}
-
-=item B<recv>(out INT, in PMC, out STR)
-
-Receive data from socket
-
-=cut
-
-op recv(out INT, in PMC, out STR) {
-    $1 = Parrot_io_recv(interp, $2, &$3);
-}
-
-=item B<send>(out INT, in PMC, in STR)
-
-Send data to socket
-
-=cut
-
-op send(out INT, in PMC, in STR) {
-    $1 = Parrot_io_send(interp, $2, $3);
+    $1 = Parrot_io_socket(interp, PMCNULL, $2, $3, $4);
 }
 
 =back

Modified: trunk/src/ops/ops.num
==============================================================================
--- trunk/src/ops/ops.num	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/ops/ops.num	Fri Mar 27 22:07:05 2009	(r37769)
@@ -1280,19 +1280,3 @@
 sockaddr_p_sc_i                1256
 sockaddr_p_s_ic                1257
 sockaddr_p_sc_ic               1258
-bind_i_p_p                     1259
-bind_i_pc_p                    1260
-bind_i_p_pc                    1261
-bind_i_pc_pc                   1262
-listen_i_p_i                   1263
-listen_i_pc_i                  1264
-listen_i_p_ic                  1265
-listen_i_pc_ic                 1266
-accept_p_p                     1267
-accept_p_pc                    1268
-recv_i_p_s                     1269
-recv_i_pc_s                    1270
-send_i_p_s                     1271
-send_i_pc_s                    1272
-send_i_p_sc                    1273
-send_i_pc_sc                   1274

Modified: trunk/src/pmc/socket.pmc
==============================================================================
--- trunk/src/pmc/socket.pmc	Fri Mar 27 21:43:16 2009	(r37768)
+++ trunk/src/pmc/socket.pmc	Fri Mar 27 22:07:05 2009	(r37769)
@@ -37,23 +37,12 @@
 
     VTABLE void init() {
         Parrot_Socket_attributes *data_struct =
-                mem_allocate_typed(Parrot_Socket_attributes);
+                mem_allocate_zeroed_typed(Parrot_Socket_attributes);
 
         PMC_data(SELF)      = data_struct;
         data_struct->local  = PMCNULL;
         data_struct->remote = PMCNULL;
 
-        /* Initialize the os_handle to the platform-specific value for closed. */
-#ifdef PIO_OS_WIN32
-    data_struct->os_handle    = (PIOHANDLE)INVALID_HANDLE_VALUE;
-#endif
-#ifdef PIO_OS_UNIX
-    data_struct->os_handle    = (PIOHANDLE)-1;
-#endif
-#ifdef PIO_OS_STDIO
-    data_struct->os_handle    = (PIOHANDLE)NULL;
-#endif
-
         PObj_custom_mark_destroy_SETALL(SELF);
     }
 
@@ -68,11 +57,12 @@
 */
 
     VTABLE PMC *clone() {
-        Parrot_Socket_attributes * const old_struct  = PARROT_SOCKET(SELF);
-        PMC * const copy = Parrot_io_new_socket_pmc(interp, old_struct->flags);
+        PMC * copy = SUPER();
+        Parrot_Socket_attributes * const old_struct = PARROT_SOCKET(SELF);
         Parrot_Socket_attributes * const data_struct = PARROT_SOCKET(copy);
 
-        data_struct->os_handle    = Parrot_dup(old_struct->os_handle);
+        data_struct->local      = VTABLE_clone(interp, old_struct->local);
+        data_struct->remote     = VTABLE_clone(interp, old_struct->remote);
 
         return SELF;
     }
@@ -115,12 +105,28 @@
         }
     }
 
-    METHOD close() {
-        INTVAL status = 0;
-        close(PARROT_SOCKET(SELF)->os_handle);
-        RETURN(INTVAL status);
-    }
+/*
 
+=item C<INTVAL get_bool()>
+
+Returns whether the Socket was successfully created.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        /* Initialize the os_handle to the platform-specific value for closed. */
+#ifdef PIO_OS_WIN32
+        return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)INVALID_HANDLE_VALUE);
+#endif
+#ifdef PIO_OS_UNIX
+        return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)-1);
+#endif
+#ifdef PIO_OS_STDIO
+        return (PARROT_SOCKET(SELF)->os_handle != (PIOHANDLE)NULL);
+#endif
+    }
 
 /*
 
@@ -130,6 +136,36 @@
 
 =over 4
 
+=item C<socket>
+
+=cut
+
+*/
+
+
+    METHOD socket(INTVAL type, INTVAL fam, INTVAL proto) {
+        PMC * res = Parrot_io_socket(interp, SELF, type, fam, proto);
+        RETURN(PMC * res);
+    }
+
+/*
+
+=item C<sockaddr>
+
+C<sockaddr> returns an object representing a socket address, generated
+from a port number (integer) and an address (string).
+
+=cut
+
+*/
+
+    METHOD sockaddr(STRING * address, INTVAL port) {
+        PMC * res = Parrot_io_sockaddr_in(interp, address, port);
+        RETURN(PMC * res);
+    }
+
+/*
+
 =item C<connect>
 
 Connects a socket object to an address.
@@ -191,16 +227,68 @@
         RETURN(INTVAL res);
     }
 
+/*
+
+=item C<bind>
+
+C<bind> binds a socket object to the port and address specified by an
+address object (the packed result of C<sockaddr>).
+
+The asynchronous version takes an additional final PMC callback
+argument, and only returns a status object. When the bind operation is
+complete, it invokes the callback, passing it a status object and the
+socket object it was called on. [If you want notification when a bind
+operation is completed, you probably want to do something with that
+bound socket object.]
+
+=cut
+
+*/
+
     METHOD bind(PMC *host) {
         INTVAL res = Parrot_io_bind(INTERP, SELF, host);
         RETURN(INTVAL res);
     }
 
+/*
+
+=item C<listen>
+
+C<listen> specifies that a socket object is willing to accept incoming
+connections. The integer argument gives the maximum size of the queue
+for pending connections.
+
+There is no asynchronous version. C<listen> marks a set of attributes on
+the socket object.
+
+=cut
+
+*/
+
     METHOD listen(INTVAL backlog) {
         INTVAL res = Parrot_io_listen(INTERP, SELF, backlog);
         RETURN(INTVAL res);
     }
 
+/*
+
+=item C<accept>
+
+C<accept> accepts a new connection on a given socket object, and returns
+a newly created socket object for the connection.
+
+The asynchronous version takes an additional final PMC callback
+argument, and only returns a status object. When the accept operation
+receives a new connection, it invokes the callback, passing it a status
+object and a newly created socket object for the connection. [While the
+synchronous C<accept> has to be called repeatedly in a loop (once for
+each connection received), the asynchronous version is only called once,
+but continues to send new connection events until the socket is closed.]
+
+=cut
+
+*/
+
     METHOD accept() {
         PMC * res = Parrot_io_accept(INTERP, SELF);
         RETURN(PMC * res);


More information about the parrot-commits mailing list