/* from the main program instead. */
GC_API void GC_CALL GC_init(void);
+/* Perform the collector shutdown. (E.g. dispose critical sections on */
+/* Win32 target.) A duplicate invocation is a no-op. GC_INIT should */
+/* not be called after the shutdown. See also GC_win32_free_heap(). */
+GC_API void GC_CALL GC_deinit(void);
+
/* General purpose allocation routines, with roughly malloc calling */
/* conv. The atomic versions promise that no relevant pointers are */
/* contained in the object. The non-atomic versions guarantee that the */
GC_EXTERN GC_bool GC_is_initialized; /* GC_init() has been run. */
-#if defined(MSWIN32) || defined(MSWINCE)
- void GC_deinit(void);
- /* Free any resources allocated by */
- /* GC_init */
-#endif
-
GC_INNER void GC_collect_a_little_inner(int n);
/* Do n units worth of garbage */
/* collection work, if appropriate. */
}
#endif
+ GC_API void GC_CALL GC_deinit(void)
+ {
+ if (GC_is_initialized) {
+ /* Prevent duplicate resource close. */
+ GC_is_initialized = FALSE;
+# if defined(THREADS) && (defined(MSWIN32) || defined(MSWINCE))
+ DeleteCriticalSection(&GC_write_cs);
+ DeleteCriticalSection(&GC_allocate_ml);
+# endif
+ }
+ }
+
#if defined(MSWIN32) || defined(MSWINCE)
# if defined(_MSC_VER) && defined(_DEBUG) && !defined(MSWINCE)
STATIC HANDLE GC_log = 0;
- void GC_deinit(void)
- {
-# ifdef THREADS
- if (GC_is_initialized) {
- DeleteCriticalSection(&GC_write_cs);
- }
-# endif
- }
-
# ifdef THREADS
# if defined(PARALLEL_MARK) && !defined(GC_ALWAYS_MULTITHREADED)
# define IF_NEED_TO_LOCK(x) if (GC_parallel || GC_need_to_lock) x
UNTESTED(GC_malloc_explicitly_typed_ignore_off_page);
UNTESTED(GC_debug_change_stubborn);
UNTESTED(GC_debug_strndup);
+ UNTESTED(GC_deinit);
UNTESTED(GC_strndup);
UNTESTED(GC_posix_memalign);
UNTESTED(GC_new_free_list);
# ifdef MSWINCE
GC_deinit();
- DeleteCriticalSection(&GC_allocate_ml);
# endif
return (int) exit_code;
}
GC_delete_gc_thread_no_free(&dll_thread_table[i]);
}
GC_deinit();
- DeleteCriticalSection(&GC_allocate_ml);
}
break;
}