2000-03-09 04:34:57 +03:00
|
|
|
// -*- 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
|
2000-02-29 04:48:02 +03:00
|
|
|
// 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"
|
|
|
|
|
2000-02-29 19:03:24 +03:00
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2000-03-09 04:34:57 +03:00
|
|
|
#include <algorithm>
|
2000-02-29 04:48:02 +03:00
|
|
|
|
2000-03-09 04:34:57 +03:00
|
|
|
/*
|
2000-02-29 04:48:02 +03:00
|
|
|
namespace JavaScript {
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
typename gc_allocator<T>::pointer
|
2000-02-29 19:03:24 +03:00
|
|
|
gc_allocator<T>::allocate(gc_allocator<T>::size_type n, const void*)
|
2000-02-29 04:48:02 +03:00
|
|
|
{
|
|
|
|
return static_cast<pointer>(GC_malloc(n*sizeof(T)));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2000-02-29 19:03:24 +03:00
|
|
|
void gc_allocator<T>::deallocate(gc_allocator<T>::pointer ptr, gc_allocator<T>::size_type)
|
2000-02-29 04:48:02 +03:00
|
|
|
{
|
|
|
|
// this can really be a NO-OP with the GC.
|
2000-02-29 19:03:24 +03:00
|
|
|
// ::GC_free(static_cast<void*>(ptr));
|
|
|
|
}
|
|
|
|
|
2000-02-29 04:48:02 +03:00
|
|
|
}
|
2000-03-09 04:34:57 +03:00
|
|
|
*/
|
2000-02-29 04:48:02 +03:00
|
|
|
|
2000-02-29 19:03:24 +03:00
|
|
|
// test driver for standalone GC development.
|
|
|
|
|
2000-03-02 23:58:26 +03:00
|
|
|
namespace JS = JavaScript;
|
2000-02-29 19:03:24 +03:00
|
|
|
|
2000-03-09 04:34:57 +03:00
|
|
|
#ifdef __GNUC__
|
|
|
|
// grr, what kind of standard is this?
|
2000-02-29 19:03:24 +03:00
|
|
|
template <class T> struct gc_types {
|
2000-03-09 04:34:57 +03:00
|
|
|
typedef basic_string<T, string_char_traits<T>, JS::gc_allocator<T> > string;
|
2000-03-02 23:58:26 +03:00
|
|
|
typedef std::vector<T, JS::gc_allocator<T> > vector;
|
|
|
|
};
|
2000-03-09 04:34:57 +03:00
|
|
|
#else
|
|
|
|
template <class T> struct gc_types {
|
|
|
|
// typedef std::basic_string<T, std::char_traits<T>, JS::gc_allocator<T> > string;
|
|
|
|
typedef typename std::vector<T, JS::gc_allocator<T> > vector;
|
|
|
|
};
|
|
|
|
#endif
|
2000-03-02 23:58:26 +03:00
|
|
|
|
2000-03-07 04:21:53 +03:00
|
|
|
template <class T>
|
|
|
|
void* operator new(std::size_t, const JS::gc_allocator<T>& alloc)
|
|
|
|
{
|
|
|
|
return alloc.allocate(1);
|
|
|
|
}
|
|
|
|
|
2000-03-02 23:58:26 +03:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
|
2000-03-07 04:21:53 +03:00
|
|
|
static int instances;
|
|
|
|
|
2000-03-09 04:34:57 +03:00
|
|
|
void* operator new(std::size_t) {return allocator::allocate(1);}
|
2000-03-02 23:58:26 +03:00
|
|
|
|
|
|
|
A()
|
|
|
|
{
|
2000-03-07 04:21:53 +03:00
|
|
|
++instances;
|
2000-03-02 23:58:26 +03:00
|
|
|
std::cout << "A::A() here." << std::endl;
|
|
|
|
}
|
|
|
|
|
2000-03-07 04:21:53 +03:00
|
|
|
protected:
|
2000-03-02 23:58:26 +03:00
|
|
|
~A()
|
|
|
|
{
|
2000-03-07 04:21:53 +03:00
|
|
|
--instances;
|
2000-03-02 23:58:26 +03:00
|
|
|
std::cout << "A::~A() here." << std::endl;
|
|
|
|
}
|
2000-03-07 04:21:53 +03:00
|
|
|
|
|
|
|
private:
|
2000-03-09 04:34:57 +03:00
|
|
|
// void operator delete(void*) {}
|
2000-02-29 19:03:24 +03:00
|
|
|
};
|
|
|
|
|
2000-03-07 04:21:53 +03:00
|
|
|
int A::instances = 0;
|
|
|
|
|
2000-03-09 04:34:57 +03:00
|
|
|
int main(int /* argc */, char* /* argv[] */)
|
2000-02-29 19:03:24 +03:00
|
|
|
{
|
2000-03-02 23:58:26 +03:00
|
|
|
using namespace std;
|
2000-03-07 04:21:53 +03:00
|
|
|
using namespace JS;
|
2000-03-02 23:58:26 +03:00
|
|
|
|
2000-02-29 19:03:24 +03:00
|
|
|
cout << "testing the GC allocator." << endl;
|
2000-03-02 23:58:26 +03:00
|
|
|
|
2000-03-09 04:34:57 +03:00
|
|
|
#ifdef XP_MAC
|
2000-03-07 04:21:53 +03:00
|
|
|
// allocate a string, using the GC, and owned by an auto_ptr, that knows how to correctly destroy the string.
|
2000-03-02 23:58:26 +03:00
|
|
|
typedef gc_types<char>::string char_string;
|
2000-03-07 04:21:53 +03:00
|
|
|
typedef gc_allocator<char_string> char_string_alloc;
|
2000-03-09 04:34:57 +03:00
|
|
|
// auto_ptr<char_string, char_string_alloc> ptr(new(char_string_alloc()) char_string("This is a garbage collectable string."));
|
|
|
|
// const char_string& str = *ptr;
|
|
|
|
char_string str("This is a garbage collectable string.");
|
2000-02-29 19:03:24 +03:00
|
|
|
cout << str << endl;
|
2000-03-09 04:34:57 +03:00
|
|
|
#endif
|
2000-02-29 19:03:24 +03:00
|
|
|
|
|
|
|
// 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;
|
2000-03-02 23:58:26 +03:00
|
|
|
typedef gc_types<int>::vector int_vector;
|
2000-02-29 19:03:24 +03:00
|
|
|
|
|
|
|
// generate 1000 random values.
|
|
|
|
int_vector values;
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
2000-03-09 04:34:57 +03:00
|
|
|
int value = rand() % 32767;
|
2000-02-29 19:03:24 +03:00
|
|
|
values.push_back(value);
|
|
|
|
// allocate a random amount of garbage.
|
|
|
|
if (!GC_malloc(static_cast<size_t>(value)))
|
|
|
|
cerr << "GC_malloc failed." << endl;
|
2000-03-02 23:58:26 +03:00
|
|
|
// allocate an object that has a finalizer to call its destructor.
|
|
|
|
A* a = new A();
|
2000-02-29 19:03:24 +03:00
|
|
|
}
|
2000-03-03 00:06:36 +03:00
|
|
|
|
2000-02-29 19:03:24 +03:00
|
|
|
// run a collection.
|
2000-03-09 04:34:57 +03:00
|
|
|
// gc_allocator<void>::collect();
|
|
|
|
GC_gcollect();
|
2000-03-07 04:21:53 +03:00
|
|
|
|
|
|
|
// print out instance count.
|
|
|
|
cout << "A::instances = " << A::instances << endl;
|
2000-02-29 19:03:24 +03:00
|
|
|
|
|
|
|
// 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;
|
2000-03-09 04:34:57 +03:00
|
|
|
|
|
|
|
#ifdef XP_MAC
|
2000-02-29 19:03:24 +03:00
|
|
|
// finally, print the string again.
|
|
|
|
cout << str << endl;
|
2000-03-09 04:34:57 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
2000-02-29 04:48:02 +03:00
|
|
|
}
|