Problema con timed_mutex

12 views
Skip to first unread message

Juan Manuel Ollé

unread,
Apr 17, 2012, 3:43:49 PM4/17/12
to cp...@googlegroups.com
 
Tengo un problema y si bien encontre una solucion (artesanal) siempre es bueno preguntar si hay alguna forma elegante para resolver el problema
Es por eso que voy a tratar de explicar que esta pasando: supongamos el siguiente codigo
 
 void f_thread(int n)
{   
    boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(3000);
    if(!my.lock(timeout))
    {
        return;
    }
   
    boost::this_thread::interruptible_wait(1000);    
    my.unlock();
}
int main()
{
    std::vector<boost::shared_ptr<boost::thread> >  threads;
    for(int n = 0; n < 10; n++)
    {
        threads.push_back( boost::shared_ptr<boost::thread>(new boost::thread(f_thread, n)));
        boost::this_thread::interruptible_wait(200);
    }
    std::for_each(threads.begin(),threads.end(), boost::bind(&(boost::thread::join), _1));
    return 0;
}
 
Luego del Primer thread los demas que empiezan a llegar se bloquean en el mutex hasta que el primero que llego lo libera, en ese momento otro thread toma el mutex y asi sucesivamente.
El problema consiste en que el orden en el que se van tomando no es especificado pudiendo quedar uno viejito sin tomar hasta que salta su time out.
 
Buscando en la documentacion de boost encontre varias opciones pero ninguna a la que le pueda asignar una prioridad.
 
Me guian por donde podria encarar
 
 
 

Ing. Esteban D. Papp

unread,
Apr 17, 2012, 4:27:39 PM4/17/12
to cp...@googlegroups.com
Que tal si los pones en una cola y cuando uno salga le pasa la posta al siguiente de la cola?

2012/4/17 Juan Manuel Ollé <juanman...@gmail.com>
 
 
 

--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"

Juan Manuel Ollé

unread,
Apr 17, 2012, 5:05:59 PM4/17/12
to cp...@googlegroups.com
Se necesita que sea syncrono, si utilizo una cola, luego debo esperar por la respuesta.

Billy Biset

unread,
Apr 17, 2012, 5:12:05 PM4/17/12
to cp...@googlegroups.com
No entiendo precisamente q es lo q queres priorizar...

Tu aclaración sobre lo sync. tampoco la entiendo.

Querés poner un barrier para 'joinear' un cierto set de threads?

Además querés que se prioricen los threads según algún criterio?

Ramiro del Corro

unread,
Apr 17, 2012, 4:08:53 PM4/17/12
to cp...@googlegroups.com
Hola Juan, no se que intentas solucionar con algo asi pero pinta a un scheduler.

Podes ver:
http://threadingbuildingblocks.org/codesamples.php#The_Task_Scheduler

Saludos
Ramiro

2012/4/17 Juan Manuel Ollé <juanman...@gmail.com>
 
 
 

--

Ing. Esteban D. Papp

unread,
Apr 17, 2012, 5:44:05 PM4/17/12
to cp...@googlegroups.com
2012/4/17 Juan Manuel Ollé <juanman...@gmail.com>
Se necesita que sea syncrono, si utilizo una cola, luego debo esperar por la respuesta.

Me parece que fui muy escueto en la respuesta...

- sincronizar acceso a la cola (o utilizar una cola atomica)
- si la cola no esta vacia, ponerse en la cola y loquear thread (pause del thread o wait por evento que contiene el thread)
- si la cola esta vacia hacer trabajo, al terminar, sacar siguiente elemento de la cola y resumir (cuando este termine chequeara el estado de la cola y sacara el siguiente o no)

Tambien podes hacer que un thread maestro sea el que haga el encole/desencole, eso es mas parecido a lo que te sugiere Ramiro que es un scheduler.

Juan Manuel Ollé

unread,
Apr 17, 2012, 6:43:06 PM4/17/12
to cp...@googlegroups.com
Ok, trato de ser mas especifico

La cosa viene porque N thread tratan de acceder a un recurso protegido (no queue ni dispatcher ni thread extra)
como se ve en el codigo cada un determinado tiempo se va generando un thread nuevo que quiere acceder al recurso, en operacion normal el tiempo entre requerimientos de adquirir el recuro es mucho mayor que el que tarda la llamada a funcion protegida.
Pero puede que en algunos casos muchos threads quieren  acceder y van quedando bloqueados.
cada thread trata de adquirir el mutex durante un tiempo y si no puede falla.

se puede crear un mutex que al momento de liberarse (por el thread que lo adquirio) no lo tome otro thread al azar sino que tome el thread que hace mas que esta esperando?

Carlos Bederián

unread,
Apr 17, 2012, 7:37:21 PM4/17/12
to cp...@googlegroups.com
Lo que querés es una condition variable sobre la disponibilidad del recurso. La documentación de Boost no dice nada sobre a cuál de los threads que esperan le pasa la notificación cuando corrés notify_one(), pero casi todas las implementaciones usan una cola por detrás para que no haya starvation.

Juan Manuel Ollé

unread,
Apr 17, 2012, 8:11:23 PM4/17/12
to cp...@googlegroups.com
Carlos,

Si por ahi encontre la forma de hacerlo, pero no me gusta demasiado la implementacion que realice.
En realidad use 2 mutex y una conditional, junto a un set sonde llevo la prioridad (un contador que se incrementa)

(mañana pego un pedacito de codigo con el ejemplo)

esta bueno ponerse a jugar con estas cosas, pero si ya esta hecho (usando boost por ejemplo) hay un monton de ojos viendo que no se escape nada




2012/4/17 Carlos Bederián <zzz...@gmail.com>

Alejandro Santos

unread,
Apr 17, 2012, 11:46:06 PM4/17/12
to cp...@googlegroups.com
No conozco si ya existe algo asi, ya se en boost o en otra libreria,
pero no parece nada extraño.

Como te decían antes, la forma general de solucionarlo es con una
queue para ordenar los threads. Podés (y debés) usar un mutex (o algun
otra primitiva de sincronización), pero no conozco nada que ya esté
hecho.

Lo que tendrías que hacer es construir tu propio mutex_con_prioridad_t
donde en las operaciones de lock() y unlock() hagas algo parecido a lo
que dice Esteban, y en vez de usar el mutex directamente desde los
threads, proteger el recurso compartido con tu propio
mutex_con_prioridad_t.


El día 17 de abril de 2012 19:43, Juan Manuel Ollé
<juanman...@gmail.com> escribió:

--
Alejandro Santos

Juan Manuel Ollé

unread,
Apr 18, 2012, 8:57:02 AM4/18/12
to cp...@googlegroups.com
Bueno lugo de jugar un rato llegue a algo como esto
 
class my_mutex
{
    boost::timed_mutex main_mutex;
    boost::condition_variable cond;
    boost::mutex local_mutex;
    std::set<int> values;
    int counter;
    int actual;
public:
    my_mutex() : counter(0),actual(0) {}
    bool lock(const boost::system_time & timeout)
    {
        boost::mutex::scoped_lock local(local_mutex);
        int n = counter++;
        values.insert(n);
        while( n != *(values.begin()))
  {
            if(!cond.timed_wait(local,timeout))
            {
                values.erase(n);
                return false;
            }
        }       
        main_mutex.lock();
        actual = n;             
        return true;
    }
    void unlock()
    {
        boost::mutex::scoped_lock local(local_mutex);
        values.erase(actual); 
        if(values.empty()) counter = 0;
        main_mutex.unlock();
        cond.notify_all();
    }
};

Y como lo que quedo es medio rebuzcado, he ahi que genere este post, para que en su experiencia me puedan guiar a una solucion mas estandar.
 
Saludos

Carlos Cattaneo

unread,
Apr 18, 2012, 1:51:41 PM4/18/12
to cp...@googlegroups.com
Juan Manuel:
 
 
Y fijate si realmente necesitás un lock que haga algo diferente al que ofrece la plataforma que uses.
 
Si realmente lo necesitás. No escondas la funcionalidad en on lock custom. Dejá expuesto que estás usando una cola que determina el orden en el que se accede al recurso. El que tenga que mantener el código te lo va a agredecer.
Quizás sos vos mismo dentro de algunos meses....:-)
 
Saludos,
Carlos

Juan Manuel Ollé

unread,
Apr 18, 2012, 2:43:12 PM4/18/12
to cp...@googlegroups.com
Carlos,
 
Muchas gracias por tu aporte, sera cuestion de evaluar un redisenio del modulo, lo mas conveniente es usar una queue en mi caso particular.
 
Saludos
 
Juan Manuel

Carlos Cattaneo

unread,
Apr 18, 2012, 5:19:58 PM4/18/12
to cp...@googlegroups.com
De nada.
Reply all
Reply to author
Forward
0 new messages