2010-07-19 14 views
6

He estado usando C# durante los últimos años y actualmente estoy corrigiendo errores en C++. En C# que podría utilizar el bloqueo en un objeto de hacer mi hilo de código seguro con:Bloqueo/desbloqueo automático usando el alcance en C++ (desde el fondo C#)

lock(lockObject) 
{ 
    // Do some work 
} 

Esto desbloquear el lockOject si había una excepción dentro del // Do some work

¿Hay algo similar en C++? En el momento en que se me ocurre ya sea:

// Code 
{ 
    AutoLock lock(lockObject); 
    // Do some work 
} 
// More Code 

Pero no me gustan las llaves sólo para mi alcance AutoLock. En el momento que estoy haciendo:

AutoLock lock(lockObject); 
// Do some work 
lock.Unlock(); 

Y dejar excepción liberación desenrollar el bloqueo si hay una excepción en //Do some work.

Lo que estoy haciendo en este momento funciona, pero me pregunto si hay una mejor manera, gracias.

+0

_Pero no me gustan las llaves para ampliar mi 'AutoLock'._ Además de su ubicación, ¿cómo son diferentes de lo que se hace en C#? –

+0

Con C# 'using (..) {...} 'y' lock (...) {...} 'puedes ver lo que está pasando. Simplemente me parece mal tener solo '{...}' vacío para crear un alcance local para hacer que 'Autolock' se destruya. – JLWarlow

+0

Eso tiene sentido. Una de las ventajas de la forma C++ de hacer las cosas es que solo necesita un alcance para limpiar múltiples bloqueos; si recuerdo bien, en C# puede terminar con cosas como 'lock (m0) {lock (m1) {lock (m2) {}}}' –

Respuesta

8

Pero no me gustan las llaves de tuercas solo para alcanzar mi AutoLock.

Así es como se hace en C++.

Tenga en cuenta que no necesita tener un bloque de alcance independiente para cada AutoLock; lo siguiente también está bien:

{ 
    AutoLock lock1; 
    AutoLock lock2; 
    // more code goes here 
} // lock2 gets destroyed, then lock1 gets destroyed 

No tiene que ser un bloque de alcance por separado tampoco; si está bloqueando algo en una función y no necesita que se desbloquee hasta que la función regrese, entonces simplemente puede usar el alcance de la función para restringir el bloqueo. Del mismo modo, si está bloqueando algo durante cada iteración en un bloque de bucle, puede usar el bloque de alcance del bucle para restringir el bloqueo.

Su enfoque de desbloqueo manual del mutex cuando haya terminado con él está bien, pero no es idiomático C++ y no es tan claro. Hace que sea más difícil averiguar dónde está desbloqueado el mutex (no mucho más difícil, quizás, pero más difícil de lo necesario).

+0

Re: Desbloqueo manual. Es cierto, no fue una elección ideal. He usado punteros inteligentes para interfaces que te permiten '.Release()' pero se lanzarán automáticamente cuando estén fuera del alcance. Ha pasado bastante tiempo desde que estaba codificando en C++, es posible que haya olvidado/olvidado algo que se ajusta a lo que estaba buscando. De ahí esta pregunta. – JLWarlow

2

Su segunda versión está bien. Considere dividir su método si tiene demasiadas llaves que son solo para el bloqueo del alcance. Lea en RAII, ese es el patrón general detrás de esta técnica, y se puede aplicar a todo tipo de gestión de recursos.

+0

Gracias por el enlace en 'RAII', ahora estoy buscando punteros inteligentes para proteger un bloque de memoria que recibe mi código. – JLWarlow