+}
+
+#if defined(ENABLE_GC_BOEHM)
+
+struct FinalizerData {
+ Finalizer::FinalizerFunc f;
+ void *data;
+ FinalizerData(Finalizer::FinalizerFunc f, void *data): f(f), data(data) { }
+};
+
+Mutex final_mutex;
+// final_map contains registered custom finalizers for a given Java
+// object. Must be accessed with held final_mutex.
+std::multimap<java_handle_t *, FinalizerData> final_map;
+
+static void custom_finalizer_handler(void *object, void *data)
+{
+ typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+ java_handle_t *hdl = (java_handle_t *) object;
+ MutexLocker l(final_mutex);
+ MI it_first = final_map.lower_bound(hdl), it = it_first;
+ assert(it->first == hdl);
+ for (; it->first == hdl; ++it) {
+ final_mutex.unlock();
+ it->second.f(hdl, it->second.data);
+ final_mutex.lock();
+ }
+ final_map.erase(it_first, it);
+}
+
+/* attach_custom_finalizer *****************************************************
+
+ Register a custom handler that is run when the object becomes
+ unreachable. This is intended for internal cleanup actions. If the
+ handler already exists, it is not registered again, and its data
+ pointer is returned.
+
+*******************************************************************************/
+
+void *Finalizer::attach_custom_finalizer(java_handle_t *h, Finalizer::FinalizerFunc f, void *data)
+{
+ MutexLocker l(final_mutex);
+
+ GC_finalization_proc ofinal = 0;
+ void *odata = 0;
+
+ GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, &ofinal, &odata);
+
+ /* There was a finalizer -- reinstall it. We do not want to
+ disrupt the normal finalizer operation. This is thread-safe
+ because the other finalizer is only installed at object
+ creation time. */
+ if (ofinal && ofinal != custom_finalizer_handler)
+ GC_REGISTER_FINALIZER_NO_ORDER(LLNI_DIRECT(h), ofinal, odata, 0, 0);
+
+ typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+ std::pair<MI, MI> r = final_map.equal_range(h);
+ for (MI it = r.first; it != r.second; ++it)
+ if (it->second.f == f)
+ return it->second.data;
+ final_map.insert(r.first, std::make_pair(h, FinalizerData(f, data)));
+ return data;
+}
+
+/* reinstall_custom_finalizer **************************************************
+
+ Arranges for the custom finalizers to be called after the Java
+ finalizer, possibly much later, because the object needs to become
+ unreachable.
+
+*******************************************************************************/
+
+void Finalizer::reinstall_custom_finalizer(java_handle_t *h)
+{
+ MutexLocker l(final_mutex);
+ std::multimap<java_handle_t *, FinalizerData>::iterator it = final_map.find(h);
+ if (it == final_map.end())
+ return;
+
+ GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, 0, 0);