Voor een programma heb ik een tijd geleden een mooi systeem gemaakt voor reference counting. Het werkt als volgt: een object maak ik met een aanroep als GC::Hold(new EenOfAndereKlasse()); en die geeft me een ref<EenOfAndereKlasse> terug. GC::Hold is als volgt geimplementeerd:
Resource<T> is dus de class met de reference count en houdt een pointer vast naar het echte object, in deze code de pointer x.
Nu is het probleem eigenlijk dat de gemaakte classes geen refcounted this-pointer hebben. Nu dacht ik dat op te lossen door de classes die dat nodig hadden te extenden van een class Object die een pointer naar de Resource als member zou hebben. In GC::Hold wordt die pointer dan gevuld:
(De ref<Object> is te casten naar een ref<EenOfAndereClass>. Ik heb nog bedacht om ook Object templated te maken, Object<EenOfAndereClass>, maar dat werkt dan natuurlijk weer niet als EenOfAndereClass weer gesubclassed wordt...).
Het probleem zit 'em erin dat ik in GC::Hold niet kan zien of een object subclass is van Object. Normaal doe je dat met een dynamic_cast<Object>(x) (en als dat 0 oplevert is het geen Object), maar een dynamic_cast mag niet bij non-polymorphic types als bijvoorbeeld std::vector, die ik redelijk vaak via GC::Hold aanmaak.
Hoe kan ik dat oplossen? Overloading lijkt niet te werken: als ik een template<> ref<Object> GC::Hold(Object* obj) maak dan wordt die niet aangeroepen als ik GC::Hold(new EenOfAndereClass) doe, waarbij EenOfAndereClass dus subclass van Object is....
Voor de duidelijkheid dus wat ik eigenlijk wil (maar dan ook op non-polymorphic types...)
C++:
1
2
3
4
| template<class T> ref<T> GC::Hold(T* x) { Resource<T>* rs = new Resource<T>(x); return rs->Reference(); } |
Resource<T> is dus de class met de reference count en houdt een pointer vast naar het echte object, in deze code de pointer x.
Nu is het probleem eigenlijk dat de gemaakte classes geen refcounted this-pointer hebben. Nu dacht ik dat op te lossen door de classes die dat nodig hadden te extenden van een class Object die een pointer naar de Resource als member zou hebben. In GC::Hold wordt die pointer dan gevuld:
C++:
1
2
3
4
5
6
7
8
| class EenOfAndereClass: public virtual Object { }; class Object { Resource<Object>* object; ref<Object> This(); }; |
(De ref<Object> is te casten naar een ref<EenOfAndereClass>. Ik heb nog bedacht om ook Object templated te maken, Object<EenOfAndereClass>, maar dat werkt dan natuurlijk weer niet als EenOfAndereClass weer gesubclassed wordt...).
Het probleem zit 'em erin dat ik in GC::Hold niet kan zien of een object subclass is van Object. Normaal doe je dat met een dynamic_cast<Object>(x) (en als dat 0 oplevert is het geen Object), maar een dynamic_cast mag niet bij non-polymorphic types als bijvoorbeeld std::vector, die ik redelijk vaak via GC::Hold aanmaak.
Hoe kan ik dat oplossen? Overloading lijkt niet te werken: als ik een template<> ref<Object> GC::Hold(Object* obj) maak dan wordt die niet aangeroepen als ik GC::Hold(new EenOfAndereClass) doe, waarbij EenOfAndereClass dus subclass van Object is....
Voor de duidelijkheid dus wat ik eigenlijk wil (maar dan ook op non-polymorphic types...)
C++:
1
2
3
4
5
6
7
8
9
10
| template<class T> ref<T> GC::Hold(T* x) { Resource<T>* rs = new Resource<T>(x); Object* object = dynamic_cast<Object*>(x); if(object!=0) { object->_resource = rs; } return rs->Reference(); } |
[ Voor 18% gewijzigd door MisterData op 07-07-2006 13:08 ]