platform/include/pion/platform/Event.hpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #ifndef __PION_EVENT_HEADER__
00021 #define __PION_EVENT_HEADER__
00022 
00023 #include <list>
00024 #include <vector>
00025 #include <boost/bind.hpp>
00026 #include <boost/function.hpp>
00027 #ifdef _MSC_VER
00028     #pragma warning(push)
00029     #pragma warning(disable: 4181) // qualifier applied to reference type
00030 #endif
00031 #include <boost/variant.hpp>
00032 #ifdef _MSC_VER
00033     #pragma warning(pop)
00034 #endif
00035 #include <boost/thread/once.hpp>
00036 #include <boost/thread/mutex.hpp>
00037 #include <boost/utility/enable_if.hpp>
00038 #include <boost/detail/atomic_count.hpp>
00039 #include <boost/iterator/iterator_facade.hpp>
00040 #include <boost/intrusive/rbtree_algorithms.hpp>
00041 #include <pion/PionConfig.hpp>
00042 #include <pion/PionBlob.hpp>
00043 #include <pion/PionDateTime.hpp>
00044 #include <pion/platform/Vocabulary.hpp>
00045 
00046 
00048 #ifndef _WIN64
00049 #define PION_EVENT_USE_POOL_ALLOCATORS
00050 #endif
00051 
00052 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
00053     #include <boost/thread/tss.hpp>
00054     #include <pion/PionPoolAllocator.hpp>
00055 #else
00056     #include <cstdlib>
00057 #endif
00058 
00059 
00060 namespace pion {        // begin namespace pion
00061 namespace platform {    // begin namespace platform (Pion Platform Library)
00062 
00063     
00067 template <typename CharType, typename AllocType>
00068 class BasicEvent
00069     : private boost::noncopyable
00070 {
00071 public:
00072 
00074     struct ParameterNode;
00075     
00077     class TermTypeNotSerializableException : public std::exception {
00078     public:
00079         virtual const char* what() const throw() {
00080             return "Term type is not serializable";
00081         }
00082     };
00083     
00084 
00085 protected:
00086 
00088     template <typename NodeType>
00089     class IteratorBase :
00090         public boost::iterator_facade<IteratorBase<NodeType>, NodeType,
00091             boost::bidirectional_traversal_tag>
00092     {
00093     private:
00094         
00096         struct enabler {};
00097         
00098     public:
00099         
00101         IteratorBase(void) { tree_algo::init(&m_param_ptr); }
00102         
00104         explicit IteratorBase(NodeType *p) : m_param_ptr(p) {}
00105         
00107         template <class OtherNodeType>
00108         IteratorBase(IteratorBase<OtherNodeType> const& other,
00109                      typename boost::enable_if<
00110                         boost::is_convertible<OtherNodeType*,NodeType*>,
00111                      enabler>::type = enabler()
00112                      )
00113             : m_param_ptr(other.m_param_ptr)
00114         {}
00115         
00116     private:
00117         
00119         inline void increment(void) {
00120             m_param_ptr = tree_algo::next_node(const_cast<ParameterNode*>(m_param_ptr));
00121         }
00122         
00124         inline void decrement(void) {
00125             m_param_ptr = tree_algo::prev_node(const_cast<ParameterNode*>(m_param_ptr));
00126         }
00127         
00129         template <class OtherValue>
00130         inline bool equal(IteratorBase<OtherValue> const& other) const {
00131             return this->m_param_ptr == other.m_param_ptr;
00132         }
00133         
00135         NodeType& dereference(void) const {
00136             return *m_param_ptr;
00137         }
00138         
00140         friend class boost::iterator_core_access;
00141         
00144         friend class IteratorBase<const ParameterNode>;
00145         friend class IteratorBase<ParameterNode>;
00146 
00148         NodeType *      m_param_ptr;
00149     };
00150 
00151 
00152 public:
00153 
00155     typedef Vocabulary::TermRef             EventType;
00156     
00158     typedef PionBlob<CharType,AllocType>    BlobType;
00159 
00161     typedef typename BlobType::BlobParams   BlobParams;
00162     
00168     typedef boost::variant<boost::int32_t, boost::uint32_t,
00169         boost::int64_t, boost::uint64_t, float, double, long double,
00170         PionDateTime, BlobType>             ParameterValue;
00171     
00177     struct ParameterNode {
00179         ParameterNode(void) {}
00180         
00182         template <typename T>
00183         ParameterNode(const Vocabulary::TermRef& tr, const T& v) :
00184             term_ref(tr), value(v)
00185         {}
00186 
00188         ParameterNode *         m_parent_ptr;
00190         ParameterNode *         m_left_ptr;
00192         ParameterNode *         m_right_ptr;
00194         boost::uint8_t          m_tree_color;
00195 
00197         Vocabulary::TermRef     term_ref;
00198 
00200         ParameterValue          value;
00201     };
00202     
00204     typedef IteratorBase<ParameterNode>         Iterator;
00205 
00207     typedef IteratorBase<ParameterNode const>   ConstIterator;
00208     
00210     typedef std::pair<ConstIterator, ConstIterator>
00211                                                 ValuesRange;
00212     
00219     BasicEvent(const EventType t, AllocType *alloc_ptr)
00220         : m_event_type(t), m_alloc_ptr(alloc_ptr), m_references(0)
00221     {
00222         // create an empty parameter tree
00223         tree_algo::init_header(&m_param_tree);
00224     }
00225     
00227     ~BasicEvent() { clear(); }
00228     
00230     inline EventType getType(void) const { return m_event_type; }
00231 
00233     inline bool empty(void) const {
00234         return (tree_algo::begin_node(&m_param_tree) == &m_param_tree);
00235     }
00236     
00238     inline ConstIterator begin(void) const {
00239         return ConstIterator(tree_algo::begin_node(&m_param_tree));
00240     }
00241     
00243     inline ConstIterator end(void) const {
00244         return ConstIterator(tree_algo::end_node(&m_param_tree));
00245     }
00246 
00248     inline void clear(void) {
00249         tree_algo::clear_and_dispose(&m_param_tree,
00250             boost::bind(&BasicEvent<CharType,AllocType>::destroyParameter, this, _1));
00251     }
00252 
00258     inline void clear(const Vocabulary::TermRef& term_ref) {
00259         ParameterNode *node_ptr;
00260         std::pair<ParameterNode*, ParameterNode*> range =
00261             tree_algo::equal_range(&m_param_tree, term_ref, m_key_compare);
00262         while (range.first != range.second) {
00263             node_ptr = range.first;
00264             range.first = tree_algo::next_node(range.first);
00265             tree_algo::erase(&m_param_tree, node_ptr);
00266             destroyParameter(node_ptr);
00267         }
00268     }
00269 
00276     inline ConstIterator find(const Vocabulary::TermRef& term_ref) const {
00277         return ConstIterator(tree_algo::find(&m_param_tree, term_ref, m_key_compare));
00278     }
00279     
00287     inline ValuesRange equal_range(const Vocabulary::TermRef& term_ref) const
00288     {
00289         std::pair<ParameterNode*, ParameterNode*> range =
00290             tree_algo::equal_range(&m_param_tree, term_ref, m_key_compare);
00291         return std::make_pair(Iterator(range.first), Iterator(range.second));
00292     }
00293 
00299     inline void for_each(boost::function2<void, Vocabulary::TermRef, const ParameterValue&> f) const {
00300         for (ParameterNode *node_ptr = tree_algo::begin_node(&m_param_tree);
00301             node_ptr != tree_algo::end_node(&m_param_tree);
00302             node_ptr = tree_algo::next_node(node_ptr))
00303         {
00304             f(node_ptr->term_ref, node_ptr->value);
00305         }
00306     }
00307 
00314     inline BasicEvent& operator+=(const BasicEvent& e) {
00315         ParameterNode *new_param_ptr;
00316         for (ParameterNode *node_ptr = tree_algo::begin_node(&e.m_param_tree);
00317             node_ptr != tree_algo::end_node(&e.m_param_tree);
00318             node_ptr = tree_algo::next_node(node_ptr))
00319         {
00320             new_param_ptr = createParameter(node_ptr->term_ref, node_ptr->value);
00321             tree_algo::insert_equal_upper_bound(&m_param_tree,
00322                 new_param_ptr, m_item_compare);
00323         }
00324         return *this;
00325     }
00326 
00333     inline void copyValues(const BasicEvent& e, const Vocabulary::TermRef& term_ref)
00334     {
00335         std::pair<ParameterNode*, ParameterNode*> range =
00336             tree_algo::equal_range(&e.m_param_tree, term_ref, e.m_key_compare);
00337         ParameterNode *new_param_ptr;
00338         while (range.first != range.second) {
00339             new_param_ptr = createParameter(range.first->term_ref, range.first->value);
00340             tree_algo::insert_equal_upper_bound(&m_param_tree,
00341                 new_param_ptr, m_item_compare);
00342             range.first = tree_algo::next_node(range.first);
00343         }
00344     }
00345     
00353     inline const ParameterValue *getPointer(const Vocabulary::TermRef& term_ref) const {
00354         const ParameterNode *node_ptr = tree_algo::find(&m_param_tree, term_ref, m_key_compare);
00355         return (node_ptr==&m_param_tree ? NULL : &(node_ptr->value));
00356     }
00357     
00364     inline bool isDefined(const Vocabulary::TermRef& term_ref) const {
00365         return (tree_algo::find(&m_param_tree, term_ref, m_key_compare) != &m_param_tree);
00366     }
00367         
00374     inline const boost::int32_t& getInt(const Vocabulary::TermRef& term_ref) const {
00375         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<boost::int32_t>(getPointer(term_ref)));
00376         return boost::get<const boost::int32_t&>(*getPointer(term_ref));
00377     }
00378     
00385     inline const boost::uint32_t& getUInt(const Vocabulary::TermRef& term_ref) const {
00386         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<boost::uint32_t>(getPointer(term_ref)));
00387         return boost::get<const boost::uint32_t&>(*getPointer(term_ref));
00388     }
00389     
00396     inline const boost::int64_t& getBigInt(const Vocabulary::TermRef& term_ref) const {
00397         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<boost::int64_t>(getPointer(term_ref)));
00398         return boost::get<const boost::int64_t&>(*getPointer(term_ref));
00399     }
00400     
00407     inline const boost::uint64_t& getUBigInt(const Vocabulary::TermRef& term_ref) const {
00408         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<boost::uint64_t>(getPointer(term_ref)));
00409         return boost::get<const boost::uint64_t&>(*getPointer(term_ref));
00410     }
00411     
00418     inline const float& getFloat(const Vocabulary::TermRef& term_ref) const {
00419         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<float>(getPointer(term_ref)));
00420         return boost::get<const float&>(*getPointer(term_ref));
00421     }
00422 
00429     inline const double& getDouble(const Vocabulary::TermRef& term_ref) const {
00430         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<double>(getPointer(term_ref)));
00431         return boost::get<const double&>(*getPointer(term_ref));
00432     }
00433     
00440     inline const long double& getLongDouble(const Vocabulary::TermRef& term_ref) const {
00441         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<long double>(getPointer(term_ref)));
00442         return boost::get<const long double&>(*getPointer(term_ref));
00443     }
00444     
00451     inline const PionDateTime& getDateTime(const Vocabulary::TermRef& term_ref) const {
00452         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<const PionDateTime&>(getPointer(term_ref)));
00453         return boost::get<const PionDateTime&>(*getPointer(term_ref));
00454     }
00455     
00462     inline const CharType *getString(const Vocabulary::TermRef& term_ref) const {
00463         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<const BlobType&>(getPointer(term_ref)));
00464         return boost::get<const BlobType&>(*getPointer(term_ref)).get();
00465     }
00466     
00473     inline const BlobType& getBlob(const Vocabulary::TermRef& term_ref) const {
00474         PION_ASSERT(getPointer(term_ref)!=NULL && boost::get<const BlobType&>(getPointer(term_ref)));
00475         return boost::get<const BlobType&>(*getPointer(term_ref));
00476     }
00477     
00486     template <typename T>
00487     inline bool getInt(const Vocabulary::TermRef& term_ref, T& v) const {
00488         const ParameterValue *param_ptr = getPointer(term_ref);
00489         if (param_ptr) {
00490             v = boost::get<const boost::int32_t&>(*param_ptr);
00491             return true;
00492         }
00493         return false;
00494     }
00495     
00504     template <typename T>
00505     inline bool getUInt(const Vocabulary::TermRef& term_ref, T& v) const {
00506         const ParameterValue *param_ptr = getPointer(term_ref);
00507         if (param_ptr) {
00508             v = boost::get<const boost::uint32_t&>(*param_ptr);
00509             return true;
00510         }
00511         return false;
00512     }
00513     
00522     template <typename T>
00523     inline bool getBigInt(const Vocabulary::TermRef& term_ref, T& v) const {
00524         const ParameterValue *param_ptr = getPointer(term_ref);
00525         if (param_ptr) {
00526             v = boost::get<const boost::int64_t&>(*param_ptr);
00527             return true;
00528         }
00529         return false;
00530     }
00531     
00540     template <typename T>
00541     inline bool getUBigInt(const Vocabulary::TermRef& term_ref, T& v) const {
00542         const ParameterValue *param_ptr = getPointer(term_ref);
00543         if (param_ptr) {
00544             v = boost::get<const boost::uint64_t&>(*param_ptr);
00545             return true;
00546         }
00547         return false;
00548     }
00549     
00558     template <typename T>
00559     inline bool getFloat(const Vocabulary::TermRef& term_ref, T& v) const {
00560         const ParameterValue *param_ptr = getPointer(term_ref);
00561         if (param_ptr) {
00562             v = boost::get<const float&>(*param_ptr);
00563             return true;
00564         }
00565         return false;
00566     }
00567 
00576     template <typename T>
00577     inline bool getDouble(const Vocabulary::TermRef& term_ref, T& v) const {
00578         const ParameterValue *param_ptr = getPointer(term_ref);
00579         if (param_ptr) {
00580             v = boost::get<const double&>(*param_ptr);
00581             return true;
00582         }
00583         return false;
00584     }
00585     
00594     template <typename T>
00595     inline bool getLongDouble(const Vocabulary::TermRef& term_ref, T& v) const {
00596         const ParameterValue *param_ptr = getPointer(term_ref);
00597         if (param_ptr) {
00598             v = boost::get<const long double&>(*param_ptr);
00599             return true;
00600         }
00601         return false;
00602     }
00603     
00612     template <typename T>
00613     inline bool getDateTime(const Vocabulary::TermRef& term_ref, T& v) const {
00614         const ParameterValue *param_ptr = getPointer(term_ref);
00615         if (param_ptr) {
00616             v = boost::get<const PionDateTime&>(*param_ptr);
00617             return true;
00618         }
00619         return false;
00620     }
00621     
00630     template <typename T>
00631     inline bool getBlob(const Vocabulary::TermRef& term_ref, T& v) const {
00632         const ParameterValue *param_ptr = getPointer(term_ref);
00633         if (param_ptr) {
00634             v = boost::get<const BlobType&>(*param_ptr);
00635             return true;
00636         }
00637         return false;
00638     }
00639 
00648     inline bool getBlob(const Vocabulary::TermRef& term_ref, std::string& str) const {
00649         const ParameterValue *param_ptr = getPointer(term_ref);
00650         if (param_ptr) {
00651             str = boost::get<const BlobType&>(*param_ptr).get();
00652             return true;
00653         }
00654         return false;
00655     }
00656 
00665     template <typename T>
00666     inline bool getString(const Vocabulary::TermRef& term_ref, T& v) const {
00667         return getBlob(term_ref, v);
00668     }
00669 
00678     inline bool getString(const Vocabulary::TermRef& term_ref, std::string& str) const {
00679         return getBlob(term_ref, str);
00680     }
00681 
00688     template <typename T>
00689     inline void setInt(const Vocabulary::TermRef& term_ref, T value) {
00690         insert(term_ref, boost::int32_t(value));
00691     }
00692 
00699     inline void setInt(const Vocabulary::TermRef& term_ref, const std::string& value) {
00700         insert(term_ref, boost::lexical_cast<boost::int32_t>(value));
00701     }
00702 
00709     template <typename T>
00710     inline void setUInt(const Vocabulary::TermRef& term_ref, T value) {
00711         insert(term_ref, boost::uint32_t(value));
00712     }
00713     
00720     inline void setUInt(const Vocabulary::TermRef& term_ref, const std::string& value) {
00721         insert(term_ref, boost::lexical_cast<boost::uint32_t>(value));
00722     }
00723     
00730     template <typename T>
00731     inline void setBigInt(const Vocabulary::TermRef& term_ref, T value) {
00732         insert(term_ref, boost::int64_t(value));
00733     }
00734     
00741     inline void setBigInt(const Vocabulary::TermRef& term_ref, const std::string& value) {
00742         insert(term_ref, boost::lexical_cast<boost::int64_t>(value));
00743     }
00744     
00751     template <typename T>
00752     inline void setUBigInt(const Vocabulary::TermRef& term_ref, T value) {
00753         insert(term_ref, boost::uint64_t(value));
00754     }
00755     
00762     inline void setUBigInt(const Vocabulary::TermRef& term_ref, const std::string& value) {
00763         insert(term_ref, boost::lexical_cast<boost::uint64_t>(value));
00764     }
00765     
00772     inline void setFloat(const Vocabulary::TermRef& term_ref, const float value) {
00773         insert(term_ref, value);
00774     }
00775     
00782     inline void setFloat(const Vocabulary::TermRef& term_ref, const std::string& value) {
00783         insert(term_ref, boost::lexical_cast<float>(value));
00784     }
00785     
00792     inline void setDouble(const Vocabulary::TermRef& term_ref, const double value) {
00793         insert(term_ref, value);
00794     }
00795 
00802     inline void setDouble(const Vocabulary::TermRef& term_ref, const std::string& value) {
00803         insert(term_ref, boost::lexical_cast<double>(value));
00804     }
00805 
00812     inline void setLongDouble(const Vocabulary::TermRef& term_ref, const long double value) {
00813         insert(term_ref, value);
00814     }
00815     
00822     inline void setLongDouble(const Vocabulary::TermRef& term_ref, const std::string& value) {
00823         insert(term_ref, boost::lexical_cast<long double>(value));
00824     }
00825     
00832     inline void setDateTime(const Vocabulary::TermRef& term_ref, const PionDateTime& value) {
00833         insert(term_ref, value);
00834     }
00835     
00843     inline void setBlob(const Vocabulary::TermRef& term_ref,
00844                           const CharType *value, std::size_t len)
00845     {
00846         insert(term_ref, make_blob(value, len));
00847     }
00848     
00855     inline void setBlob(const Vocabulary::TermRef& term_ref, const CharType *value) {
00856         insert(term_ref, make_blob(value, strlen(value)));
00857     }
00858     
00865     inline void setBlob(const Vocabulary::TermRef& term_ref, const std::string& value) {
00866         insert(term_ref, make_blob(value));
00867     }
00868     
00875     inline void setBlob(const Vocabulary::TermRef& term_ref, const BlobType& value) {
00876         insert(term_ref, value);
00877     }
00878     
00886     inline void setString(const Vocabulary::TermRef& term_ref,
00887                           const CharType *value, std::size_t len)
00888     {
00889         setBlob(term_ref, value, len);
00890     }
00891     
00898     inline void setString(const Vocabulary::TermRef& term_ref, const CharType *value) {
00899         setBlob(term_ref, value);
00900     }
00901     
00908     inline void setString(const Vocabulary::TermRef& term_ref, const std::string& value) {
00909         setBlob(term_ref, value);
00910     }
00911     
00918     inline void setString(const Vocabulary::TermRef& term_ref, const BlobType& value) {
00919         setBlob(term_ref, value);
00920     }
00921     
00929     inline void set(const Vocabulary::Term& t, const std::string& value)
00930     {
00931         switch (t.term_type) {
00932         case Vocabulary::TYPE_NULL:
00933         case Vocabulary::TYPE_OBJECT:
00934             // not serializable
00935             throw TermTypeNotSerializableException();
00936             break;
00937         case Vocabulary::TYPE_INT8:
00938         case Vocabulary::TYPE_INT16:
00939         case Vocabulary::TYPE_INT32:
00940             setInt(t.term_ref, value);
00941             break;
00942         case Vocabulary::TYPE_UINT8:
00943         case Vocabulary::TYPE_UINT16:
00944         case Vocabulary::TYPE_UINT32:
00945             setUInt(t.term_ref, value);
00946             break;
00947         case Vocabulary::TYPE_INT64:
00948             setBigInt(t.term_ref, value);
00949             break;
00950         case Vocabulary::TYPE_UINT64:
00951             setUBigInt(t.term_ref, value);
00952             break;
00953         case Vocabulary::TYPE_FLOAT:
00954             setFloat(t.term_ref, value);
00955             break;
00956         case Vocabulary::TYPE_DOUBLE:
00957             setDouble(t.term_ref, value);
00958             break;
00959         case Vocabulary::TYPE_LONG_DOUBLE:
00960             setLongDouble(t.term_ref, value);
00961             break;
00962         case Vocabulary::TYPE_DATE_TIME:
00963         case Vocabulary::TYPE_DATE:
00964         case Vocabulary::TYPE_TIME:
00965             {
00966             pion::PionTimeFacet f(t.term_format);
00967             const pion::PionDateTime pdt(f.fromString(value));
00968             setDateTime(t.term_ref, pdt);
00969             break;
00970             }
00971         case Vocabulary::TYPE_SHORT_STRING:
00972         case Vocabulary::TYPE_STRING:
00973         case Vocabulary::TYPE_LONG_STRING:
00974         case Vocabulary::TYPE_CHAR:
00975         case Vocabulary::TYPE_BLOB:
00976         case Vocabulary::TYPE_ZBLOB:
00977             setString(t.term_ref, value);
00978             break;
00979         }
00980     }
00981     
00989     static inline bool write(std::ostream& str, const ParameterValue& value,
00990         const Vocabulary::Term& t)
00991     {
00992         switch (t.term_type) {
00993         case Vocabulary::TYPE_NULL:
00994         case Vocabulary::TYPE_OBJECT:
00995             // not serializable
00996             throw TermTypeNotSerializableException();
00997             break;
00998         case Vocabulary::TYPE_INT8:
00999         case Vocabulary::TYPE_INT16:
01000         case Vocabulary::TYPE_INT32:
01001             str << boost::get<const boost::int32_t&>(value);
01002             break;
01003         case Vocabulary::TYPE_UINT8:
01004         case Vocabulary::TYPE_UINT16:
01005         case Vocabulary::TYPE_UINT32:
01006             str << boost::get<const boost::uint32_t&>(value);
01007             break;
01008         case Vocabulary::TYPE_INT64:
01009             str << boost::get<const boost::int64_t&>(value);
01010             break;
01011         case Vocabulary::TYPE_UINT64:
01012             str << boost::get<const boost::uint64_t&>(value);
01013             break;
01014         case Vocabulary::TYPE_FLOAT:
01015             str << boost::get<const float&>(value);
01016             break;
01017         case Vocabulary::TYPE_DOUBLE:
01018             str << boost::get<const double&>(value);
01019             break;
01020         case Vocabulary::TYPE_LONG_DOUBLE:
01021             str << boost::get<const long double&>(value);
01022             break;
01023         case Vocabulary::TYPE_SHORT_STRING:
01024         case Vocabulary::TYPE_STRING:
01025         case Vocabulary::TYPE_LONG_STRING:
01026         case Vocabulary::TYPE_CHAR:
01027         case Vocabulary::TYPE_BLOB:
01028         case Vocabulary::TYPE_ZBLOB:
01029             str << boost::get<const BlobType&>(value).get();
01030             break;
01031         case Vocabulary::TYPE_DATE_TIME:
01032         case Vocabulary::TYPE_DATE:
01033         case Vocabulary::TYPE_TIME:
01034             {
01035             pion::PionTimeFacet f(t.term_format);
01036             f.write(str, boost::get<const PionDateTime&>(value));
01037             break;
01038             }
01039         }
01040     }
01041     
01049     static inline std::string& write(std::string& str, const ParameterValue& value,
01050         const Vocabulary::Term& t)
01051     {
01052         switch (t.term_type) {
01053         case Vocabulary::TYPE_NULL:
01054         case Vocabulary::TYPE_OBJECT:
01055             // not serializable
01056             throw TermTypeNotSerializableException();
01057             break;
01058         case Vocabulary::TYPE_INT8:
01059         case Vocabulary::TYPE_INT16:
01060         case Vocabulary::TYPE_INT32:
01061             str = boost::lexical_cast<std::string>( boost::get<const boost::int32_t&>(value) );
01062             break;
01063         case Vocabulary::TYPE_UINT8:
01064         case Vocabulary::TYPE_UINT16:
01065         case Vocabulary::TYPE_UINT32:
01066             str = boost::lexical_cast<std::string>( boost::get<const boost::uint32_t&>(value) );
01067             break;
01068         case Vocabulary::TYPE_INT64:
01069             str = boost::lexical_cast<std::string>( boost::get<const boost::int64_t&>(value) );
01070             break;
01071         case Vocabulary::TYPE_UINT64:
01072             str = boost::lexical_cast<std::string>( boost::get<const boost::uint64_t&>(value) );
01073             break;
01074         case Vocabulary::TYPE_FLOAT:
01075             str = boost::lexical_cast<std::string>( boost::get<const float&>(value) );
01076             break;
01077         case Vocabulary::TYPE_DOUBLE:
01078             str = boost::lexical_cast<std::string>( boost::get<const double&>(value) );
01079             break;
01080         case Vocabulary::TYPE_LONG_DOUBLE:
01081             str = boost::lexical_cast<std::string>( boost::get<const long double&>(value) );
01082             break;
01083         case Vocabulary::TYPE_SHORT_STRING:
01084         case Vocabulary::TYPE_STRING:
01085         case Vocabulary::TYPE_LONG_STRING:
01086         case Vocabulary::TYPE_CHAR:
01087         case Vocabulary::TYPE_BLOB:
01088         case Vocabulary::TYPE_ZBLOB:
01089             str = boost::get<const BlobType&>(value).get();
01090             break;
01091         case Vocabulary::TYPE_DATE_TIME:
01092         case Vocabulary::TYPE_DATE:
01093         case Vocabulary::TYPE_TIME:
01094             {
01095             pion::PionTimeFacet f(t.term_format);
01096             str = f.toString( boost::get<const PionDateTime&>(value) );
01097             break;
01098             }
01099         }
01100         return str;
01101     }
01102     
01104     inline BlobParams make_blob(const std::string& str) const {
01105         return BlobParams(*m_alloc_ptr, str.c_str(), str.size());
01106     }
01107     
01109     inline BlobParams make_blob(const CharType *ptr, const std::size_t len) const {
01110         return BlobParams(*m_alloc_ptr, ptr, len);
01111     }
01112 
01114     inline BlobParams make_blob(const CharType *ptr) const {
01115         return BlobParams(*m_alloc_ptr, ptr, strlen(ptr));
01116     }
01117 
01119     inline boost::uint32_t getReferences(void) const { return m_references; }
01120     
01121     
01122 protected:
01123     
01125     friend class EventPtr;
01126     
01128     friend class EventFactory;
01129 
01131     inline void addReference(void) { ++m_references; }
01132     
01134     inline boost::uint32_t removeReference(void) { return --m_references; }
01135     
01137     inline AllocType *getAllocator(void) { return m_alloc_ptr; }
01138     
01145     template <typename T>   
01146     inline void insert(const Vocabulary::TermRef& term_ref, const T& value) {
01147         PION_ASSERT(term_ref != Vocabulary::UNDEFINED_TERM_REF);
01148         ParameterNode *new_param_ptr = createParameter(term_ref, value);
01149         tree_algo::insert_equal_upper_bound(&m_param_tree,
01150             new_param_ptr, m_item_compare);
01151     }
01152     
01161     template <typename T>   
01162     inline ParameterNode *createParameter(const Vocabulary::TermRef& term_ref, const T& value) {
01163         void *mem_ptr = m_alloc_ptr->malloc(sizeof(ParameterNode));
01164         return new (mem_ptr) ParameterNode(term_ref, value);
01165     }
01166     
01172     inline void destroyParameter(ParameterNode *param_ptr) {
01173         param_ptr->~ParameterNode();
01174         m_alloc_ptr->free(param_ptr, sizeof(ParameterNode));
01175     }
01176     
01177 
01179     struct ParameterNodeCompare {
01181         inline bool operator()(const ParameterNode *a, const ParameterNode *b) const {
01182             return (a->term_ref < b->term_ref);
01183         }
01184     };  
01185     
01187     struct ParameterKeyCompare {
01189         inline bool operator()(const ParameterNode *a, const Vocabulary::TermRef& b) const {
01190             return (a->term_ref < b);
01191         }
01193         inline bool operator()(const Vocabulary::TermRef& a, const ParameterNode *b) const {
01194             return (a < b->term_ref);
01195         }
01196     };  
01197     
01199     struct ParameterNodeTraits {
01200         typedef ParameterNode               node;
01201         typedef ParameterNode *             node_ptr;
01202         typedef const ParameterNode *       const_node_ptr;
01203         typedef boost::uint8_t              color;
01204         static node_ptr get_parent(const_node_ptr n)       {  return n->m_parent_ptr;   }  
01205         static void set_parent(node_ptr n, node_ptr parent){  n->m_parent_ptr = parent; }  
01206         static node_ptr get_left(const_node_ptr n)         {  return n->m_left_ptr;     }  
01207         static void set_left(node_ptr n, node_ptr left)    {  n->m_left_ptr = left;     }  
01208         static node_ptr get_right(const_node_ptr n)        {  return n->m_right_ptr;    }  
01209         static void set_right(node_ptr n, node_ptr right)  {  n->m_right_ptr = right;   }  
01210         static color get_color(const_node_ptr n)           {  return n->m_tree_color;   }  
01211         static void set_color(node_ptr n, color c)         {  n->m_tree_color = c;      }
01212         static color black()                               {  return color(0);     }
01213         static color red()                                 {  return color(1);     }        
01214     };
01215     
01217     typedef boost::intrusive::rbtree_algorithms<ParameterNodeTraits>    tree_algo;
01218 
01219     
01220 private:
01221     
01223     const EventType                 m_event_type;
01224     
01226     ParameterNode                   m_param_tree;
01227     
01229     ParameterNodeCompare            m_item_compare;
01230     
01232     ParameterKeyCompare             m_key_compare;
01233     
01235     AllocType * const               m_alloc_ptr;
01236     
01238     boost::detail::atomic_count     m_references;
01239 };
01240 
01241     
01242 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01243 
01245     typedef PionPoolAllocator<16, 256>          EventAllocator;
01246 
01247 #else
01248     
01250     struct DummyEventAllocator {
01258         inline void *malloc(std::size_t n) { return ::malloc(n); }
01259         
01266         inline void free(void *ptr, std::size_t n) { ::free(ptr); }
01267     };
01268     
01270     typedef DummyEventAllocator         EventAllocator;
01271 
01272 #endif
01273     
01274     
01276 typedef BasicEvent<char, EventAllocator>    Event;
01277     
01278     
01282 class EventPtr {
01283 public:
01284     
01286     ~EventPtr() { reset(); }
01287     
01289     EventPtr(void) : m_event_ptr(NULL) {}
01290 
01292     EventPtr(const EventPtr& ptr)
01293         : m_event_ptr(ptr.m_event_ptr)
01294     {
01295         if (m_event_ptr != NULL)
01296             m_event_ptr->addReference();
01297     }
01298     
01300     inline EventPtr& operator=(const EventPtr& ptr) { reset(ptr); return *this; }
01301     
01303     inline Event& operator*() const { return *m_event_ptr; }
01304     
01306     inline Event* operator->() const { return m_event_ptr; }
01307 
01309     inline Event *get(void) const { return m_event_ptr; }
01310     
01312     inline bool is_safe(void) const {
01313         return (m_event_ptr != NULL && m_event_ptr->getReferences()==1);
01314     }
01315     
01317     inline void reset(void) {
01318         if (m_event_ptr != NULL) {
01319             if (m_event_ptr->removeReference() == 0) {
01320                 EventAllocator *alloc_ptr = m_event_ptr->getAllocator();
01321                 m_event_ptr->~Event();
01322                 alloc_ptr->free(m_event_ptr, sizeof(Event));
01323             }
01324             m_event_ptr = NULL;
01325         }
01326     }
01327     
01329     inline void reset(const EventPtr& ptr) {
01330         reset();
01331         m_event_ptr = ptr.m_event_ptr;
01332         if (m_event_ptr != NULL)
01333             m_event_ptr->addReference();
01334     }
01335 
01337     inline void swap(EventPtr& ptr) {
01338         Event *tmp_event_ptr(ptr.m_event_ptr);
01339         ptr.m_event_ptr = m_event_ptr;
01340         m_event_ptr = tmp_event_ptr;
01341     }
01342     
01343     
01344 protected:
01345 
01347     friend class EventFactory;
01348     
01350     EventPtr(Event *event_ptr)
01351         : m_event_ptr(event_ptr)
01352     {
01353         if (m_event_ptr != NULL)
01354             m_event_ptr->addReference();
01355     }
01356     
01357     
01358 private:
01359     
01361     Event *         m_event_ptr;
01362 };
01363     
01364     
01369 class PION_PLATFORM_API EventFactory :
01370     private boost::noncopyable
01371 {
01372 public:
01373 
01375     ~EventFactory() {}
01376     
01378     EventFactory(void)
01379         : m_event_alloc(EventAllocatorFactory::getAllocator())
01380     {}
01381     
01383     explicit EventFactory(EventAllocator& alloc)
01384         : m_event_alloc(alloc)
01385     {}
01386 
01388     explicit EventFactory(Event& e)
01389         : m_event_alloc(*e.getAllocator())
01390     {}
01391     
01400     inline EventPtr create(const Event::EventType t) {
01401         void *mem_ptr = m_event_alloc.malloc(sizeof(Event));
01402         return EventPtr(new (mem_ptr) Event(t, &m_event_alloc));
01403     }
01404 
01411     inline void create(EventPtr& ptr, const Event::EventType t) {
01412         if (ptr.is_safe() && ptr->getType() == t)
01413             ptr->clear();
01414         else
01415             ptr = create(t);
01416     }
01417     
01419     inline EventAllocator& getAllocator(void) { return m_event_alloc; }
01420     
01422     inline Event::BlobParams make_blob(const std::string& str) const {
01423         return Event::BlobParams(m_event_alloc, str.c_str(), str.size());
01424     }
01425     
01427     inline Event::BlobParams make_blob(const char *ptr, const std::size_t len) const {
01428         return Event::BlobParams(m_event_alloc, ptr, len);
01429     }
01430 
01432     inline Event::BlobParams make_blob(const char *ptr) const {
01433         return Event::BlobParams(m_event_alloc, ptr, strlen(ptr));
01434     }
01435     
01436     
01437 private:
01438     
01442     class EventAllocatorFactory {
01443     public:
01444         
01446         ~EventAllocatorFactory() {
01447 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01448             // lock access to the Event allocators
01449             boost::unique_lock<boost::mutex> alloc_lock(m_alloc_mutex);
01450             // destruct all the EventAllocators that have been generated
01451             for (std::list<EventAllocator*>::iterator i = m_active_allocs.begin();
01452                  i != m_active_allocs.end(); ++i)
01453             {
01454                 delete *i;
01455             }
01456             for (std::list<EventAllocator*>::iterator i = m_inactive_allocs.begin();
01457                  i != m_inactive_allocs.end(); ++i)
01458             {
01459                 delete *i;
01460             }
01461             // release thread-specific storage for the last thread remaining,
01462             // the current thread, which is performing static global cleanup
01463             // (this is the only time this destructor would ever be called)
01464             m_thread_alloc.release();
01465 #endif
01466         }
01467         
01473         inline static EventAllocator& getAllocator(void) {
01474             boost::call_once(EventAllocatorFactory::createInstance, m_instance_flag);
01475             EventAllocator *alloc_ptr;
01476 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01477             alloc_ptr = m_instance_ptr->m_thread_alloc.get();
01478             if (alloc_ptr == NULL) {
01479                 // no allocator found for this thread
01480                 boost::unique_lock<boost::mutex> alloc_lock(m_instance_ptr->m_alloc_mutex);
01481                 if (m_instance_ptr->m_inactive_allocs.empty()) {
01482                     // no inactive allocators we can reuse -> create a new one
01483                     alloc_ptr = new EventAllocator();
01484                 } else {
01485                     // recycle an inactive allocator that already exists
01486                     alloc_ptr = m_instance_ptr->m_inactive_allocs.front();
01487                     m_instance_ptr->m_inactive_allocs.pop_front();
01488                     // release unused memory
01489                     alloc_ptr->release_memory();
01490                 }
01491                 // add the allocator to the active EventAllocator
01492                 m_instance_ptr->m_active_allocs.push_back(alloc_ptr);
01493                 // store the new thread-specific allocator
01494                 m_instance_ptr->m_thread_alloc.reset(alloc_ptr);
01495             }
01496 #else
01497             alloc_ptr = & m_instance_ptr->m_single_alloc;
01498 #endif
01499             return *alloc_ptr;
01500         }
01501 
01502         
01503     private:
01504         
01506         EventAllocatorFactory(void)
01507 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01508             : m_thread_alloc(&EventAllocatorFactory::releaseAllocator)
01509 #endif
01510         {}
01511         
01513         static void createInstance(void);
01514         
01516         static void releaseAllocator(EventAllocator *ptr) {
01517 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01518             // do not free the EventAllocator since other threads may still need to dealloate Events!
01519             boost::unique_lock<boost::mutex> alloc_lock(m_instance_ptr->m_alloc_mutex);
01520             // remove allocator from active list
01521             for (std::list<EventAllocator*>::iterator i = m_instance_ptr->m_active_allocs.begin();
01522                  i != m_instance_ptr->m_active_allocs.end(); ++i)
01523             {
01524                 if (ptr == *i) {
01525                     m_instance_ptr->m_active_allocs.erase(i);
01526                     break;
01527                 }
01528             }
01529             // release unused memory
01530             ptr->release_memory();
01531             // add allocator to the inactive list
01532             m_instance_ptr->m_inactive_allocs.push_back(ptr);
01533 #endif
01534         }
01535         
01536         
01537 #ifdef PION_EVENT_USE_POOL_ALLOCATORS
01539         boost::thread_specific_ptr<EventAllocator>      m_thread_alloc;
01540         
01542         std::list<EventAllocator*>                      m_active_allocs;
01543         
01545         std::list<EventAllocator*>                      m_inactive_allocs;
01546         
01548         boost::mutex                                    m_alloc_mutex;
01549 #else
01551         EventAllocator                                  m_single_alloc;
01552 #endif
01553         
01555         static EventAllocatorFactory *                  m_instance_ptr;
01556         
01558         static boost::once_flag                         m_instance_flag;
01559     };
01560     
01561     
01563     EventAllocator &        m_event_alloc;
01564 };
01565 
01566 
01574 typedef std::vector<EventPtr>   EventContainer;
01575 
01576 
01577 }   // end namespace platform
01578 }   // end namespace pion
01579 
01580 #endif

Generated on Wed Apr 13 16:38:34 2011 for pion-platform by  doxygen 1.4.7