shared_object.hpp

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2009 - 2012 by Chris Hopman <cjhopman@gmail.com>
00003    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #ifndef SHARED_OBJECT_HPP_INCLUDED
00016 #define SHARED_OBJECT_HPP_INCLUDED
00017 
00018 #include <climits>
00019 #include <cassert>
00020 #include <boost/multi_index_container.hpp>
00021 #include <boost/multi_index/hashed_index.hpp>
00022 #include <boost/multi_index/member.hpp>
00023 
00024 template <typename T>
00025 struct shared_node {
00026     T val;
00027     mutable unsigned long count;
00028     shared_node() : val(), count(0) { }
00029     shared_node(const T& o) : val(o), count(0) { }
00030     static const unsigned long max_count = ULONG_MAX;
00031 };
00032 
00033 template <typename T>
00034 struct hasher {
00035     size_t operator()(const T& o) {
00036         return hash_value(o.val);
00037     }
00038 };
00039 
00040 template <typename T, typename node = shared_node<T> >
00041 class shared_object {
00042 public:
00043     typedef T type;
00044 
00045     shared_object() : val_(NULL) { set(T()); }
00046 
00047     shared_object(const T &o) : val_(NULL) { set(o); }
00048 
00049     shared_object(const shared_object& o) : val_(o.val_) {
00050         assert(valid());
00051         val_->count++;
00052     }
00053 
00054     operator T() const {
00055         assert(valid());
00056         return val_->val;
00057     }
00058 
00059     shared_object& operator=(const shared_object& o) {
00060         if (val_ == o.val_) return *this;
00061         shared_object tmp(o);
00062         swap(tmp);
00063         return *this;
00064     }
00065 
00066     ~shared_object() { clear(); }
00067 
00068     void set(const T& o) {
00069         if (valid() && o == get()) return;
00070         clear();
00071 
00072         val_ = &*index().insert(node(o)).first;
00073         val_->count++;
00074 
00075         assert((val_->count) < (node::max_count));
00076     }
00077 
00078     const T& get() const {
00079         assert(valid());
00080         return val_->val;
00081     }
00082 
00083     void swap(shared_object& o) {
00084         std::swap(val_, o.val_);
00085     }
00086 
00087     const node* ptr() const {
00088         return val_;
00089     }
00090 
00091 protected:
00092 
00093     typedef boost::multi_index_container<
00094         node,
00095         boost::multi_index::indexed_by<
00096             boost::multi_index::hashed_unique<
00097                 BOOST_MULTI_INDEX_MEMBER(node, T, val)
00098             >
00099         >
00100     > hash_map;
00101 
00102     typedef typename hash_map::template nth_index<0>::type hash_index;
00103 
00104     static hash_map& map() { static hash_map* map = new hash_map; return *map; }
00105     static hash_index& index() { return map().template get<0>(); }
00106 
00107     const node* val_;
00108 
00109     bool valid() const {
00110         return val_ != NULL;
00111     }
00112 
00113     void clear() {
00114         if (!valid()) return;
00115         val_->count--;
00116 
00117         if (val_->count == 0) index().erase(index().find(val_->val));
00118         val_ = NULL;
00119     }
00120 
00121 };
00122 
00123 template <typename T>
00124 bool operator==(const shared_object<T>& a, const shared_object<T>& b) {
00125     return a.ptr() == b.ptr() ? true : a.get() == b.get();
00126 }
00127 
00128 template <typename T>
00129 bool operator<(const shared_object<T>& a, const shared_object<T>& b) {
00130     assert(a.valid());
00131     assert(b.valid());
00132     return a.get() < b.get();
00133 }
00134 
00135 template <typename T>
00136 std::ostream& operator<<(std::ostream& stream, const shared_object<T>& o) {
00137     assert(o.valid());
00138     return stream << o.get();
00139 }
00140 
00141 template <typename T>
00142 std::istream& operator>>(std::istream& stream, shared_object<T>& o) {
00143     T t;
00144     std::istream& ret = stream >> t;
00145     o.set(t);
00146     return ret;
00147 }
00148 
00149 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:10 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs