2012-10-01 11 views
7

estoy tratando de añadir un poco de depuración comprobación de un código de desbloqueo CRITICAL_SECTION, y yo intentado el siguiente:¿Por qué el miembro OwningThread de CRITICAL_SECTION de tipo HANDLE, cuando indica la identificación del hilo?

... 
    if (m_pCritSect) { 
    ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId()); 
    LeaveCriticalSection(m_pCritSect); 
    } 
} 

De depuración CRITICAL_SECTIONS (con VS 2005, sobre todo en Windows XP) "sé" que el valor de OwningThread (miembro de la estructura RTL_CRITICAL_SECTION definida en winnt.h) es el valor de th ID del subproceso que contiene el bloqueo.

Sin embargo hilo IDs están representados por DWORD (typedef para unsigned long) valores, mientras que esta variable tiene el tipo HANDLE (typedef para void*) que requiere un reinterpret_cast para el uso de la HandleToULong Macro de basetsd.h para el código de seguridad funcione.

Incluso el MSDN docs Estado:

Cuando el primer subproceso llama a la rutina EnterCriticalSection, (...) OwningThread se convierte en el ID del hilo de la persona que llama.

Entonces, ¿por qué en la tierra se define como HANDLE?


Editar Nota: He encontrado a statement donde un cartel indica que el MANGO/DWORD-Id desajuste es cierta misfeature conocida de algunos detalles internos de Windows. Así que tal vez este es el caso aquí también:

GetCurrentThreadId devuelve un DWORD, que envío hasta el núcleo en un mensaje . PsLookupThreadByThreadId toma el ID del tema en un mango, ... ...

Se trata de un error conocido de API de Windows ("conocido" en que hablé con el administrador de filtros DEV relevante sobre esto, ya que aparece en Filtro Manager también debido a la API API de E/S problema). Siempre y cuando no tenga más de medio billón de hilos y procesos (ellos utilizan una única tabla de identificador compartido) estarás bien . Quizás para el momento ese sea un problema real, correremos algo diferente. [RE: ThreadId a HANDLE para 64 bit?, 08/08/08 14:21, Tony Mason]

+1

En cualquier caso, reinterpret_cast es exagerado. Un static_cast haría. Ambos HANDLE y DWORD son tipos integrales. –

+0

@ArmenTsirunyan - NO, en VS2005 no se puede usar un static_cast para lanzar un HANDLE a un DWORD: 'error C2440: 'static_cast': no ​​se puede convertir de 'HANDLE' a 'DWORD'' –

+0

Eso es raro. ¿Podría decirme para qué son typedefs? –

Respuesta

8

Cualquier identificador en el SDK cuyo nombre empieza con RTL o Rtl es código o declaraciones que forman parte del tiempo de ejecución capa, el pegamento que une el bien documentado Winapi con el api del sistema operativo nativo no documentado. El winapi es inamovible, el sistema operativo nativo cambia mucho con cada versión de Windows. Inevitablemente, el pegamento también cambia.

El winapi es la capa documentada, el sistema operativo nativo no está documentado. La capa de tiempo de ejecución tampoco estaba documentada, pero con el tiempo se revelaron partes de ella. Ya sea porque rellena una característica que falta en el winapi. O, en este caso, porque es realmente útil para solucionar problemas. Sin embargo, un problema principal al hacerlo es que una vez que se revela una declaración, Microsoft nunca puede volver a cambiarla. Porque hacerlo romperá los programas existentes, una gran carga para sus clientes.

Por lo tanto, seguramente el campo ThreadOwner realmente sostuvo el asa del hilo en una versión previa de Windows. Tenga en cuenta que LockSemaphore también es engañoso, en realidad es un evento de restablecimiento automático. Demasiado tarde para arreglarlo, el gato está fuera de la bolsa.

4

Creo que la razón principal es que se trata de un detalle de implementación. No me sorprendería si en algún momento de la historia fuera realmente un asa o algo así.

Además, le sugiero que no use los miembros internos en el código de producción, y I am not alone. Si se mira de cerca, API de sincronización utilizan CRITICAL_SECTION que no encontrará documentado como una estructura en MSDN y no RTL_CRITICAL_SECTION (que se typedef'ed a CRITICAL_SECTION)

El valor que se almacena en OwningThread miembro se ha tomado de CLIENT_ID parte de Thread Information Block.En CLIENT_ID como modela como PVOID que es probable por la que se modela de la misma manera dentro de CRITICAL_SECTION:

typedef struct _CLIENT_ID 
{ 
    PVOID UniqueProcess; 
    PVOID UniqueThread; 
} CLIENT_ID, *PCLIENT_ID; 
+0

Proporcioné un enlace de MSDN que recorre esta estructura (siempre que esté en la sección * Tareas de depuración avanzadas *), así que creo que está bastante bien utilizar esto * en el código de comprobación de depuración *. –

+0

Aún no se compilará si la estructura cambia, y tampoco considero el código de producción real del código ASSERT, ya que no se implementa para el usuario final (es decir, en la versión de lanzamiento) –

Cuestiones relacionadas