2011-01-08 4 views
8

¿Cómo se usa std.typecons.RefCounted!(T) para hacer un objeto contado de referencia en D?Hacer un objeto de referencia contado en D usando RefCounted! (T)

He intentado averiguar qué hace std.array.Array internamente al mirar la fuente, pero mientras puedo leer la fuente, simplemente no puedo entender qué es una "carga útil" o cómo funciona cuando hay cosas como copia de estructuras bit a bit implicada, así como también por qué algunas cosas se duplican en la estructura interna y externa.

¿Alguien podría proporcionar un ejemplo o un enlace sobre cómo usarlo, por ejemplo, para envolver un simple Win32 HANDLE?

Gracias!

Respuesta

9

Descargo de responsabilidad: No he probado mis afirmaciones, solo lea el documentation.

La carga útil se refiere a lo que se está almacenando. En su caso, la carga útil es la MANIJA Win32. Desde MANGO es un número entero que no quieres hacer:

auto refHandle = RefCounted!HANDLE(WhatGetsMeAHandle()); 

Debido a una función de Windows tendrá que ser llamado cuando el mango se sale del ámbito.

En std.containers.Array lo que vio fue una estructura llamada Payload, que tenía un campo llamado _payload. La estructura va a ser el almacenamiento de los datos, a los que se accede a través de _payload. Esto proporciona un nivel de direccionamiento indirecto que se utilizará más adelante.

Notarás que RefCounted es en realidad used on the Array structure. Esto significa que el destructor para esa estructura solo se invocará cuando el recuento de referencia sea 0. Por lo tanto, el ~ this() dentro de Payload es el lugar en el que desearía limpiar su HANDLE.

Qué está sucediendo: dado que struct es un tipo de valor, cada vez que la estructura sale del ámbito se llama al destructor, no hay uno para Array, pero Payload está envuelto en un RefCounted, el destructor para RefCounted! es tambien llamado. Y solo cuando el recuento de referencias llega a cero se llama al destructor para la carga útil.

Ahora, RefCounted tiene semántica de referencia, esto significa que al tener una matriz a, puede asignarla a auto b = a; y todo se copiará, pero RefCounted tiene un postblits defined, lo que significa que los datos no se copiarán, pero el recuento de referencias será incrementado.

Ahora intentaré ofrecerle un esquema de envoltura para lo que desee. Probablemente lo ayude a visualizar la información anterior, pero puede no ser del todo correcto. Avíseme si algo necesita reparación.

struct MyWinWrapper { 
    struct Payload { 
     HANDLE _payload; 
     this(HANDLE h) { _payload = h; } 
     ~this() { freeHandleHere(_payload); } 

     // Should never perform these operations 
     this(this) { assert(false); } 
     void opAssign(MyWinWrapper.Payload rhs) { assert(false); } 
    } 

    private alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; 
    private Data _data; 

    this(HANDLE h) { _data = Data(h); } 
} 

Dado que no existe un constructor predeterminado para una estructura, es probable que desee proporcionar una función gratuita que devuelva esta estructura.

+0

¡Gracias por la respuesta detallada! ¡Lo hiciste parecer tan fácil! :) – Mehrdad

+0

@Lambert, originalmente iba a seguir diciendo que no use el primer fragmento de código ya que no sabía cómo hacer lo que quería. Pero luego me interesé y comencé a escribir lo que estaba aprendiendo. –

+1

¿No debería el controlador de myWinWrapper '' data = Data (h); '? –

Cuestiones relacionadas