/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* $Rev$ $Date$ */ #ifndef tuscany_gc_hpp #define tuscany_gc_hpp /** * Garbage collected pointer. */ #include #include #include namespace tuscany { template class gc_ptr { public: gc_ptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) { } ~gc_ptr() throw() { release(); } gc_ptr(const gc_ptr& r) throw() : countingRef(r.countingRef) { acquire(r.countingRef); } gc_ptr& operator=(const gc_ptr& r) throw() { if(this == &r) return *this; acquire(r.countingRef); release(); countingRef = r.countingRef; return *this; } const bool operator==(const gc_ptr& r) const throw() { if (this == &r) return true; if (countingRef == NULL) return r.countingRef == NULL; if (r.countingRef == NULL) return false; return countingRef-> ptr == r.countingRef->ptr; } const bool operator!=(const gc_ptr& r) const throw() { return !this->operator ==(r); } T& operator*() const throw() { return *countingRef->ptr; } T* operator->() const throw() { return countingRef->ptr; } operator T*() const throw() { return countingRef->ptr; } template friend std::ostream& operator<<(std::ostream&, const gc_ptr&); private: struct CountingRef { T* ptr; unsigned count; CountingRef(T* p) throw() : ptr(p), count(1) { } }* countingRef; void acquire(CountingRef* ref) throw() { if(ref) __sync_add_and_fetch(&ref->count, 1); } void release() throw() { if(countingRef) { unsigned rc = __sync_sub_and_fetch(&countingRef->count, 1); if(rc == 0) { delete countingRef->ptr; delete countingRef; } } } }; template std::ostream& operator<<(std::ostream& out, const gc_ptr& p) { return out << p.countingRef->ptr; } /** * Garbage collected pointer to an array. */ template class gc_aptr { public: gc_aptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) { } ~gc_aptr() throw() { release(); } gc_aptr(const gc_aptr& r) throw() : countingRef(r.countingRef) { acquire(r.countingRef); } gc_aptr& operator=(const gc_aptr& r) throw() { if(this == &r) return *this; acquire(r.countingRef); release(); countingRef = r.countingRef; return *this; } const bool operator==(const gc_aptr& r) const throw() { if (this == &r) return true; if (countingRef == NULL) return r.countingRef == NULL; if (r.countingRef == NULL) return false; return countingRef-> ptr == r.countingRef->ptr; } const bool operator!=(const gc_aptr& r) const throw() { return !this->operator ==(r); } T& operator*() const throw() { return *countingRef->ptr; } T* operator->() const throw() { return countingRef->ptr; } operator T*() const throw() { return countingRef->ptr; } template friend std::ostream& operator<<(std::ostream&, const gc_aptr&); private: struct CountingRef { T* ptr; unsigned count; CountingRef(T* p) throw() : ptr(p), count(1) { } }* countingRef; void acquire(CountingRef* ref) throw() { if(ref) __sync_add_and_fetch(&ref->count, 1); } void release() throw() { if(countingRef) { unsigned rc = __sync_sub_and_fetch(&countingRef->count, 1); if(rc == 0) { delete[] countingRef->ptr; delete countingRef; } } } }; template std::ostream& operator<<(std::ostream& out, const gc_aptr& p) { return out << p.countingRef->ptr; } /** * Garbage collected pointer to a reference counting object. */ template class gc_counting_ptr { public: gc_counting_ptr(T* p = 0) throw() : ptr(p) { acquire(p); } ~gc_counting_ptr() throw() { release(); } gc_counting_ptr(const gc_counting_ptr& r) throw() : ptr(r.ptr) { acquire(ptr); } gc_counting_ptr& operator=(const gc_counting_ptr& r) throw() { if(this == &r) return *this; acquire(r.ptr); release(); ptr = r.ptr; return *this; } const bool operator==(const gc_counting_ptr& r) const throw() { if (this == &r) return true; return ptr == r.ptr; } const bool operator!=(const gc_counting_ptr& r) const throw() { return !this->operator ==(r); } T& operator*() const throw() { return *ptr; } T* operator->() const throw() { return ptr; } operator T*() const throw() { return ptr; } template friend std::ostream& operator<<(std::ostream&, const gc_counting_ptr&); private: T* ptr; void acquire(T* p) throw() { if(p) p->acquire(); } void release() throw() { if(ptr) { if(ptr->release() == 0) { delete ptr; } } } }; template std::ostream& operator<<(std::ostream& out, const gc_counting_ptr& p) { return out << p.ptr; } /** * Apache Portable Runtime library context */ class APRContext { public: APRContext() { apr_initialize(); } ~APRContext() { apr_terminate(); } }; APRContext aprContext; /** * Garbage collected memory pool, using an APR pool. */ class gc_pool { public: gc_pool() : aprPool(new APRPool) { } operator apr_pool_t*() const { return aprPool->p; } private: class APRPool { friend class gc_pool; friend class gc_counting_ptr; unsigned int refCount; apr_pool_t* p; APRPool() : refCount(0) { apr_pool_create(&p, NULL); } ~APRPool() { apr_pool_destroy(p); } unsigned int acquire() { return __sync_add_and_fetch(&refCount, 1); } unsigned int release() { return __sync_sub_and_fetch(&refCount, 1); } }; const gc_counting_ptr aprPool; }; /** * Garbage collected pointer to pooled memory. */ template class gc_pool_ptr { public: gc_pool_ptr(T* ptr = 0) throw() : ptr(ptr) { } ~gc_pool_ptr() throw() { } gc_pool_ptr(const gc_pool_ptr& r) throw() : ptr(r.ptr) { } gc_pool_ptr& operator=(const gc_pool_ptr& r) throw() { if(this == &r) return *this; ptr = r.ptr; return *this; } const bool operator==(const gc_pool_ptr& r) const throw() { if (this == &r) return true; return ptr == r.ptr; } const bool operator!=(const gc_pool_ptr& r) const throw() { return !this->operator ==(r); } T& operator*() const throw() { return *ptr; } T* operator->() const throw() { return ptr; } operator T*() const throw() { return ptr; } template friend std::ostream& operator<<(std::ostream&, const gc_pool_ptr&); private: T* ptr; }; template std::ostream& operator<<(std::ostream& out, const gc_pool_ptr& p) { return out << p.ptr; } /** * Cleanup function, called by the APR pool to cleanup registered resources. * Calls the allocated object's destructor. */ template apr_status_t gc_pool_cleanupCallback(void* v) { T* t = static_cast(v); t->~T(); return APR_SUCCESS; } /** * Returns a pointer to an object allocated from a memory pool. */ template gc_pool_ptr gc_pool_new(const gc_pool& mp) { // Allocate memory from the pool void* m = apr_palloc(mp, sizeof(T)); // Register a cleanup callback apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback, apr_pool_cleanup_null) ; // Run the requested type's constructor over the allocated memory return new (m) T(); } } #endif /* tuscany_gc_hpp */