00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef _FU_TRACKER_H_
00010 #define _FU_TRACKER_H_
00011
00017 #ifndef _FU_OBJECT_H_
00018 #include "FUtils/FUObject.h"
00019 #endif // _FU_OBJECT_H_
00020
00021 class FUTracker;
00022
00032 class FCOLLADA_EXPORT FUTrackable : public FUObject
00033 {
00034 private:
00035 DeclareObjectType(FUObject);
00036
00037
00038 typedef fm::pvector<FUTracker> FUTrackerList;
00039 FUTrackerList trackers;
00040
00041 public:
00045 FUTrackable();
00046
00049 virtual ~FUTrackable();
00050
00054 size_t GetTrackerCount() const { return trackers.size(); }
00055
00056 protected:
00060 void Detach();
00061
00062 private:
00063 friend class FUTracker;
00064 void AddTracker(FUTracker* tracker);
00065 void RemoveTracker(FUTracker* tracker);
00066 bool HasTracker(const FUTracker* tracker) const;
00067 };
00068
00069
00077 class FCOLLADA_EXPORT FUTracker
00078 {
00079 public:
00081 virtual ~FUTracker() {}
00082
00086 virtual void OnObjectReleased(FUTrackable* object) = 0;
00087
00090 virtual bool TracksObject(const FUTrackable* object) const { return object != NULL ? object->HasTracker(this) : false; }
00091
00092 protected:
00095 void TrackObject(FUTrackable* object) { if (object) object->AddTracker(this); }
00096
00099 void UntrackObject(FUTrackable* object) { if (object) object->RemoveTracker(this); }
00100 };
00101
00108 template <class ObjectClass = FUTrackable>
00109 class FUTrackedPtr : public FUTracker
00110 {
00111 protected:
00113 ObjectClass* ptr;
00114
00115 public:
00119 FUTrackedPtr(ObjectClass* _ptr = NULL) : ptr(_ptr)
00120 {
00121 if (ptr != NULL) FUTracker::TrackObject((FUTrackable*) ptr);
00122 ptr = ptr;
00123 }
00124
00127 ~FUTrackedPtr()
00128 {
00129 if (ptr != NULL) FUTracker::UntrackObject((FUTrackable*) ptr);
00130 ptr = NULL;
00131 }
00132
00136 FUTrackedPtr& operator=(ObjectClass* _ptr)
00137 {
00138 if (ptr != NULL) FUTracker::UntrackObject((FUTrackable*) ptr);
00139 ptr = _ptr;
00140 if (ptr != NULL) FUTracker::TrackObject((FUTrackable*) ptr);
00141 return *this;
00142 }
00143 inline FUTrackedPtr& operator=(const FUTrackedPtr& _ptr) { return operator=(_ptr.ptr); }
00147 virtual bool TracksObject(const FUTrackable* object) const { return (FUTrackable*) ptr == object; }
00148
00151 inline ObjectClass& operator*() { FUAssert(ptr != NULL, return *ptr); return *ptr; }
00152 inline const ObjectClass& operator*() const { FUAssert(ptr != NULL, return *ptr); return *ptr; }
00153 inline ObjectClass* operator->() { return ptr; }
00154 inline const ObjectClass* operator->() const { return ptr; }
00155 inline operator ObjectClass*() { return ptr; }
00156 inline operator const ObjectClass*() const { return ptr; }
00158 protected:
00162 virtual void OnObjectReleased(FUTrackable* object)
00163 {
00164 FUAssert(TracksObject(object), return);
00165 ptr = NULL;
00166 }
00167 };
00168
00176 template <class ObjectClass = FUTrackable>
00177 class FUTrackedList : private fm::pvector<ObjectClass>, FUTracker
00178 {
00179 public:
00180 typedef fm::pvector<ObjectClass> Parent;
00181 typedef ObjectClass* item;
00182 typedef const ObjectClass* const_item;
00183 typedef item* iterator;
00184 typedef const_item* const_iterator;
00185
00187 virtual ~FUTrackedList() { clear(); }
00188
00190 void clear()
00191 {
00192 for (iterator it = begin(); it != end(); ++it)
00193 {
00194 FUTracker::UntrackObject((FUTrackable*) (*it));
00195 }
00196 Parent::clear();
00197 }
00198
00201 ObjectClass*& front() { return (ObjectClass*&) Parent::front(); }
00202 const ObjectClass*& front() const { return (const ObjectClass*&) Parent::front(); }
00206 ObjectClass*& back() { return (ObjectClass*&) Parent::back(); }
00207 const ObjectClass*& back() const { return (const ObjectClass*&) Parent::back(); }
00212 inline ObjectClass* at(size_t index) { return (ObjectClass*) Parent::at(index); }
00213 inline const ObjectClass* at(size_t index) const { return (const ObjectClass*) Parent::at(index); }
00214 template <class INTEGER> inline ObjectClass* operator[](INTEGER index) { return at(index); }
00215 template <class INTEGER> inline const ObjectClass* operator[](INTEGER index) const { return at(index); }
00219 inline iterator begin() { return (iterator) Parent::begin(); }
00220 inline const_iterator begin() const { return (const_iterator) Parent::begin(); }
00224 inline iterator end() { return (iterator) Parent::end(); }
00225 inline const_iterator end() const { return (const_iterator) Parent::end(); }
00231 inline iterator find(const ObjectClass* item) { return (iterator) Parent::find(item); }
00232 inline const_iterator find(const ObjectClass* item) const { return (const_iterator) Parent::find(item); }
00236 inline void push_back(ObjectClass* object)
00237 {
00238 FUTracker::TrackObject((FUTrackable*) object);
00239 Parent::push_back(object);
00240 }
00241
00246 iterator insert(iterator _iterator, ObjectClass* object)
00247 {
00248 FUTracker::TrackObject(object);
00249 return (iterator) Parent::insert(_iterator, object);
00250 }
00251
00255 inline void insert(size_t index, ObjectClass* object) { insert(begin() + index, object); }
00256
00262 template <class _It>
00263 void insert(iterator _where, _It _startIterator, _It _endIterator)
00264 {
00265 if (_startIterator < _endIterator)
00266 {
00267 size_t relativeWhere = _where - begin();
00268 size_t count = _endIterator - _startIterator;
00269 Parent::insert(Parent::begin() + relativeWhere, count);
00270 _where = begin() + relativeWhere;
00271
00272 for (; _startIterator != _endIterator; ++_startIterator, ++_where)
00273 {
00274 *_where = const_cast<ObjectClass*>((const ObjectClass*)(*_startIterator));
00275 FUTracker::TrackObject(const_cast<FUTrackable*>((const FUTrackable*) (*_startIterator)));
00276 }
00277 }
00278 }
00279
00281 void pop_back()
00282 {
00283 if (!Parent::empty())
00284 {
00285 FUTracker::UntrackObject(back());
00286 Parent::pop_back();
00287 }
00288 }
00289
00292 iterator erase(iterator _it)
00293 {
00294 FUTracker::UntrackObject((FUTrackable*) *_it);
00295 return (iterator) Parent::erase(_it);
00296 }
00297
00301 inline void erase(iterator first, iterator last)
00302 {
00303 for (iterator it = first; it != last; ++it) FUTracker::UntrackObject((FUTrackable*) *it);
00304 Parent::erase(first, last);
00305 }
00306
00310 inline void erase(size_t first, size_t last) { erase(begin() + first, begin() + last); }
00311
00315 inline bool erase(const ObjectClass* value)
00316 {
00317 iterator it = Parent::find(value);
00318 if (it != Parent::end())
00319 {
00320 FUTracker::UntrackObject((FUTrackable*) *it);
00321 Parent::erase(it);
00322 return true;
00323 }
00324 return false;
00325 }
00326
00329 inline void erase(size_t index) { erase(begin() + index); }
00330
00333 virtual bool TracksObject(const FUTrackable* object) const { return Parent::contains((ObjectClass*) object); }
00334
00340 FUTrackedList<ObjectClass>& operator= (const FUTrackedList<ObjectClass>& other) { clear(); insert(end(), other.begin(), other.end()); return *this; }
00341
00342 inline bool empty() const { return Parent::empty(); }
00343 inline size_t size() const { return Parent::size(); }
00344 void reserve(size_t count) { Parent::reserve(count); }
00345 inline bool contains(const ObjectClass* value) const { return Parent::contains(value); }
00351 inline bool release(const ObjectClass* value)
00352 {
00353 ObjectClass** it = find(value);
00354 if (it != Parent::end()) { erase(it); ((FUTrackable*) value)->Release(); return true; }
00355 return false;
00356 }
00357
00359 void pop_front()
00360 {
00361 if (!Parent::empty())
00362 {
00363 FUTracker::UntrackObject(front());
00364 Parent::pop_front();
00365 }
00366 }
00367
00368 protected:
00371 virtual void OnObjectReleased(FUTrackable* object)
00372 {
00373 FUAssert(TracksObject(object), return);
00374 Parent::erase((ObjectClass*) object);
00375 }
00376 };
00377
00378 #endif // _FU_TRACKER_H_