/////////////////////////////////////////////////////////////////////////////// // Date: Sat Oct 27 00:45:34 CDT 2007 // Author: John Quigley // Revision: $Id$ // // The White Programming Language // Copyright (C) 2007 John Quigley // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . /////////////////////////////////////////////////////////////////////////////// #include #include #include #include "core/core.h" #include "core/util.h" #include "core/gc.h" /** * TODO: document * */ WGC *WGC_new(void) { WGC *new = (WGC *)malloc(sizeof(struct WGC)); new->incrementalEnabled = Boolean_new(); // default for HB is False new->isInitialized = Boolean_new(); new->objectData = ObjectData_new(); return new; } /** * TODO: document * */ void WGC_delete(WGC *object) { Boolean_delete(object->incrementalEnabled); Boolean_delete(object->isInitialized); ObjectData_delete(object->objectData); free(object); LOGGER_DEBUG("garbage collection subsytem uninitialized"); } /** * On some platforms, it is necessary to invoke this from the main executable, * not from a dynamic library, before the initial invocation of a GC routine. * It is recommended that this be done in portable code, though we try to * ensure that it expands to a no-op on as many platforms as possible. */ void WGC_init(WGC *self) { GC_INIT(); Boolean_setValue(self->isInitialized, True); LOGGER_DEBUG("garbage collection subsytem initialized"); } /** * Cause the garbage collector to perform a small amount of work every few * invocations of GC_MALLOC or the like, instead of performing an entire * collection at once. This is likely to increase total running time. It * will improve response on a platform that either has suitable support in * the garbage collector (Linux and most Unix versions, win32 if the collector * was suitably built) or if "stubborn" allocation is used. On many platforms * this interacts poorly with system calls that write to the garbage collected * heap. */ void WGC_enableIncremental(WGC *self) { GC_enable_incremental(); Boolean_setValue(self->incrementalEnabled, True); LOGGER_DEBUG("incremental garbage collection enabled"); } /** * Allocates and clears nbytes of storage. Requires (amortized) time * proportional to nbytes. The resulting object will be automatically * deallocated when unreferenced. References from objects allocated with the * system malloc are usually not considered by the collector. */ void *WGC_allocate(size_t nbytes) { return GC_MALLOC(nbytes); } /** * Allocates nbytes of storage. Requires (amortized) time proportional to * nbytes. The resulting object will be automatically deallocated when * unreferenced. The client promises that the resulting object will never * contain any pointers. The memory is not cleared. This is the preferred * way to allocate strings, floating point arrays, bitmaps, etc. */ void *WGC_allocateAtomic(size_t nbytes) { return GC_MALLOC_ATOMIC(nbytes); } /** * Identical to GC_MALLOC, except that the resulting object is not * automatically deallocated. Unlike the system-provided malloc, the * collector does scan the object for pointers to garbage-collectable * memory, even if the block itself does not appear to be reachable. * (Objects allocated in this way are effectively treated as roots by the * collector.) */ void *WGC_allocateRoot(size_t nbytes) { return GC_MALLOC_UNCOLLECTABLE(nbytes); } /** * Allocate a new object of the indicated size and copy (a prefix of) the old * object into the new object. The old object is reused in place if * convenient. If the original object was allocated with GC_MALLOC_ATOMIC, the * new object is subject to the same constraints. If it was allocated as an * uncollectable object, then the new object is uncollectable, and the old * object (if different) is deallocated. */ void *WGC_reallocate(void *old, size_t newSize) { return GC_REALLOC(old, newSize); } /** * */ char *WGC_strdup(char *string) { size_t len = strlen(string) + 1; void *new = WGC_allocateAtomic(len); if (new == NULL) return NULL; return (char *)memcpy(new, string, len); } /** * Explicitly force a garbage collection. */ void WGC_collect(void) { GC_gcollect(); } /** * Explicitly deallocate an object. Typically not useful for small collectable * objects. */ void WGC_deallocate(void *dead) { GC_FREE(dead); } // EOF