Mon blog à propos de programmation
Publié ou mis à jour le : 2013-12-31

Dispose parallèle et efficace (C#)

Dans .NET, pour chaque classe utilisée en parallèle (par plusieurs tâches, ou « thread safe » pour les anglophones) et implémentant IDisposable, il faut péniblement implémenter une méthode « Dispose » fonctionnant en parallèle aussi.
Ici je propose une petite structure qui nous facilite la vie, et qui en plus a le mérite d’être efficace: rapide et petite.

Code de la structure:

internal struct DisposeParallèle
{
  enum LibéréOuPas { PasEncoreSupprimé, DéjàSupprimé }

  int déjàSuppriméOuPas;

  internal void Dispose(Action MéthodeDeSuppression)
  {
    // "Interlocked" est bien plus rapide que "lock". 

    LibéréOuPas l = (LibéréOuPas)
      System.Threading.Interlocked.CompareExchange(
        ref this.déjàSuppriméOuPas,
        (int)LibéréOuPas.DéjàSupprimé,
        (int) LibéréOuPas.PasEncoreSupprimé);

    // Ici, "déjàSuppriméOuPas" a toujours pour valeur DéjàSupprimé, et il n'en changera plus.

    if (l == LibéréOuPas.PasEncoreSupprimé)thodeDeSuppression();
  }
}

Remarques:

  1. On utilise « Interlocked », qui est bien plus rapide que « lock ».
    La preuve: http://www.drdobbs.com/windows/boosting-performance-with-atomic-operati/226900048
  2. On se contente de mémoriser un simple entier 32 bits, là où un « lock » aurait nécessité un objet et un booléen.
    J’aurais aimé ne mémoriser qu’un booléen, d’ailleurs, mais « Interlocked » ne propose pas de méthode « CompareExchange » sur un booléen.
  3. En tant que simple structure, on économise les ressources objets, et on n’a pas besoin d’appeler un constructeur.

Exemple d’utilisation:

internal class MaClasse : IDisposable
{
  DisposeParallèle disposeParallèle;

  void IDisposable.Dispose()
  {
    this.disposeParallèle.Dispose(this.suppression);
  }

  void suppression()
  {
    // votre code...
  }
  
  ~MaClasse() // si nécessaire
  {
    ((IDisposable)this).Dispose();
  }
}

Ça reste assez simple à utiliser, avec un code bien découpé donc facile à maintenir.