// -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- // // The contents of this file are subject to the Netscape Public // License Version 1.1 (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.mozilla.org/NPL/ // // Software distributed under the License is distributed on an "AS // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr // implied. See the License for the specific language governing // rights and limitations under the License. // // The Original Code is the JavaScript 2 Prototype. // // The Initial Developer of the Original Code is Netscape // Communications Corporation. Portions created by Netscape are // Copyright (C) 2000 Netscape Communications Corporation. All // Rights Reserved. #include "gc_allocator.h" #include #include #include #include /* namespace JavaScript { template typename gc_allocator::pointer gc_allocator::allocate(gc_allocator::size_type n, const void*) { return static_cast(GC_malloc(n*sizeof(T))); } template void gc_allocator::deallocate(gc_allocator::pointer ptr, gc_allocator::size_type) { // this can really be a NO-OP with the GC. // ::GC_free(static_cast(ptr)); } } */ // test driver for standalone GC development. namespace JS = JavaScript; #ifdef __GNUC__ // grr, what kind of standard is this? template struct gc_types { typedef basic_string, JS::gc_allocator > string; typedef std::vector > vector; }; #else template struct gc_types { typedef std::basic_string, JS::gc_allocator > string; typedef typename std::vector > vector; }; #endif template void* operator new(std::size_t, const JS::gc_allocator& alloc) { return alloc.allocate(1); } /** * 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 traits; typedef JS::gc_allocator allocator; friend struct traits; static int instances; void* operator new(std::size_t) { return allocator::allocate(1); } A() { ++instances; std::cout << "A::A() here." << std::endl; } protected: ~A() { --instances; std::cout << "A::~A() here." << std::endl; } private: // void operator delete(void*) {} }; int A::instances = 0; int main(int /* argc */, char* /* argv[] */) { using namespace std; using namespace JS; cout << "testing the GC allocator." << endl; #ifdef XP_MAC // allocate a string, using the GC, and owned by an auto_ptr, that knows how to correctly destroy the string. typedef gc_types::string char_string; typedef gc_allocator char_string_alloc; auto_ptr ptr(new(char_string_alloc()) char_string("This is a garbage collectable string.")); const char_string& str = *ptr; cout << str << endl; #endif // question, how can we partially evaluate a template? // can we say, typedef template vector. // typedef vector > int_vector; typedef gc_types::vector int_vector; // generate 1000 random values. int_vector values; for (int i = 0; i < 1000; ++i) { int value = rand() % 32767; values.push_back(value); // allocate a random amount of garbage. if (!GC_malloc(static_cast(value))) cerr << "GC_malloc failed." << endl; // allocate an object that has a finalizer to call its destructor. A* a = new A(); } // run a collection. // gc_allocator::collect(); GC_gcollect(); // print out instance count. cout << "A::instances = " << A::instances << endl; // sort the values. sort(values.begin(), values.end()); // print the values. int_vector::iterator iter = values.begin(), last = values.end(); cout << *iter++; while (iter < last) cout << ' ' << *iter++; cout << endl; #ifdef XP_MAC // finally, print the string again. cout << str << endl; #endif return 0; }