$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r60320 - in sandbox/stm/branches/vbe/boost/stm: . memory_managers synch tx tx_memory_managers
From: vicente.botet_at_[hidden]
Date: 2010-03-07 13:22:53
Author: viboes
Date: 2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
New Revision: 60320
URL: http://svn.boost.org/trac/boost/changeset/60320
Log:
Boost.STM/vbe: 
* added tx_memory_managers
* cleanup
Added:
   sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/
   sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/malloc_mm.hpp   (contents, props changed)
   sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/shared_mm.hpp   (contents, props changed)
   sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/tss_mm.hpp   (contents, props changed)
Removed:
   sandbox/stm/branches/vbe/boost/stm/safe_downcast.hpp
   sandbox/stm/branches/vbe/boost/stm/tx/reference.hpp
Text files modified: 
   sandbox/stm/branches/vbe/boost/stm/language_like.hpp                       |    24 +++++++++++++-----------                
   sandbox/stm/branches/vbe/boost/stm/memory_managers/base_memory_manager.hpp |     5 -----                                   
   sandbox/stm/branches/vbe/boost/stm/synch/synchronized.hpp                  |     1 +                                       
   sandbox/stm/branches/vbe/boost/stm/transaction.hpp                         |    40 +---------------------------------------
   4 files changed, 15 insertions(+), 55 deletions(-)
Modified: sandbox/stm/branches/vbe/boost/stm/language_like.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/language_like.hpp	(original)
+++ sandbox/stm/branches/vbe/boost/stm/language_like.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -233,13 +233,11 @@
 {                                                                               \
     boost::stm::detail::control_flow __boost_stm_ctrl_;                    \
     for(boost::stm::transaction __boost_stm_txn_;;) {                                                                        \
-        \
         try{                                                                    \
             boost::stm::detail::commit_on_destruction __boost_stm_destr_ (__boost_stm_txn_); \
             try{                                                            \
                 do {                                                           \
                     __boost_stm_ctrl_=boost::stm::detail::break_;      \
-                        if(false);else
 
                         // user code here
 
@@ -252,19 +250,23 @@
                 __boost_stm_destr_.release();                              \
                 throw;                                                          \
             } catch(...) {                                                      \
+            if(true) {\
                 if (__boost_stm_txn_.forced_to_abort()) {\
                     __boost_stm_destr_.release();                              \
                 } else {\
                     __boost_stm_destr_.commit();\
                 }\
+            } else {\
+                __boost_stm_destr_.release();\
+            }\
                 throw;                                                          \
             }                                                                   \
             break;                                                                  \
         } catch (boost::stm::aborted_tx &) {                                        \
             if (__boost_stm_txn_.is_nested()) throw;                                              \
             do {                                                                    \
-                __boost_stm_ctrl_=boost::stm::detail::break_;                  \
-                try {throw;}catch (boost::stm::aborted_tx &)
+                __boost_stm_ctrl_=boost::stm::detail::break_;                  
+
 
 
 #define BOOST_STM_E_END_RETRY                                                       \
@@ -273,7 +275,7 @@
             } while ((__boost_stm_ctrl_=boost::stm::detail::continue_),false);     \
         }                                                                               \
         BOOST_ASSERT(__boost_stm_ctrl_ == boost::stm::detail::none);           \
-        if (true) __boost_stm_txn_.restart();                                                               \
+        __boost_stm_txn_.restart();                                                               \
     }                                                       \
     BOOST_ASSERT(__boost_stm_ctrl_ == boost::stm::detail::none);           \
 } void()
@@ -284,7 +286,7 @@
             } while ((__boost_stm_ctrl_=boost::stm::detail::continue_),false);     \
         }                                                                       \
         if (__boost_stm_ctrl_ != boost::stm::detail::none) break;              \
-        if (true) __boost_stm_txn_.restart();                                                               \
+        __boost_stm_txn_.restart();                                                               \
     }                                               \
     if (__boost_stm_ctrl_==boost::stm::detail::continue_) continue;                          \
     if (__boost_stm_ctrl_==boost::stm::detail::break_) break;                           \
@@ -525,10 +527,10 @@
 // deletes the allocated object on transaction TX
 //---------------------------------------------------------------------------
 
-#define BOOST_STM_TX_DELETE_ARRAY(TX, PTR) \
-    (TX).delete_array(PTR)
+#define BOOST_STM_TX_DELETE_ARRAY(TX, PTR, SIZE) \
+    (TX).delete_array(PTR, SIZE)
 
-#define BOOST_STM_E_DELETE_ARRAY(PTR) BOOST_STM_TX_DELETE_ARRAY(__boost_stm_txn_, PTR)
+#define BOOST_STM_E_DELETE_ARRAY(PTR, SIZE) BOOST_STM_TX_DELETE_ARRAY(__boost_stm_txn_, PTR, SIZE)
 
 //---------------------------------------------------------------------------
 // deletes the allocated object on transaction TX
@@ -544,10 +546,10 @@
 // deletes the allocated object on transaction TX
 //---------------------------------------------------------------------------
 
-#define BOOST_STM_DELETE_ARRAY(PTR) \
+#define BOOST_STM_DELETE_ARRAY(PTR, SIZE) \
     if (boost::stm::current_transaction()!=0)  \
         BOOST_STM_TX_DELETE_ARRAY(*boost::stm::current_transaction(), \
-            PTR) \
+            PTR, SIZE) \
     else delete [] PTR
 
 
Modified: sandbox/stm/branches/vbe/boost/stm/memory_managers/base_memory_manager.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/memory_managers/base_memory_manager.hpp	(original)
+++ sandbox/stm/branches/vbe/boost/stm/memory_managers/base_memory_manager.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -33,11 +33,6 @@
 namespace boost { namespace stm {
 
 //-----------------------------------------------------------------------------
-// forward declarations
-//-----------------------------------------------------------------------------
-class transaction;
-
-//-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // this class provides two functions (retrieve_mem and return_mem) and  
 // to manage a pool of memory
Deleted: sandbox/stm/branches/vbe/boost/stm/safe_downcast.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/safe_downcast.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
+++ (empty file)
@@ -1,98 +0,0 @@
-//  boost cast.hpp header file  ----------------------------------------------//
-
-//  (C) Copyright Kevlin Henney and Dave Abrahams 1999.
-//  Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-//  See http://www.boost.org/libs/conversion for Documentation.
-
-
-#ifndef BOOST_SAFE_DOWNCAST__HPP
-#define BOOST_SAFE_DOWNCAST__HPP
-
-# include <boost/config.hpp>
-# include <boost/assert.hpp>
-# include <typeinfo>
-# include <boost/type.hpp>
-# include <boost/limits.hpp>
-# include <boost/detail/select_type.hpp>
-# include <boost/type_traits/is_virtual_base_of.hpp>
-# include <boost/type_traits/remove_pointer.hpp>
-# include <boost/mpl/or.hpp>
-
-# include <boost/cast.hpp>
-# include <boost/serialization/smart_cast.hpp>
-
-
-
-//  It has been demonstrated numerous times that MSVC 6.0 fails silently at link
-//  time if you use a template function which has template parameters that don't
-//  appear in the function's argument list.
-//
-//  TODO: Add this to config.hpp?
-# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
-#  define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
-# else
-#  define BOOST_EXPLICIT_DEFAULT_TARGET
-# endif
-
-namespace boost
-{
-
-//  safe_polymorphic_downcast  --------------------------------------------------------//
-
-// When the Base class is virtual inherited we need to use dynamic_cast to downcast.
-// Of course as most of the time the Derived class don't inherit virtualy from BASE a static_cast is enough
-
-    namespace detail {
-        template <typename IsVirtualBaseOf, class Target, class Source>
-        struct safe_polymorphic_downcast;
-
-        template <class Target, class Source>
-        struct safe_polymorphic_downcast<true_type, Target,Source> {
-            inline static Target apply(Source* x ) {
-                return dynamic_cast<Target>(x);
-            }
-        };
-        template <class Target, class Source>
-        struct safe_polymorphic_downcast<false_type, Target,Source> {
-            inline static Target apply(Source* x ) {
-                return static_cast<Target>(x);
-                //return polymorphic_downcast<Target>(x);
-            }
-        };
-
-    }
-    template <class Target, class Source>
-    inline Target safe_polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
-    {
-        #if 1
-        return serialization::smart_cast<Target, Source*>(x);
-        #else
-        typedef typename is_virtual_base_of<Source, typename remove_pointer<Target>::type >::type IsVirtualBaseOf;
-        return detail::safe_polymorphic_downcast<true_type,Target,Source>::apply(x);
-        #endif
-    }
-
-    template <class Target, class Inter, class Source>
-    inline Target safe_polymorphic_downcast_2(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
-    {
-        typedef typename is_virtual_base_of<Source, Inter >::type IsVirtualBaseOf;
-        return detail::safe_polymorphic_downcast<IsVirtualBaseOf,Target,Source>::apply(x);
-    }
-
-    template <class Target, class Inter1, class Inter2, class Source>
-    inline Target safe_polymorphic_downcast_3(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
-    {
-        typedef integral_constant<bool,
-                                is_virtual_base_of<Source, Inter1>::type::value || is_virtual_base_of<Source, Inter2>::type::value
-                            > IsVirtualBaseOf;
-        return detail::safe_polymorphic_downcast<IsVirtualBaseOf,Target,Source>::apply(x);
-    }
-
-#  undef BOOST_EXPLICIT_DEFAULT_TARGET
-
-} // namespace boost
-
-#endif  // BOOST_CAST_HPP
Modified: sandbox/stm/branches/vbe/boost/stm/synch/synchronized.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/synch/synchronized.hpp	(original)
+++ sandbox/stm/branches/vbe/boost/stm/synch/synchronized.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -57,6 +57,7 @@
 #define BOOST_STM_TRY_TO_SYNCHRONIZE_VAR_UNTIL(VAR, LOCKABLE, ABS_TIME) \
     BOOST_STM_TRY_TO_SYNCHRONIZE_TYPE_UNTIL(pthread_mutex_t, VAR, LOCKABLE, ABS_TIME)
 #endif
+
 #define BOOST_STM_SYNCHRONIZE(LOCKABLE) \
     BOOST_STM_SYNCHRONIZE_VAR(_, LOCKABLE)
 #define BOOST_STM_ADOPT_SYNCHRONIZE(LOCKABLE) \
Modified: sandbox/stm/branches/vbe/boost/stm/transaction.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/transaction.hpp	(original)
+++ sandbox/stm/branches/vbe/boost/stm/transaction.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -2335,45 +2335,6 @@
 inline void unlock(M& m, latm::mutex_type& lock) {transaction::unlock(m, lock);}
 
 
-#if defined(BOOST_STM_USE_SPECIFIC_TRANSACTION_MEMORY_MANAGER)
-template <class T> T* cache_allocate(transaction& t) {
-    #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER) && defined (USE_STM_MEMORY_MANAGER)
-    T* res=  reinterpret_cast<T*>(base_memory_manager::retrieve_mem(sizeof(T)));
-    if (res==0) throw std::bad_alloc();
-    return res;
-    #elif defined(BOOST_STM_CACHE_USE_MALLOC)
-    T* res= reinterpret_cast<T*>(malloc(sizeof(T)));
-    if (res==0) throw std::bad_alloc();
-    return res;
-    //return  reinterpret_cast<T*>(::new char[sizeof(T)]);
-    #elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
-    T* res=   reinterpret_cast<T*>(t.context_.mstorage_.allocate<T>());
-    if (res==0) throw std::bad_alloc();
-    return res;
-    #else
-    return 0;
-    #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER, BOOST_STM_CACHE_USE_MALLOC or BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER must be defined"
-    #endif
-}
-#endif
-
-#if defined(BOOST_STM_USE_SPECIFIC_TRANSACTION_MEMORY_MANAGER)
-
-template <class T>
-inline void cache_deallocate(T* ptr) {
-    if (ptr) {
-    #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER) && defined (USE_STM_MEMORY_MANAGER)
-        base_memory_manager::return_mem(ptr,sizeof(T));
-    #elif defined(BOOST_STM_CACHE_USE_MALLOC)
-        free(ptr);
-        //delete [] ptr;
-    #elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
-    #else
-    #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER, BOOST_STM_CACHE_USE_MALLOC or BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER must be defined"
-    #endif
-        }
-}
-#endif
 
 inline void cache_release(base_transaction_object* ptr) {
     if (ptr==0) return ;
@@ -2419,6 +2380,7 @@
 } // stm  namespace
 } // boost namespace
 
+#include <boost/stm/tx_memory_manager.hpp>
 #include <boost/stm/detail/transaction_impl.hpp>
 #include <boost/stm/detail/latm_general_impl.hpp>
 
Deleted: sandbox/stm/branches/vbe/boost/stm/tx/reference.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/tx/reference.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
+++ (empty file)
@@ -1,133 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Justin E. Gottchlich 2009.
-// (C) Copyright Vicente J. Botet Escriba 2009.
-// Distributed under the Boost
-// Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or
-// copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-// See http://www.boost.org/libs/stm for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_STM_TX_REFERENCE__HPP
-#define BOOST_STM_TX_REFERENCE__HPP
-
-//-----------------------------------------------------------------------------
-#include <boost/stm/transaction.hpp>
-#include <boost/stm/transaction_object.hpp>
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-namespace boost { namespace stm { namespace tx {
-
-//-----------------------------------------------------------------------------
-// mixin transactional object class that wraps a object type providing
-// a transparent transactional view on a transactional context
-// a non-transactional view on a non-transactional context
-// Note: the sizeof(object<T>)>>>>=sizeof(T)
-//-----------------------------------------------------------------------------
-template <typename Final, typename T, typename Base=base_transaction_object>
-class reference : public transaction_object< Final, Base >
-{
-protected:
-public:
-    T val_;
-public:
-    typedef reference<Final, T, Base> this_type;
-    typedef Final final_type;
-    typedef T value_type;
-    //-----------------------------------------------------------------------------
-    reference() : val_() {}
-
-    reference(reference const& r) : val_(r.value()) {}
-    template<typename F, typename U>
-    reference(reference<F,U> const& r) : val_(r.value()) {}
-    reference(T v) : val_(v) {}
-    // contructor from a convertible to T
-    template <typename U>
-    reference(U v) : val_(v) {}
-
-    reference& operator=(reference const& rhs) {
-        if (this!=&rhs) {
-            ref()=rhs.value();
-        }
-        return *this;
-    }
-    template<typename F, typename U>
-    reference& operator=(reference<F,U> const& rhs) {
-        ref()=rhs.value();
-        return *this;
-    }
-       
-    operator T() const { return value(); }
-    operator T&() { return ref(); }
-
-    //-----------------------------------------------------------------------------
-    // accessors
-    T& ref() {
-        transaction* tx=current_transaction();
-        if (tx!=0 && tx->in_flight()) {
-            if (tx->forced_to_abort()) {
-                tx->lock_and_abort();
-                throw aborted_transaction_exception("aborting transaction");
-            }
-
-            return tx->write(*static_cast<Final*>(this)).val_;
-        }
-        return val_;
-    }
-
-    T* address_of() {
-        return &val_;
-    }
-    //-----------------------------------------------------------------------------
-    T value() const {
-        transaction* tx=current_transaction();
-        if (tx!=0 && tx->in_flight()) {
-            if (tx->forced_to_abort()) {
-                tx->lock_and_abort();
-                throw aborted_transaction_exception("aborting transaction");
-            }
-            return tx->read(*static_cast<Final const*>(this)).val_;
-        }
-        return val_;
-    }
-    // shallow copy
-    reference(reference const& rhs, stm::shallow_t)
-    : val_(rhs.val_)
-    {}
-    // shallow assignment
-    reference& shallow_assign(reference const& rhs)
-    {
-        val_=rhs.val_;
-        return *this;
-    }
-};
-
-//~ template <typename OSTREAM, typename F, typename T, typename B>
-//~ OSTREAM& operator<<(OSTREAM& os, reference<F, T, B> const& r) {
-    //~ os << r.value();
-    //~ return os;
-//~ }
-//~ template <typename ISTREAM, typename F, typename T, typename B>
-//~ ISTREAM& operator>>(ISTREAM& is, reference<F, T, B> & r) {
-    //~ T v;
-    //~ is >> v;
-    //~ r=v;
-    //~ return is;
-//~ }
-
-
-}
-// shallow trait
-template <typename F, typename T, typename B>
-struct has_shallow_copy_semantics<tx::reference<F,T,B> > : boost::mpl::true_
-{};
-
-    
-}}
-#endif //BOOST_STM_TX_REFERENCE__HPP
-
-
Added: sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/malloc_mm.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/malloc_mm.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Justin E. Gottchlich 2009.
+// (C) Copyright Vicente J. Botet Escriba 2009.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/stm for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_TX_ALLOC_MM__HPP
+#define BOOST_STM_TX_ALLOC_MM__HPP
+
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+class transaction;
+
+struct malloc_mm {
+    template <class T> 
+    static T* allocate(transaction& t) {
+        T* res= reinterpret_cast<T*>(malloc(sizeof(T)));
+        if (res==0) throw std::bad_alloc();
+        return res;
+    }
+
+    template <class T>
+    static void deallocate(T* ptr) {
+        if (ptr) {
+            free(ptr);
+        }
+    }
+
+};
+} // stm  namespace
+} // boost namespace
+
+///////////////////////////////////////////////////////////////////////////////
+#endif // BOOST_STM_TX_ALLOC_MM__HPP
+
+
Added: sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/shared_mm.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/shared_mm.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Justin E. Gottchlich 2009.
+// (C) Copyright Vicente J. Botet Escriba 2009.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/stm for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_TX_ALLOC_MM__HPP
+#define BOOST_STM_TX_ALLOC_MM__HPP
+
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+class transaction;
+
+struct shared_mm {
+    template <class T> 
+    static T* allocate(transaction& t) {
+        T* res=  reinterpret_cast<T*>(base_memory_manager::retrieve_mem(sizeof(T)));
+        if (res==0) throw std::bad_alloc();
+        return res;
+    }
+
+    template <class T>
+    static void deallocate(T* ptr) {
+        if (ptr) {
+            base_memory_manager::return_mem(ptr,sizeof(T));
+        }
+    }
+};
+} // stm  namespace
+} // boost namespace
+
+///////////////////////////////////////////////////////////////////////////////
+#endif // BOOST_STM_TX_ALLOC_MM__HPP
+
+
Added: sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/tss_mm.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/branches/vbe/boost/stm/tx_memory_managers/tss_mm.hpp	2010-03-07 13:22:52 EST (Sun, 07 Mar 2010)
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Justin E. Gottchlich 2009.
+// (C) Copyright Vicente J. Botet Escriba 2009.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/stm for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_TX_ALLOC_MM__HPP
+#define BOOST_STM_TX_ALLOC_MM__HPP
+
+//-----------------------------------------------------------------------------
+
+#include <boost/stm/transaction.hpp>
+
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+struct tss_mm {
+    template <class T> 
+    static T* allocate(transaction& t) {
+        T* res=   reinterpret_cast<T*>(t.context_.mstorage_.allocate<T>());
+        if (res==0) throw std::bad_alloc();
+        return res;
+    }
+
+    template <class T>
+    static void deallocate(T* ptr) {
+        // no action as the mm is monotonic
+    }
+};
+
+} // stm  namespace
+} // boost namespace
+
+///////////////////////////////////////////////////////////////////////////////
+#endif // BOOST_STM_TX_ALLOC_MM__HPP
+
+