[Resolvido] C++ lock

Boa tarde pessoal,
estou com o seguinte problema em meu codigo C++,

resumindo tenho 2 ou mais threads removendo dados de uma queue, para isso tenho que usar algum tipo de lock, foi quando eu lembrei do mutex (ou semaforo) entao implementei da seguinte maneira.

[code]
pthread_mutex_t proc_fila_mutex = PTHREAD_MUTEX_INITIALIZER;

		pthread_mutex_lock(&proc_fila_mutex);
		if (!filaPessoas.empty()){
			pessoa = filaPessoas.front();
			filaPessoas.pop();
			hasPessoa = true;
		}
		pthread_mutex_unlock(&proc_fila_mutex)[/code]

porem quando a primeira thread libera com o unlock, a segunda nao entra no lock, ela fica travada por um tempo, ou seja, nao esta sendo instantâneo…alguem sabe como eu posso fazer isso corretamente?!

Grato.

Se você está usando C++ é mais fácil, seguro e portável controlar threads através da boost:
http://www.boost.org/doc/libs/1_43_0/doc/html/thread.html

[quote=Sad7]Boa tarde pessoal,
estou com o seguinte problema em meu codigo C++,

resumindo tenho 2 ou mais threads removendo dados de uma queue, para isso tenho que usar algum tipo de lock, foi quando eu lembrei do mutex (ou semaforo) entao implementei da seguinte maneira.

[code]
pthread_mutex_t proc_fila_mutex = PTHREAD_MUTEX_INITIALIZER;

		pthread_mutex_lock(&proc_fila_mutex);
		if (!filaPessoas.empty()){
			pessoa = filaPessoas.front();
			filaPessoas.pop();
			hasPessoa = true;
		}
		pthread_mutex_unlock(&proc_fila_mutex)[/code]

porem quando a primeira thread libera com o unlock, a segunda nao entra no lock, ela fica travada por um tempo, ou seja, nao esta sendo instantâneo…alguem sabe como eu posso fazer isso corretamente?!

Grato.[/quote]

Sua expectativa não está de acordo com a especificação dessa API.
A API não garante que uma thread esperando pelo mutex receberá tempo de processamento instantaneamente após o mutex ser destravado.

Quando, como e porquê uma thread recebe tempo de processamento é ditado pela política de escalonamento do sistema, que pode variar de implementação para implementação.

Seria bom também usar RAII nos mutexes. Senão uma exception disparada no meio desse código poderá impedir que o unlock seja chamado (ou um programador mais desatento pode inadvertidamente inserir um return ali no meio).

Agora, para isso você vai acabar criando uma classe Mutex, que é o que a boost já faz… por isso, volto a insistir que use a boost ao invés do pThreads diretamente.

[quote=ViniGodoy]Seria bom também usar RAII nos mutexes. Senão uma exception disparada no meio desse código poderá impedir que o unlock seja chamado (ou um programador mais desatento pode inadvertidamente inserir um return ali no meio).

Agora, para isso você vai acabar criando uma classe Mutex, que é o que a boost já faz… por isso, volto a insistir que use a boost ao invés do pThreads diretamente.[/quote]

Entao vou estudar melhor a boost, o que eu preciso eh perfmormace e segurança, e se voce disse q eh melhor irei trocar…
Valeu Vini.

Vini,
eu estou com o seguinte problema, eu tenho q iniciar duas threads de uma vez, uma para receber e uma para enviar,estou fzd da seguinte maneira:

thread thRecv(thRecvMethod, clntSock);
		thRecv.join();

		thread thOCR(thOcrMethod, clntSock);
		thOCR.join();

porem ele nao passa do primeiro join, inicia a primeira thread e fica parado, o que eu devo fzer !?

e outra pergunta, ql API para log vc me aconselha a usar no C++.
Grato.

O join() é o comando que manda a thread atual esperar a thread que recebeu o join().

Se você não quer espera-la, então não dê o join(). Talvez você quisesse é isso aqui:

[code]//Dispara as duas.
thread thRecv(thRecvMethod, clntSock);
thread thOCR(thOcrMethod, clntSock);

//Espera as duas terminarem
thRecv.join();
thOCR.join(); [/code]

Que tal a boost log?
http://boost-log.sourceforge.net/libs/log/doc/html/index.html

Na verdade, a boost é uma biblioteca excelente com muita coisa. Vale a pena estuda-la a fundo. E ela é feita pelo mesmo comitée que cria o C++. Tudo de altíssima qualidade, performance e praticamente oficial.

E o melhor, tem uma documentação simplesmente excelente.

[quote=ViniGodoy]O join() é o comando que manda a thread atual esperar a thread que recebeu o join().

Se você não quer espera-la, então não dê o join(). Talvez você quisesse é isso aqui:

[code]//Dispara as duas.
thread thRecv(thRecvMethod, clntSock);
thread thOCR(thOcrMethod, clntSock);

//Espera as duas terminarem
thRecv.join();
thOCR.join(); [/code][/quote]

Isso mesmo,
funcionou perfeitamente.

a e parte do lock, eu resolvi com a biblioteca semaphore, mais eprcebi q a boost tbm tem um lock nela, eh melhor usar o do boost?

Valeu!!

Que tal a boost log?
http://boost-log.sourceforge.net/libs/log/doc/html/index.html

Na verdade, a boost é uma biblioteca excelente com muita coisa. Vale a pena estuda-la a fundo. E ela é feita pelo mesmo comitée que cria o C++. Tudo de altíssima qualidade, performance e praticamente oficial.

E o melhor, tem uma documentação simplesmente excelente.[/quote]

Eu dei uma olhada na parte de threads somente, irei verificar mais a fundo essa biblioteca.
Vo tentar implementar a parte de log.
Qualquer coisa eu grito aee…valeu mesmo cara.

A ordem geralmente é essa:

  1. Tem na STL?
  2. Tem na boost?
  3. Tem em outra biblioteca confiável?
  4. Posso implementar?
  5. Tem em alguma biblioteca desconhecida?

No seu caso (em que você quer esperar 2 threads terminarem), o correto em boost::thread é usar o “barrier” que é feito justamente para isso (você inicia N threads, e quer esperar por todas terminarem, ou pelo menos M delas terminarem, etc.) da forma mais eficiente que houver no seu sistema operacional. (No seu caso, você está esperando a thread 1 terminar e depois a 2, mas com barriers você poderia ter algo como esperar a 1 e a 2 terminarem = tanto faz quem terminar primeiro, a 2 ou a 1, que você teria a condição correta.

Uma vantagem de usar a boost é que seu programa fica bem mais fácil de portar para o Windows (ou vice-versa, portar um programa Windows para o Unix/Linux). Onde estou trabalhando há um projeto de portar um serviço do Windows para o Linux, que será possível porque ele foi escrito usando principalmente as bibliotecas do Boost.

[quote=ViniGodoy]A ordem geralmente é essa:

  1. Tem na STL?
  2. Tem na boost?
  3. Tem em outra biblioteca confiável?
  4. Posso implementar?
  5. Tem em alguma biblioteca desconhecida?[/quote]

Entendi.

[quote]
No seu caso (em que você quer esperar 2 threads terminarem), o correto em boost::thread é usar o “barrier” que é feito justamente para isso (você inicia N threads, e quer esperar por todas terminarem, ou pelo menos M delas terminarem, etc.) da forma mais eficiente que houver no seu sistema operacional. (No seu caso, você está esperando a thread 1 terminar e depois a 2, mas com barriers você poderia ter algo como esperar a 1 e a 2 terminarem = tanto faz quem terminar primeiro, a 2 ou a 1, que você teria a condição correta.

Uma vantagem de usar a boost é que seu programa fica bem mais fácil de portar para o Windows (ou vice-versa, portar um programa Windows para o Unix/Linux). Onde estou trabalhando há um projeto de portar um serviço do Windows para o Linux, que será possível porque ele foi escrito usando principalmente as bibliotecas do Boost. [/quote]

Na verdade eu inicio ela e soh finalizo no caso de alguma exception, pois meu caso de thread eh pra uso de multiplas conexoes de socket, esse projeto em C++ eh um socker server, entao eu nao preciso esperar terminar entendeu.

O Boost tem um negócio pronto para múltiplas conexões de socket, chamado “boost::asio”. Você pode usá-lo com conexões assíncronas, economizando threads se você quiser ter muitas conexões simultâneas ao mesmo tempo.

hunn, esse boost eh demais cara…tem muita coisa…
vou verificar sobre o socket.

o Vini, tem como vc me dizer como eu posso inicializar o log, pois eu nao consegui ainda =//