added gc_traits_finalizable to use GC finalization facilities to call destructors.

This commit is contained in:
beard%netscape.com 2000-03-02 20:58:26 +00:00
Родитель 5020fc86a7
Коммит 1c54ce1dd3
4 изменённых файлов: 134 добавлений и 20 удалений

Просмотреть файл

@ -40,25 +40,58 @@ void gc_allocator<T>::deallocate(gc_allocator<T>::pointer ptr, gc_allocator<T>::
// test driver for standalone GC development.
using namespace std;
using namespace JavaScript;
namespace JS = JavaScript;
template <class T> struct gc_types {
typedef vector<T, gc_allocator<T> > gc_vector;
typedef std::basic_string<T, std::char_traits<T>, JS::gc_allocator<T> > string;
typedef std::vector<T, JS::gc_allocator<T> > vector;
};
/**
* Define a C++ class that is garbage collectable, and wants to have its destructor
* called when it is finalized.
*/
class A {
public:
typedef JS::gc_traits_finalizable<A> traits;
typedef JS::gc_allocator<A, traits> allocator;
friend struct traits;
void* operator new(std::size_t)
{
return allocator::allocate(1);
}
void operator delete(void*) {}
A()
{
std::cout << "A::A() here." << std::endl;
}
private:
~A()
{
std::cout << "A::~A() here." << std::endl;
}
};
void main(int /* argc */, char* /* argv[] */)
{
using namespace std;
using namespace JavaScript;
cout << "testing the GC allocator." << endl;
typedef basic_string< char, char_traits<char>, gc_allocator<char> > GC_string;
GC_string str("This is a garbage collectable string.");
typedef gc_types<char>::string char_string;
auto_ptr<char_string> ptr(new char_string("This is a garbage collectable string."));
char_string& str = *ptr;
cout << str << endl;
// question, how can we partially evaluate a template?
// can we say, typedef template <class T> vector<typename T>.
// typedef vector<int, gc_allocator<int> > int_vector;
typedef gc_types<int>::gc_vector int_vector;
typedef gc_types<int>::vector int_vector;
// generate 1000 random values.
int_vector values;
@ -68,6 +101,8 @@ void main(int /* argc */, char* /* argv[] */)
// allocate a random amount of garbage.
if (!GC_malloc(static_cast<size_t>(value)))
cerr << "GC_malloc failed." << endl;
// allocate an object that has a finalizer to call its destructor.
A* a = new A();
}
// run a collection.

Просмотреть файл

@ -33,6 +33,10 @@ namespace JavaScript {
void* GC_malloc_atomic(size_t bytes);
void GC_free(void* ptr);
void GC_gcollect(void);
typedef void (*GC_finalization_proc) (void* obj, void* client_data);
void GC_register_finalizer(void* obj, GC_finalization_proc proc, void* client_data,
GC_finalization_proc *old_proc, void* *old_client_data);
}
/**
@ -44,7 +48,7 @@ namespace JavaScript {
};
/**
* Specializations for blocks of known types: the macro define_atomic_type(_type)
* Specializations for blocks of atomic types: the macro define_atomic_type(_type)
* specializes gc_traits<T> for types that need not be scanned by the
* GC. Implementors are free to define other types as atomic, if they are
* guaranteed not to contain pointers.
@ -70,10 +74,28 @@ namespace JavaScript {
#undef define_atomic_type
template <class T> struct gc_traits_finalizable {
static void finalizer(void* obj, void* client_data)
{
T* t = static_cast<T*>(obj);
size_t n = static_cast<size_t>(client_data);
for (size_t i = 0; i < n; ++i)
t[i].~T();
}
static T* allocate(size_t n)
{
T* t = gc_traits<T>::allocate(n);
GC_finalization_proc old_proc; void* old_client_data;
GC_register_finalizer((void*)t, &finalizer, (void*)n, &old_proc, &old_client_data);
return t;
}
};
/**
* An allocator that can be used to allocate objects in the garbage collected heap.
*/
template <class T> class gc_allocator {
template <class T, class traits = gc_traits<T> > class gc_allocator {
public:
typedef T value_type;
typedef size_t size_type;
@ -90,7 +112,7 @@ namespace JavaScript {
template<class U> gc_allocator(const gc_allocator<U>&) {}
// ~gc_allocator() {}
static pointer allocate(size_type n, const void* /* hint */ = 0) { return gc_traits<T>::allocate(n); }
static pointer allocate(size_type n, const void* /* hint */ = 0) { return traits::allocate(n); }
static void deallocate(pointer, size_type) {}
static void construct(pointer p, const T &val) { new(p) T(val);}

Просмотреть файл

@ -40,25 +40,58 @@ void gc_allocator<T>::deallocate(gc_allocator<T>::pointer ptr, gc_allocator<T>::
// test driver for standalone GC development.
using namespace std;
using namespace JavaScript;
namespace JS = JavaScript;
template <class T> struct gc_types {
typedef vector<T, gc_allocator<T> > gc_vector;
typedef std::basic_string<T, std::char_traits<T>, JS::gc_allocator<T> > string;
typedef std::vector<T, JS::gc_allocator<T> > vector;
};
/**
* Define a C++ class that is garbage collectable, and wants to have its destructor
* called when it is finalized.
*/
class A {
public:
typedef JS::gc_traits_finalizable<A> traits;
typedef JS::gc_allocator<A, traits> allocator;
friend struct traits;
void* operator new(std::size_t)
{
return allocator::allocate(1);
}
void operator delete(void*) {}
A()
{
std::cout << "A::A() here." << std::endl;
}
private:
~A()
{
std::cout << "A::~A() here." << std::endl;
}
};
void main(int /* argc */, char* /* argv[] */)
{
using namespace std;
using namespace JavaScript;
cout << "testing the GC allocator." << endl;
typedef basic_string< char, char_traits<char>, gc_allocator<char> > GC_string;
GC_string str("This is a garbage collectable string.");
typedef gc_types<char>::string char_string;
auto_ptr<char_string> ptr(new char_string("This is a garbage collectable string."));
char_string& str = *ptr;
cout << str << endl;
// question, how can we partially evaluate a template?
// can we say, typedef template <class T> vector<typename T>.
// typedef vector<int, gc_allocator<int> > int_vector;
typedef gc_types<int>::gc_vector int_vector;
typedef gc_types<int>::vector int_vector;
// generate 1000 random values.
int_vector values;
@ -68,6 +101,8 @@ void main(int /* argc */, char* /* argv[] */)
// allocate a random amount of garbage.
if (!GC_malloc(static_cast<size_t>(value)))
cerr << "GC_malloc failed." << endl;
// allocate an object that has a finalizer to call its destructor.
A* a = new A();
}
// run a collection.

Просмотреть файл

@ -33,6 +33,10 @@ namespace JavaScript {
void* GC_malloc_atomic(size_t bytes);
void GC_free(void* ptr);
void GC_gcollect(void);
typedef void (*GC_finalization_proc) (void* obj, void* client_data);
void GC_register_finalizer(void* obj, GC_finalization_proc proc, void* client_data,
GC_finalization_proc *old_proc, void* *old_client_data);
}
/**
@ -44,7 +48,7 @@ namespace JavaScript {
};
/**
* Specializations for blocks of known types: the macro define_atomic_type(_type)
* Specializations for blocks of atomic types: the macro define_atomic_type(_type)
* specializes gc_traits<T> for types that need not be scanned by the
* GC. Implementors are free to define other types as atomic, if they are
* guaranteed not to contain pointers.
@ -70,10 +74,28 @@ namespace JavaScript {
#undef define_atomic_type
template <class T> struct gc_traits_finalizable {
static void finalizer(void* obj, void* client_data)
{
T* t = static_cast<T*>(obj);
size_t n = static_cast<size_t>(client_data);
for (size_t i = 0; i < n; ++i)
t[i].~T();
}
static T* allocate(size_t n)
{
T* t = gc_traits<T>::allocate(n);
GC_finalization_proc old_proc; void* old_client_data;
GC_register_finalizer((void*)t, &finalizer, (void*)n, &old_proc, &old_client_data);
return t;
}
};
/**
* An allocator that can be used to allocate objects in the garbage collected heap.
*/
template <class T> class gc_allocator {
template <class T, class traits = gc_traits<T> > class gc_allocator {
public:
typedef T value_type;
typedef size_t size_type;
@ -90,7 +112,7 @@ namespace JavaScript {
template<class U> gc_allocator(const gc_allocator<U>&) {}
// ~gc_allocator() {}
static pointer allocate(size_type n, const void* /* hint */ = 0) { return gc_traits<T>::allocate(n); }
static pointer allocate(size_type n, const void* /* hint */ = 0) { return traits::allocate(n); }
static void deallocate(pointer, size_type) {}
static void construct(pointer p, const T &val) { new(p) T(val);}