зеркало из https://github.com/mozilla/pjs.git
added gc_traits_finalizable to use GC finalization facilities to call destructors.
This commit is contained in:
Родитель
5020fc86a7
Коммит
1c54ce1dd3
|
@ -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);}
|
||||
|
|
Загрузка…
Ссылка в новой задаче