Re: IO::File performace issue
[p5sagit/p5-mst-13.2.git] / ext / IO / IO.xs
index 4f713a0..4abc135 100644 (file)
@@ -49,11 +49,20 @@ typedef FILE * OutputStream;
 #define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
 #endif
 
+#ifndef __attribute__noreturn__
+#  define __attribute__noreturn__
+#endif
+
+#ifndef NORETURN_FUNCTION_END
+# define NORETURN_FUNCTION_END /* NOT REACHED */ return 0
+#endif
+
+static int not_here(const char *s) __attribute__noreturn__;
 static int
-not_here(char *s)
+not_here(const char *s)
 {
     croak("%s not implemented on this architecture", s);
-    return -1;
+    NORETURN_FUNCTION_END;
 }
 
 
@@ -73,53 +82,24 @@ io_blocking(pTHX_ InputStream f, int block)
     RETVAL = fcntl(PerlIO_fileno(f), F_GETFL, 0);
     if (RETVAL >= 0) {
        int mode = RETVAL;
+       int newmode = mode;
 #ifdef O_NONBLOCK
        /* POSIX style */
-#if defined(O_NDELAY) && O_NDELAY != O_NONBLOCK
-       /* Ooops has O_NDELAY too - make sure we don't
-        * get SysV behaviour by mistake. */
 
-       /* E.g. In UNICOS and UNICOS/mk a F_GETFL returns an O_NDELAY
+# ifndef O_NDELAY
+#  define O_NDELAY O_NONBLOCK
+# endif
+       /* Note: UNICOS and UNICOS/mk a F_GETFL returns an O_NDELAY
         * after a successful F_SETFL of an O_NONBLOCK. */
        RETVAL = RETVAL & (O_NONBLOCK | O_NDELAY) ? 0 : 1;
 
-       if (block >= 0) {
-           if ((mode & O_NDELAY) || ((block == 0) && !(mode & O_NONBLOCK))) {
-               int ret;
-               mode = (mode & ~O_NDELAY) | O_NONBLOCK;
-               ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-               if(ret < 0)
-                   RETVAL = ret;
-           }
-           else
-              if ((mode & O_NDELAY) || ((block > 0) && (mode & O_NONBLOCK))) {
-               int ret;
-               mode &= ~(O_NONBLOCK | O_NDELAY);
-               ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-               if(ret < 0)
-                   RETVAL = ret;
-              }
+       if (block == 0) {
+           newmode &= ~O_NDELAY;
+           newmode |= O_NONBLOCK;
+       } else if (block > 0) {
+           newmode &= ~(O_NDELAY|O_NONBLOCK);
        }
 #else
-       /* Standard POSIX */
-       RETVAL = RETVAL & O_NONBLOCK ? 0 : 1;
-
-       if ((block == 0) && !(mode & O_NONBLOCK)) {
-           int ret;
-           mode |= O_NONBLOCK;
-           ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-           if(ret < 0)
-               RETVAL = ret;
-        }
-       else if ((block > 0) && (mode & O_NONBLOCK)) {
-           int ret;
-           mode &= ~O_NONBLOCK;
-           ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-           if(ret < 0)
-               RETVAL = ret;
-        }
-#endif
-#else
        /* Not POSIX - better have O_NDELAY or we can't cope.
         * for BSD-ish machines this is an acceptable alternative
         * for SysV we can't tell "would block" from EOF but that is
@@ -127,21 +107,17 @@ io_blocking(pTHX_ InputStream f, int block)
         */
        RETVAL = RETVAL & O_NDELAY ? 0 : 1;
 
-       if ((block == 0) && !(mode & O_NDELAY)) {
-           int ret;
-           mode |= O_NDELAY;
-           ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-           if(ret < 0)
-               RETVAL = ret;
-        }
-       else if ((block > 0) && (mode & O_NDELAY)) {
-           int ret;
-           mode &= ~O_NDELAY;
-           ret = fcntl(PerlIO_fileno(f),F_SETFL,mode);
-           if(ret < 0)
-               RETVAL = ret;
-        }
+       if (block == 0) {
+           newmode |= O_NDELAY;
+       } else if (block > 0) {
+           newmode &= ~O_NDELAY;
+       }
 #endif
+       if (newmode != mode) {
+           const int ret = fcntl(PerlIO_fileno(f),F_SETFL,newmode);
+           if (ret < 0)
+               RETVAL = ret;
+       }
     }
     return RETVAL;
 #else
@@ -157,21 +133,32 @@ fgetpos(handle)
     CODE:
        if (handle) {
 #ifdef PerlIO
-           ST(0) = sv_2mortal(newSV(0));
+           ST(0) = sv_newmortal();
+#if PERL_VERSION < 8
+           Fpos_t pos;
+           if (PerlIO_getpos(handle, &pos) != 0) {
+               ST(0) = &PL_sv_undef;
+           }
+           else {
+               sv_setpvn(ST(0), (char *)&pos, sizeof(Fpos_t));
+           }
+#else
            if (PerlIO_getpos(handle, ST(0)) != 0) {
                ST(0) = &PL_sv_undef;
            }
+#endif
 #else
+           Fpos_t pos;
            if (fgetpos(handle, &pos)) {
                ST(0) = &PL_sv_undef;
            } else {
-               ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t)));
+               ST(0) = sv_2mortal(newSVpvn((char*)&pos, sizeof(Fpos_t)));
            }
 #endif
        }
        else {
-           ST(0) = &PL_sv_undef;
            errno = EINVAL;
+           ST(0) = &PL_sv_undef;
        }
 
 SysRet
@@ -181,7 +168,19 @@ fsetpos(handle, pos)
     CODE:
        if (handle) {
 #ifdef PerlIO
+#if PERL_VERSION < 8
+           char *p;
+           STRLEN len;
+           if (SvOK(pos) && (p = SvPV(pos,len)) && len == sizeof(Fpos_t)) {
+               RETVAL = PerlIO_setpos(handle, (Fpos_t*)p);
+           }
+           else {
+               RETVAL = -1;
+               errno = EINVAL;
+           }
+#else
            RETVAL = PerlIO_setpos(handle, pos);
+#endif
 #else
            char *p;
            STRLEN len;
@@ -205,7 +204,7 @@ MODULE = IO PACKAGE = IO::File      PREFIX = f
 
 void
 new_tmpfile(packname = "IO::File")
-    char *             packname
+    char *     packname
     PREINIT:
        OutputStream fp;
        GV *gv;
@@ -235,7 +234,7 @@ _poll(timeout,...)
 PPCODE:
 {
 #ifdef HAS_POLL
-    int nfd = (items - 1) / 2;
+    const int nfd = (items - 1) / 2;
     SV *tmpsv = NEWSV(999,nfd * sizeof(struct pollfd));
     struct pollfd *fds = (struct pollfd *)SvPVX(tmpsv);
     int i,j,ret;
@@ -268,7 +267,7 @@ io_blocking(handle,blk=-1)
 PROTOTYPE: $;$
 CODE:
 {
-    int ret = io_blocking(aTHX_ handle, items == 1 ? -1 : blk ? 1 : 0);
+    const int ret = io_blocking(aTHX_ handle, items == 1 ? -1 : blk ? 1 : 0);
     if(ret >= 0)
        XSRETURN_IV(ret);
     else