gpointer *entries;
guint16 *domain_ids;
domain_ids = g_malloc0 (sizeof (guint16) * new_size);
- entries = g_malloc (sizeof (gpointer) * new_size);
- /* we disable GC because we could lose some disappearing link updates */
- mono_gc_disable ();
- mono_gc_memmove (entries, handles->entries, sizeof (gpointer) * handles->size);
- mono_gc_bzero (entries + handles->size, sizeof (gpointer) * handles->size);
+ entries = g_malloc0 (sizeof (gpointer) * new_size);
memcpy (domain_ids, handles->domain_ids, sizeof (guint16) * handles->size);
for (i = 0; i < handles->size; ++i) {
MonoObject *obj = mono_gc_weak_link_get (&(handles->entries [i]));
- if (handles->entries [i])
- mono_gc_weak_link_remove (&(handles->entries [i]), track);
- /*g_print ("reg/unreg entry %d of type %d at %p to object %p (%p), was: %p\n", i, handles->type, &(entries [i]), obj, entries [i], handles->entries [i]);*/
if (obj) {
mono_gc_weak_link_add (&(entries [i]), obj, track);
+ mono_gc_weak_link_remove (&(handles->entries [i]), track);
+ } else {
+ g_assert (!handles->entries [i]);
}
}
g_free (handles->entries);
g_free (handles->domain_ids);
handles->entries = entries;
handles->domain_ids = domain_ids;
- mono_gc_enable ();
}
/* set i and slot to the next free position */
--- /dev/null
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace WeakReferenceTest
+{
+ public static class Cache {
+ static GCHandle[] table = new GCHandle[1024 * 1024];
+
+ public static T Probe<T>(int hc) where T : class
+ {
+ int index = hc & (table.Length - 1);
+ lock (table)
+ {
+ var wr = table[index];
+ if (!wr.IsAllocated)
+ return null;
+ return wr.Target as T;
+ }
+ }
+
+ public static T Add<T>(T obj, int hc) where T : class
+ {
+ int index = hc & (table.Length - 1);
+ lock (table)
+ {
+ table[index] = GCHandle.Alloc (obj, GCHandleType.Weak);
+ }
+ return obj;
+ }
+
+ }
+
+ public class Tester {
+ static readonly int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
+
+ Random rand = new Random(seed);
+
+ bool alive;
+ Thread thread;
+
+ public void Start()
+ {
+ alive = true;
+ thread = new Thread(new ThreadStart(Work));
+ thread.Start();
+ }
+
+ void Work()
+ {
+ do {
+
+ var item = rand.Next ();
+ var probed = Cache.Probe<object>(item.GetHashCode());
+
+ if (probed == null) {
+ Cache.Add<object>(item, item.GetHashCode());
+ }
+
+ if (rand.NextDouble() <= 0.1) {
+ GC.Collect();
+ }
+
+ } while (alive);
+ }
+
+ public void Stop ()
+ {
+ alive = false;
+ }
+
+ }
+
+ static class RandHelper {
+ public static string RandString(this Random rand, int len)
+ {
+ char[] table = new char[len];
+ for (int idx = 0; idx < len; idx++) {
+ table[idx] = (char) ('a' + idx);
+ }
+ return new string(table, 0, len);
+ }
+ }
+
+ class MainClass
+ {
+ public static void Main (string[] args)
+ {
+ Console.WriteLine("Starting cache testers");
+ List<Tester> testers = new List<Tester>();
+ for (int count = 0; count < 10; count++) {
+ testers.Add(new Tester());
+ }
+
+ foreach (var tester in testers) {
+ tester.Start();
+ }
+
+ for (int i = 0; i < 4; ++i)
+ {
+ Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+
+ foreach (var tester in testers)
+ {
+ tester.Stop ();
+ }
+ }
+ }
+}