Sip: Boost.Thread es genial, y debe ajustarse perfectamente a sus necesidades. (En estos días, muchas personas dicen que casi se puede contar con Boost como funcionalidad incorporada.)
Todavía no hay clases que pueda usar de fábrica, pero una vez que tenga las primitivas de sincronización disponibles , es bastante simple implementar su propia envoltura segura para subprocesos, por ejemplo, std::stack
. Podría ser algo como esto (no implementar todos los métodos ...):
template <typename T> class MyThreadSafeStack {
public:
void push(const T& item) {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.push(item);
}
void pop() {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.pop();
}
T top() const { // note that we shouldn't return a reference,
// because another thread might pop() this
// object in the meanwhile
boost::mutex::scoped_lock lock(m_mutex);
return m_stack.top();
}
private:
mutable boost::mutex m_mutex;
std::stack<T> m_stack;
}
Si usted es nuevo en C++, por favor, aprender sobre RAII. Pertinente a este caso, Boost.Thread tiene las clases de "cerradura de alcance" para dificultar dispararse en la pierna al olvidarse de liberar un candado.
Si alguna vez se encuentra escribiendo código como este:
void doStuff() {
myLock.lock();
if (!condition) {
reportError();
myLock.unlock();
return;
}
try {
doStuffThatMayThrow();
}
catch (std::exception& e) {
myLock.unlock();
throw e;
}
doMoreStuff();
myLock.unlock();
}
, a continuación, sólo debe decir que no, e ir RAII lugar (sintaxis no directamente de Boost):
void doStuff() {
scoped_lock lock;
if (!condition) {
reportError();
return;
}
doStuffThatMayThrow();
doMoreStuff();
}
El punto es que cuando el objeto scoped_lock
sale del alcance, su destructor libera el recurso, en este caso, el bloqueo. Esto siempre ocurrirá, sin importar si sale del alcance lanzando una excepción o ejecutando la extraña declaración return
que su colega agregó furtivamente en el medio de su función, o simplemente al llegar al final de la función.
Si está interesado en la atomicidad de las instrucciones x86 PUSH/POP, por favor haga una pregunta por separado: no tiene nada que ver con C++, que no usaría tales instrucciones para acceder a una estructura de datos de pila. –
El comité está más ocupado escribiendo clases de predicación paralelas en DDJ en lugar de hacer abstracciones de modelo de memoria atómicas y mucho mejores para el compilador obligatorio en TR1 (probablemente ni siquiera en TR2). Para responder: realmente no empuja y pop y, por lo tanto, implícitamente modificar los registros a través de los hilos dice que actualmente se ejecuta en núcleos distintos, ¿o sí? :-) Buen golpe, pero no funcionaría. No puedes hacerlo sin cerrojo o al menos sin el martillo CAS. Para fanáticos de C++: Deben simplemente sentarse y definir y acordar los protocolos de coherencia existentes, + dejar algo de espacio para nuevos desarrollos. –
Para los interesados, investigué las operaciones atómicas e Intel tiene soporte de DCAS a través de cmpxchg16b. Lamentablemente, AMD solo tiene cmpxchg8b. No me importa, ya que estoy escribiendo para las máquinas Intel :) – bugmenot77