Clase wxMutex
Un objeto mutex es un objeto de sincronización cuyo estado se establece en "señalizado" cuando no es propiedad de ningún subproceso, y en "no señalizado" cuando es propiedad de alguno.
Su nombre proviene de su utilidad para coordinar el acceso mutuamente excluyente a un recurso compartido, ya que sólo un subproceso a la vez puede ser propietario de un objeto mutex.
Nota: Es preferible utilizar std::mutex en lugar de esta clase en el nuevo código.
Los mutex pueden ser recursivos en el sentido de que un subproceso puede bloquear un mutex que ya había bloqueado anteriormente (en lugar de bloquear todo el proceso en esta situación al comenzar a esperar un mutex que nunca se liberará mientras el subproceso está esperando), pero no se recomienda su uso en Unix y no son recursivos por defecto. La razón de esto es que los mutex recursivos no son compatibles con todas las variantes de Unix y, lo que es peor, no se pueden utilizar con wxCondition.
Por ejemplo, cuando varios subprocesos utilizan los datos almacenados en la lista enlazada, sólo se deben permitir modificaciones en la lista a un subproceso a la vez, ya que durante la adición de un nuevo nodo, la integridad de la lista se rompe temporalmente (esto también se denomina invariante del programa).
// Esta variable tiene el prefijo "s_" porque es estática: ver un "s_" en un
// programa multihilo es, en general, una buena señal de que se debe
// utilizar un mutex (o una sección crítica).
static wxMutex s_mutexProtectingTheGlobalData;
// Almacenamos algunos números en esta matriz global que presumiblemente
// es utilizada por varios subprocesos simultáneamente.
wxArrayInt s_data;
void MyThread::AddNewNode(int num)
{
// Asegúrate de que ningún otro subproceso acceda a la lista.
// Hay que tener en cuenta que no se recomienda utilizar Lock() y Unlock() de
// forma explícita y que sólo se hace aquí con fines ilustrativos. Es preferible
// utilizar wxMutexLocker, como se muestra a continuación.
s_mutexProtectingTheGlobalData.Lock();
s_data.Add(num);
s_mutexProtectingTheGlobaData.Unlock();
}
// devuelve verdadero si el número dado es mayor que todos los elementos de la matriz
bool MyThread::IsGreater(int num)
{
// Antes de utilizar la lista, debemos adquirir el mutex.
wxMutexLocker lock(s_mutexProtectingTheGlobalData);
size_t count = s_data.Count();
for ( size_t n = 0; n < count; n++ )
{
if ( s_data[n] > num )
return false;
}
return true;
}
Observar cómo se utilizó wxMutexLocker en la segunda función para garantizar que el mutex se desbloquee en cualquier caso: tanto si la función devuelve verdadero como falso (porque siempre se llama al destructor del bloqueo del objeto local). Utilizar esta clase en lugar de utilizar directamente wxMutex es, en general, más seguro, y lo es aún más si el programa utiliza excepciones C++.
Funciones miembro
wxMutex()
wxMutex::wxMutex(wxMutexType type = wxMUTEX_DEFAULT)
Constructor por defecto.
~wxMutex()
wxMutex::~wxMutex()
Destruye el objeto wxMutex.
Lock()
wxMutexError wxMutex::Lock()
Bloquea el objeto mutex.
Esto es equivalente a LockTimeout() con un tiempo de espera infinito.
Hay que tener en cuenta que si este mutex ya está bloqueado por el subproceso de llamada, esta función no se bloquea, sino que retorna inmediatamente.
Valor de retorno
Uno de los siguientes: wxMUTEX_NO_ERROR, wxMUTEX_DEAD_LOCK.
LockTimeout()
wxMutexError wxMutex::LockTimeout(unsigned long msec)
Intenta bloquear el objeto mutex durante el intervalo de tiempo especificado.
Valor de retorno
Uno de los siguientes valores: wxMUTEX_NO_ERROR, wxMUTEX_DEAD_LOCK, wxMUTEX_TIMEOUT.
TryLock()
wxMutexError wxMutex::TryLock()
Intenta bloquear el objeto mutex.
Si no puede, devuelve inmediatamente un error.
Valor de retorno
Uno de los siguientes: wxMUTEX_NO_ERROR, wxMUTEX_BUSY.
Unlock()
wxMutexError wxMutex::Unlock()
Desbloquea el objeto mutex.
Valor de retorno
Uno de los siguientes valores: wxMUTEX_NO_ERROR, wxMUTEX_UNLOCKED.