Boost logo

Boost-Commit :

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());
       }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk