$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r75292 - in trunk/boost/chrono: . io io/utility
From: vicente.botet_at_[hidden]
Date: 2011-11-03 18:39:08
Author: viboes
Date: 2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
New Revision: 75292
URL: http://svn.boost.org/trac/boost/changeset/75292
Log:
Chrono: Added duration_units::global() and some refactoring so that the client code is simpler: imbue_if_has_not
Text files modified: 
   trunk/boost/chrono/config.hpp                        |     1                                         
   trunk/boost/chrono/io/duration_get.hpp               |    18 ++-------                               
   trunk/boost/chrono/io/duration_put.hpp               |    17 ++------                                
   trunk/boost/chrono/io/duration_units.hpp             |    74 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp |    60 ++++++++++++++++++++++++--------        
   5 files changed, 130 insertions(+), 40 deletions(-)
Modified: trunk/boost/chrono/config.hpp
==============================================================================
--- trunk/boost/chrono/config.hpp	(original)
+++ trunk/boost/chrono/config.hpp	2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
@@ -93,6 +93,7 @@
 #define BOOST_CHRONO_IO_USE_XALLOC
 #define BOOST_CHRONO_USES_DURATION_PUT
 #define BOOST_CHRONO_USES_DURATION_GET
+//#define BOOST_CHRONO_USES_DURATION_UNITS_GLOBAL
 //#define BOOST_CHRONO_IS_LOCALIZABLE_VIRTUAL
 //#define BOOST_CHRONO_IS_LOCALIZABLE_TRANSLATE
 
Modified: trunk/boost/chrono/io/duration_get.hpp
==============================================================================
--- trunk/boost/chrono/io/duration_get.hpp	(original)
+++ trunk/boost/chrono/io/duration_get.hpp	2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
@@ -161,9 +161,6 @@
           duration<Rep, Period> &d, const char_type *pattern, const char_type *pat_end) const
       {
 
-        if (!std::has_facet<duration_units<CharT> >(ios.getloc())) ios.imbue(
-            std::locale(ios.getloc(), new duration_units_default<CharT> ()));
-
         typedef typename detail::duration_io_intermediate<Rep>::type intermediate_type;
         intermediate_type r;
         detail::rt_ratio rt;
@@ -226,7 +223,7 @@
                     break;
                   }
                   loc_found=true;
-                  std::basic_string<CharT> pat = std::use_facet<duration_units<CharT> >(ios.getloc()).get_pattern();
+                  std::basic_string<CharT> pat = duration_units<CharT>::imbue_if_has_not(ios).get_pattern();
                   if (pattern+1 != pat_end)
                   pat.append(pattern+1, pat_end);
                   pattern = pat.data();
@@ -327,10 +324,7 @@
       iter_type get(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err,
           duration<Rep, Period> & d) const
       {
-        if (!std::has_facet<duration_units<CharT> >(ios.getloc())) ios.imbue(
-            std::locale(ios.getloc(), new duration_units_default<CharT> ()));
-
-        std::basic_string < CharT > str = std::use_facet<duration_units<CharT> >(ios.getloc()).get_pattern();
+        std::basic_string < CharT > str = duration_units<CharT>::imbue_if_has_not(ios).get_pattern();
         return get(s, end, ios, err, d, str.data(), str.data() + str.size());
       }
 
@@ -360,9 +354,7 @@
       iter_type get_unit(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
           detail::rt_ratio &rt) const
       {
-        if (!std::has_facet<duration_units<CharT> >(is.getloc()))
-          is.imbue(std::locale(is.getloc(), new duration_units_default<CharT> ()));
-        duration_units<CharT> const &facet = std::use_facet<duration_units<CharT> >(is.getloc());
+        duration_units<CharT> const &facet = duration_units<CharT>::imbue_if_has_not(is);
 
         if (*i == '[')
         {
@@ -582,8 +574,8 @@
     /**
      * Unique identifier for this type of facet.
      */
-    template <class CharT, class OutputIterator>
-    std::locale::id duration_get<CharT, OutputIterator>::id;
+    template <class CharT, class InputIterator>
+    std::locale::id duration_get<CharT, InputIterator>::id;
 
   } // chrono
 }
Modified: trunk/boost/chrono/io/duration_put.hpp
==============================================================================
--- trunk/boost/chrono/io/duration_put.hpp	(original)
+++ trunk/boost/chrono/io/duration_put.hpp	2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
@@ -91,8 +91,7 @@
       iter_type put(iter_type s, std::ios_base& ios, duration<Rep, Period> const& d, const CharT* pattern,
           const CharT* pat_end) const
       {
-        if (!std::has_facet<duration_units<CharT> >(ios.getloc())) ios.imbue(
-            std::locale(ios.getloc(), new duration_units_default<CharT> ()));
+        duration_units<CharT,OutputIterator> const& units_facet = duration_units<CharT,OutputIterator>::imbue_if_has_not(ios);
 
         const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc());
         for (; pattern != pat_end; ++pattern)
@@ -119,7 +118,7 @@
                 }
                 case 'x':
                 {
-                  std::basic_string<CharT> pat = std::use_facet<duration_units<CharT> >(ios.getloc()).get_pattern();
+                  std::basic_string<CharT> pat = units_facet.get_pattern();
                   pattern = pat.data();
                   pat_end = pattern + pat.size();
                   break;
@@ -150,10 +149,7 @@
       template <typename Rep, typename Period>
       iter_type put(iter_type s, std::ios_base& ios, duration<Rep, Period> const& d) const
       {
-        if (!std::has_facet<duration_units<CharT> >(ios.getloc())) ios.imbue(
-            std::locale(ios.getloc(), new duration_units_default<CharT> ()));
-
-        std::basic_string<CharT> str = std::use_facet<duration_units<CharT> >(ios.getloc()).get_pattern();
+        std::basic_string<CharT> str = duration_units<CharT,OutputIterator>::imbue_if_has_not(ios).get_pattern();
         return put(s, ios, d, str.data(), str.data() + str.size());
       }
 
@@ -179,16 +175,13 @@
        * @param d the duration
        * @param pattern
        * @Effects imbue in @c ios the @c duration_units_default facet if not already present.
-       * @Effects Calls std::use_facet<duration_units<CharT> >(ios.getloc()).put(s, ios, d).
+       * @Effects Calls std::use_facet<duration_units<CharT,OutputIterator> >(ios.getloc()).put(s, ios, d).
        * @Returns An iterator pointing immediately after the last character produced.
        */
       template <typename Rep, typename Period>
       iter_type put_unit(iter_type s, std::ios_base& ios, duration<Rep, Period> const& d) const
       {
-        if (!std::has_facet<duration_units<CharT> >(ios.getloc())) ios.imbue(
-            std::locale(ios.getloc(), new duration_units_default<CharT> ()));
-
-        return std::use_facet<duration_units<CharT> >(ios.getloc()).put(s, ios, d);
+        return duration_units<CharT,OutputIterator>::imbue_if_has_not(ios).put(s, ios, d);
       }
 
       /**
Modified: trunk/boost/chrono/io/duration_units.hpp
==============================================================================
--- trunk/boost/chrono/io/duration_units.hpp	(original)
+++ trunk/boost/chrono/io/duration_units.hpp	2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
@@ -16,6 +16,7 @@
 #include <boost/chrono/io/ios_base_state.hpp>
 #include <string>
 #include <iostream>
+#include <ios>
 //#include <locale>
 #include <boost/utility/enable_if.hpp>
 #include <algorithm>
@@ -136,6 +137,7 @@
     template <typename CharT=char, class OutputIterator = std::ostreambuf_iterator<CharT> >
     class duration_units: public std::locale::facet
     {
+      static duration_units* global_;
     public:
       typedef CharT char_type;
       typedef OutputIterator iter_type;
@@ -147,6 +149,50 @@
       {
       }
 
+      /**
+       * @Return Gets the global duration_units,
+       * used when the stream has no associated duration_units facet.
+       * @Throws an exception if the global is 0.
+      Ê
+      */
+      static duration_units* global()
+      {
+        return global_;
+      }
+
+      /**
+      If the facet is not 0, sets the new global duration_units, after deleting the preceding one. This is used when the stream has no associated duration_units facet.
+      Otherwise throw an exception.
+      */
+      static void global(duration_units* ptr)
+      {
+        global_ = ptr;
+      }
+
+      /**
+       * Factory cloning a the global instance.
+       * @return a clone of the global instance.
+       */
+      static duration_units* make()
+      {
+        return global_->clone();;
+      }
+
+      /**
+       * imbue a clone of this facet in @c ios.
+       * @param ios the ios to imbue.
+       */
+#if defined BOOST_CHRONO_USES_DURATION_UNITS_GLOBAL
+      // FIXME: This cause a linker problem on compilers other than clang-3.0 c++03 or c++0x
+      static duration_units<CharT,OutputIterator> const& imbue_if_has_not(std::ios_base& ios)
+      {
+        if (!std::has_facet<duration_units<CharT,OutputIterator> >(ios.getloc()))
+          ios.imbue(std::locale(ios.getloc(), make()));
+        return std::use_facet<duration_units<CharT,OutputIterator> >(ios.getloc());
+      }
+#else
+      static inline duration_units<CharT,OutputIterator> const& imbue_if_has_not(std::ios_base& ios);
+#endif
       /* TBR */
       virtual bool swaps_value_unit_order() const = 0;
 
@@ -245,6 +291,10 @@
       }
 
     protected:
+
+      virtual ~duration_units() {}
+      virtual duration_units<CharT, OutputIterator>* clone() const = 0;
+
       virtual std::basic_string<CharT> do_get_pattern() const=0;
       virtual std::size_t do_get_plural_forms() const = 0;
       virtual std::size_t do_get_plural_form(int_least64_t value) const = 0;
@@ -315,6 +365,8 @@
     template <typename CharT, class OutputIterator>
     std::locale::id duration_units<CharT, OutputIterator>::id;
 
+
+
     ///////////////////////////
     // This class is used to define the strings for the default English
     template <typename CharT=char, class OutputIterator = std::ostreambuf_iterator<CharT> >
@@ -328,12 +380,19 @@
         duration_units<CharT, OutputIterator> (refs)
       {
       }
+      ~duration_units_default() {}
+
       bool swaps_value_unit_order() const
       {
         return false;
       }
 
     protected:
+      duration_units<CharT, OutputIterator>* clone() const
+      {
+        return new duration_units_default<CharT, OutputIterator>();
+      }
+
       std::size_t do_get_plural_forms() const
       {
         return 2;
@@ -801,6 +860,21 @@
 
     };
 
+    template <typename CharT, class OutputIterator>
+    duration_units<CharT, OutputIterator>* duration_units<CharT, OutputIterator>::global_=new duration_units_default<CharT, OutputIterator>();
+
+#if ! defined BOOST_CHRONO_USES_DURATION_UNITS_GLOBAL
+    template <typename CharT, class OutputIterator>
+    duration_units<CharT,OutputIterator> const&
+    duration_units<CharT, OutputIterator>::imbue_if_has_not(std::ios_base& ios)
+    {
+        if (!std::has_facet<duration_units<CharT,OutputIterator> >(ios.getloc())) ios.imbue(
+            std::locale(ios.getloc(), new duration_units_default<CharT,OutputIterator>()));
+        return std::use_facet<duration_units<CharT,OutputIterator> >(ios.getloc());
+    }
+
+#endif
+
 #if   defined BOOST_CHRONO_IS_LOCALIZABLE_VIRTUAL
 
   template <typename CharT, typename T>
Modified: trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp
==============================================================================
--- trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp	(original)
+++ trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp	2011-11-03 18:39:07 EDT (Thu, 03 Nov 2011)
@@ -24,19 +24,32 @@
   namespace chrono
   {
 
+    /**
+     * @c ios_base_state_ptr is a smart pointer to a ios_base specific state.
+     */
     template<typename T>
     class ios_base_state_ptr
     {
     public:
+      /**
+       * Explicit constructor.
+       * @param ios the ios
+       * @Effects Constructs a @c ios_base_state_ptr by storing the associated @c ios.
+       */
       explicit ios_base_state_ptr(std::ios_base& ios) :
         ios_(ios)
       {
       }
-      //ios_base_state_ptr(std::ios_base ios, void (*cleanup_function)(T*));
       ~ios_base_state_ptr()
       {
       }
 
+      /**
+       * @Effects Allocates the index if not already done
+       * Registers the callback responsible of maintaining the state pointer coherency, if not already done.
+       * Retrieves the associated ios pointer
+       * @return the retrieved pointer.
+       */
       T const* get() const BOOST_NOEXCEPT
       {
         register_once(index(), ios_);
@@ -57,6 +70,10 @@
         }
         return static_cast<T*> (pw);
       }
+      /**
+       * @Effects as if @c return get();
+       * @return the retrieved pointer.
+       */
       T * operator->() BOOST_NOEXCEPT
       {
         return get();
@@ -66,6 +83,11 @@
         return get();
       }
 
+      /**
+       * @Effects as if @c return *get();
+       * @return a reference to the retrieved state.
+       * @Remark The behavior is undefined if @c get()==0.
+       */
       T & operator*() BOOST_NOEXCEPT
       {
         return *get();
@@ -75,6 +97,10 @@
         return *get();
       }
 
+      /**
+       * @Effects reset the current pointer after storing in a temporary variable the pointer to the current state.
+       * @return the stored state pointer.
+       */
       T * release()BOOST_NOEXCEPT
       {
         T const* f = get();
@@ -82,18 +108,23 @@
         return f;
       }
 
-      void reset(T* new_value=0) BOOST_NOEXCEPT
+      /**
+       *
+       * @param new_ptr the new pointer.
+       * @Effects deletes the current state and replace it with the new one.
+       */
+      void reset(T* new_ptr=0) BOOST_NOEXCEPT
       {
         register_once(index(), ios_);
         void*& pw = ios_.pword(index());
-        if (pw != 0)
-        {
-          delete static_cast<T*> (pw);
-        }
-        pw = new_value;
+        delete static_cast<T*> (pw);
+        pw = new_ptr;
       }
 
       //explicit
+      /**
+       * Explicit conversion to bool.
+       */
       operator bool() const BOOST_NOEXCEPT
       {
         return get()!=0;
@@ -177,9 +208,9 @@
     };
 
     /**
-     *
-
-
+     * @c ios_base_state is a non null variant of @c ios_base_state_ptr.
+     * @tparm T
+     * @Requires Must be DefaultConstructible and HeapAllocatable
      */
     template<typename T>
     class ios_base_state : public ios_base_state_ptr<T>
@@ -194,7 +225,6 @@
           this->base_type::reset(new T());
         }
       }
-      //ios_base_state(std::ios_base ios, void (*cleanup_function)(T*));
       ~ios_base_state()
       {
       }
@@ -228,7 +258,7 @@
 
       long flags() const BOOST_NOEXCEPT
       {
-        return get();
+        return value();
       }
       long flags(long v) BOOST_NOEXCEPT
       {
@@ -239,7 +269,7 @@
 
       long setf(long v)
       {
-          long tmp = get();
+          long tmp = value();
           ref() |= v;
           return tmp;
       }
@@ -251,7 +281,7 @@
 
       long setf(long v, long mask)
       {
-          long tmp = get();
+          long tmp = value();
           unsetf(mask);
           ref() |= v & mask;
           return tmp;
@@ -266,7 +296,7 @@
         return ios_;
       }
     private:
-      long get() const BOOST_NOEXCEPT
+      long value() const BOOST_NOEXCEPT
       {
         return ios_.iword(index());
       }