Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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