← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~paul-lucas/zorba/pjl-misc into lp:zorba

 

Paul J. Lucas has proposed merging lp:~paul-lucas/zorba/pjl-misc into lp:zorba.

Commit message:
Eliminated slight performance degradation in ato*() functions. It turns out that passing nullptr as a default argument (when nullptr is our own implementation, not the C++11 version) is a tad slow presumably because each instance must be initialized. Changing this to use a global singleton instance eliminates the performance degradation.

Requested reviews:
  Paul J. Lucas (paul-lucas)

For more details, see:
https://code.launchpad.net/~paul-lucas/zorba/pjl-misc/+merge/143386

Eliminated slight performance degradation in ato*() functions. It turns out that passing nullptr as a default argument (when nullptr is our own implementation, not the C++11 version) is a tad slow presumably because each instance must be initialized. Changing this to use a global singleton instance eliminates the performance degradation.
-- 
https://code.launchpad.net/~paul-lucas/zorba/pjl-misc/+merge/143386
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/util/CMakeLists.txt'
--- src/util/CMakeLists.txt	2013-01-04 16:08:03 +0000
+++ src/util/CMakeLists.txt	2013-01-15 19:20:28 +0000
@@ -37,6 +37,10 @@
   http_util.h
   http_util.cpp)
 
+IF (NOT ZORBA_CXX_NULLPTR)
+  LIST(APPEND UTIL_SRCS cxx_util.cpp)
+ENDIF (NOT ZORBA_CXX_NULLPTR)
+
 IF(ZORBA_WITH_FILE_ACCESS)
   LIST(APPEND UTIL_SRCS mmap_file.cpp)
 ENDIF(ZORBA_WITH_FILE_ACCESS)

=== added file 'src/util/cxx_util.cpp'
--- src/util/cxx_util.cpp	1970-01-01 00:00:00 +0000
+++ src/util/cxx_util.cpp	2013-01-15 19:20:28 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * 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.
+ */
+
+#include <zorba/config.h>
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ZORBA_CXX_NULLPTR
+
+#include "cxx_util.h"
+
+zorba::nullptr_type const zorba_nullptr = { };
+
+#endif /* ZORBA_CXX_NULLPTR */
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/util/cxx_util.h'
--- src/util/cxx_util.h	2012-09-19 21:16:15 +0000
+++ src/util/cxx_util.h	2013-01-15 19:20:28 +0000
@@ -23,13 +23,15 @@
 
 #ifndef ZORBA_CXX_NULLPTR
 
+namespace zorba {
+
 /**
- * See: http://www2.research.att.com/~bs/C++0xFAQ.html#nullptr
+ * A \c nullptr type.
  *
- * We use "zorba_nullptr" in combination with a macro to elimimate a
- * "identifier 'nullptr' will become a keyword in C++0x" warning.
+ * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
+ * section 1.1: "Alternative #1: A Library Implementation of nullptr," p. 3.
  */
-class nullptr_t {
+class nullptr_type {
 public:
   template<typename T>                  // convertible to any type
   operator T*() const {                 // of null non-member
@@ -41,7 +43,18 @@
   }
 private:
   void operator&() const;               // whose address can't be taken
-} const zorba_nullptr = {};             // and whose name is nullptr
+};
+
+} // namespace zorba
+
+/**
+ * We use "zorba_nullptr" in combination with a macro to elimimate an
+ * "identifier 'nullptr' will become a keyword in C++0x" warning.
+ *
+ * We also use a singleton object since using multiple instances as shown in
+ * Bjarne's paper has a sligt performance penalty.
+ */
+extern zorba::nullptr_type const zorba_nullptr;
 
 #define nullptr ::zorba_nullptr
 

=== modified file 'src/util/string_util.cpp'
--- src/util/string_util.cpp	2013-01-11 15:45:59 +0000
+++ src/util/string_util.cpp	2013-01-15 19:20:28 +0000
@@ -56,64 +56,81 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static void check_errno( char const *buf, char const *end ) {
-  if ( errno == ERANGE ) {
-    zstring const s( buf, end );
-    throw std::range_error(
-      BUILD_STRING( '"', s, "\": number too big/small" )
-    );
-  }
-}
-
-static void check_parse_number( char const *buf, char const *end,
+static void no_digits( char const *buf ) {
+  throw std::invalid_argument( BUILD_STRING( '"', buf, "\": no digits" ) );
+}
+
+static void too_big_or_small( char const *buf, char const *end ) {
+  zstring const s( buf, end );
+  throw std::range_error( BUILD_STRING( '"', s, "\": number too big/small" ) );
+}
+
+inline void check_errno( char const *buf, char const *end ) {
+  if ( errno == ERANGE )
+    too_big_or_small( buf, end );
+}
+
+static void check_trailing_chars_impl( char const *end ) {
+  for ( ; *end; ++end )                 // remaining characters, if any, ...
+    if ( !ascii::is_space( *end ) )     // ... may only be whitespace
+      throw std::invalid_argument(
+        BUILD_STRING( '\'', *end, "': invalid character" )
+      );
+}
+
+inline void check_parse_number( char const *buf, char const *end,
                                 bool check_trailing_chars ) {
   if ( end == buf )
-    throw std::invalid_argument( BUILD_STRING( '"', buf, "\": no digits" ) );
+    no_digits( buf );
   if ( check_trailing_chars )
-    for ( ; *end; ++end )               // remaining characters, if any, ...
-      if ( !ascii::is_space( *end ) )   // ... may only be whitespace
-        throw std::invalid_argument(
-          BUILD_STRING( '"', *end, "\": invalid character" )
-        );
+    check_trailing_chars_impl( end );
 }
 
-#define ATON_PREAMBLE()           \
-  bool check_trailing_chars;      \
-  char const *pc;                 \
-  if ( end ) {                    \
-    check_trailing_chars = false; \
-  } else {                        \
-    end = &pc;                    \
-    check_trailing_chars = true;  \
-  }                               \
-  errno = 0
+class aton_context {
+public:
+  aton_context( char const **&end ) {
+    if ( end ) {
+      check_trailing_chars_ = false;
+    } else {
+      end = &end_;
+      check_trailing_chars_ = true;
+    }
+    errno = 0;
+  }
+  bool check_trailing_chars() const {
+    return check_trailing_chars_;
+  }
+private:
+  bool check_trailing_chars_;
+  char const *end_;
+};
 
 ///////////////////////////////////////////////////////////////////////////////
 
 double atod( char const *buf, char const **end ) {
-  ATON_PREAMBLE();
+  aton_context const ctx( end );
   double const result = std::strtod( buf, (char**)end );
-  check_parse_number( buf, *end, check_trailing_chars );
+  check_parse_number( buf, *end, ctx.check_trailing_chars() );
   return result;
 }
 
 float atof( char const *buf, char const **end ) {
-  ATON_PREAMBLE();
+  aton_context const ctx( end );
   float const result = std::strtof( buf, (char**)end );
-  check_parse_number( buf, *end, check_trailing_chars );
+  check_parse_number( buf, *end, ctx.check_trailing_chars() );
   return result;
 }
 
 long long atoll( char const *buf, char const **end ) {
-  ATON_PREAMBLE();
+  aton_context const ctx( end );
   long long const result = std::strtoll( buf, (char**)end, 10 );
   check_errno( buf, *end );
-  check_parse_number( buf, *end, check_trailing_chars );
+  check_parse_number( buf, *end, ctx.check_trailing_chars() );
   return result;
 }
 
 unsigned long long atoull( char const *buf, char const **end ) {
-  ATON_PREAMBLE();
+  aton_context const ctx( end );
   //
   // We have to check for '-' ourselves since strtoull(3) allows it (oddly).
   //
@@ -122,7 +139,7 @@
 
   unsigned long long const result = std::strtoull( buf, (char**)end, 10 );
   check_errno( buf, *end );
-  check_parse_number( buf, *end, check_trailing_chars );
+  check_parse_number( buf, *end, ctx.check_trailing_chars() );
 
   if ( minus && result ) {
     //


Follow ups