If we're linking against Boehm GC, then we may as well allow it to collect the runtime's hash tables, rather than doing that manually.

main
theraven 15 years ago
parent 7deef6854a
commit 2d9f41aa94

@ -1,3 +1,4 @@
#ifndef ENABLE_GC
#include "objc/toydispatch.h"
#include "lock.h"
#include "visibility.h"
@ -17,3 +18,5 @@ PRIVATE void objc_collect_garbage_data(void(*cleanup)(void*), void *garbage)
}
dispatch_async_f(garbage_queue, garbage, cleanup);
}
#endif

@ -22,6 +22,16 @@
#include <string.h>
#include <stdio.h>
#ifdef ENABLE_GC
# include <gc/gc.h>
# define CALLOC(x,y) GC_MALLOC(x*y)
# define IF_NO_GC(x)
#else
# define CALLOC(x,y) calloc(x,y)
# define IF_NO_GC(x) x
#endif
#ifndef MAP_TABLE_NAME
# error You must define MAP_TABLE_NAME.
#endif
@ -77,7 +87,7 @@ typedef struct
{
mutex_t lock;
unsigned int table_used;
unsigned int enumerator_count;
IF_NO_GC(unsigned int enumerator_count;)
struct PREFIX(_table_cell_struct) table[MAP_TABLE_STATIC_SIZE];
} PREFIX(_table);
static PREFIX(_table) MAP_TABLE_STATIC_NAME;
@ -94,14 +104,14 @@ typedef struct PREFIX(_table_struct)
mutex_t lock;
unsigned int table_size;
unsigned int table_used;
unsigned int enumerator_count;
IF_NO_GC(unsigned int enumerator_count;)
struct PREFIX(_table_struct) *old;
struct PREFIX(_table_cell_struct) *table;
} PREFIX(_table);
PREFIX(_table) *PREFIX(_create)(uint32_t capacity)
{
PREFIX(_table) *table = calloc(1, sizeof(PREFIX(_table)));
PREFIX(_table) *table = CALLOC(1, sizeof(PREFIX(_table)));
# ifndef MAP_TABLE_NO_LOCK
INIT_LOCK(table->lock);
# endif
@ -112,8 +122,6 @@ PREFIX(_table) *PREFIX(_create)(uint32_t capacity)
# define TABLE_SIZE(x) (x->table_size)
#endif
// Collects garbage in the background
void objc_collect_garbage_data(void(*)(void*), void*);
#ifdef MAP_TABLE_STATIC_SIZE
static int PREFIX(_table_resize)(PREFIX(_table) *table)
@ -122,7 +130,10 @@ static int PREFIX(_table_resize)(PREFIX(_table) *table)
}
#else
# ifndef MAP_TABLE_SINGLE_THREAD
# if !(defined(MAP_TABLE_SINGLE_THREAD) || defined(ENABLE_GC))
// Collects garbage in the background
void objc_collect_garbage_data(void(*)(void*), void*);
/**
* Free the memory from an old table. By the time that this is reached, there
* are no heap pointers pointing to this table. There may be iterators, in
@ -162,13 +173,13 @@ static int PREFIX(_table_resize)(PREFIX(_table) *table)
// Note: We multiply the table size, rather than the count, by two so that
// we get overflow checking in calloc. Two times the size of a cell will
// never overflow, but two times the table size might.
struct PREFIX(_table_cell_struct) *newArray = calloc(table->table_size, 2 *
struct PREFIX(_table_cell_struct) *newArray = CALLOC(table->table_size, 2 *
sizeof(struct PREFIX(_table_cell_struct)));
if (NULL == newArray) { return 0; }
// Allocate a new table structure and move the array into that. Now
// lookups will try using that one, if possible.
PREFIX(_table) *copy = calloc(1, sizeof(PREFIX(_table)));
PREFIX(_table) *copy = CALLOC(1, sizeof(PREFIX(_table)));
memcpy(copy, table, sizeof(PREFIX(_table)));
table->old = copy;
@ -192,10 +203,12 @@ static int PREFIX(_table_resize)(PREFIX(_table) *table)
}
}
table->old = NULL;
# ifdef MAP_TABLE_SINGLE_THREAD
# ifndef ENABLE_GC
# ifdef MAP_TABLE_SINGLE_THREAD
free(copy);
# else
# else
objc_collect_garbage_data(PREFIX(_table_collect_garbage), copy);
# endif
# endif
return 1;
}
@ -448,21 +461,23 @@ PREFIX(_next)(PREFIX(_table) *table,
{
if (NULL == *state)
{
*state = calloc(1, sizeof(struct PREFIX(_table_enumerator)));
*state = CALLOC(1, sizeof(struct PREFIX(_table_enumerator)));
// Make sure that we are not reallocating the table when we start
// enumerating
MAP_LOCK();
(*state)->table = table;
(*state)->index = -1;
__sync_fetch_and_add(&table->enumerator_count, 1);
IF_NO_GC(__sync_fetch_and_add(&table->enumerator_count, 1);)
MAP_UNLOCK();
}
if ((*state)->seen >= (*state)->table->table_used)
{
#ifndef ENABLE_GC
MAP_LOCK();
__sync_fetch_and_sub(&table->enumerator_count, 1);
MAP_UNLOCK();
free(*state);
#endif
#ifdef MAP_TABLE_ACCESS_BY_REFERENCE
return NULL;
#else
@ -481,11 +496,13 @@ PREFIX(_next)(PREFIX(_table) *table,
#endif
}
}
#ifndef ENABLE_GC
// Should not be reached, but may be if the table is unsafely modified.
MAP_LOCK();
table->enumerator_count--;
MAP_UNLOCK();
free(*state);
#endif
#ifdef MAP_TABLE_ACCESS_BY_REFERENCE
return NULL;
#else
@ -545,3 +562,6 @@ PREFIX(_current)(PREFIX(_table) *table,
#ifdef MAP_TABLE_ACCESS_BY_REFERENCE
# undef MAP_TABLE_ACCESS_BY_REFERENCE
#endif
#undef CALLOC
#undef IF_NO_GC

Loading…
Cancel
Save