Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Does ConditionalWeakTable work?

Discussion in 'Scripting' started by gwiazdorrr, Jan 23, 2019.

  1. gwiazdorrr

    gwiazdorrr

    Joined:
    Sep 29, 2014
    Posts:
    102
    I wanted to give ConditionalWeakTable a go, but I am not sure whether it works at all.

    I created a following play mode unit test:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.TestTools;
    4. using NUnit.Framework;
    5. using System.Collections;
    6. using System.Runtime.CompilerServices;
    7.  
    8. public class ConditionalWeakTableTest
    9. {
    10.     private static void Collect()
    11.     {
    12.         System.GC.Collect();
    13.         System.GC.WaitForPendingFinalizers();
    14.     }
    15.  
    16.     [UnityTest]
    17.     public IEnumerator Test()
    18.     {
    19.         object a = new object();
    20.         object b = new object();
    21.  
    22.         var cwt = new ConditionalWeakTable<object, object>();
    23.         cwt.Add(a, b);
    24.  
    25.         var wa = new System.WeakReference(a);
    26.         var wb = new System.WeakReference(b);
    27.  
    28.         Assert.IsTrue(wa.IsAlive);
    29.         Assert.IsTrue(wb.IsAlive);
    30.  
    31.         yield return null;
    32.         Collect();
    33.  
    34.         Assert.IsTrue(wa.IsAlive);
    35.         Assert.IsTrue(wb.IsAlive);
    36.  
    37.         b = null;
    38.  
    39.         for (int i = 0; i < 10; ++i)
    40.         {
    41.             yield return null;
    42.             Collect();
    43.  
    44.             Assert.IsTrue(wa.IsAlive);
    45.             Assert.IsTrue(wb.IsAlive);
    46.         }
    47.  
    48.         a = null;
    49.  
    50.         for ( int i = 0; i < 1000; ++i )
    51.         {
    52.             yield return null;
    53.             Collect();
    54.         }
    55.  
    56.         Assert.IsFalse(wa.IsAlive, "If CWS worked, this would be false.");
    57.         Assert.IsFalse(wb.IsAlive, "If CWS worked, this would be false.");
    58.     }
    59. }
    60.  
    No matter how long I wait, I always fail at the second last Assert - as if a & b were never collected. Similar code executed in a standalone C# project works.

    So, is there something I am doing wrong here? I am currently on 2018.2.18 with Mono backend, .NET 4.X.
     
    Last edited: Jan 23, 2019
    Flying_Banana likes this.
  2. Flying_Banana

    Flying_Banana

    Joined:
    Jun 19, 2019
    Posts:
    26
  3. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    Standalone C# projects works on .NET, while unity uses mono. Those are different GCs and some .NET features might be not supported in Mono. Check mono docs on this particular collection if it is supported or not.
     
  4. Flying_Banana

    Flying_Banana

    Joined:
    Jun 19, 2019
    Posts:
    26
    After some digging I found this tracked bug in Mono!

    Who knows how long it will take for this to be fixed...wish there is an option to switch Editor script backend to IL2CPP too.
     
  5. Gotmachine

    Gotmachine

    Joined:
    Sep 26, 2019
    Posts:
    30
    For anyone stumbling on this thread, ConditionalWeakTable indeed didn't work correctly in Unity prior to 2021.2, it was treating entries as strong references, basically making CWT act like a dictionary, thus making it totally useless.

    However, this was fixed at some point in Mono/Boehm, and the fix made it's way to Unity in 2021.2 when they updated to Mono 6.12.
     
  6. Flying_Banana

    Flying_Banana

    Joined:
    Jun 19, 2019
    Posts:
    26
    Four years then, apparently :’)