Introdução à Threads para
Windows na linguagem C
Modularizando Threads
em uma struct C
Luiz Carlos d´Oleron
[email protected]
Introdução
• Nesta aula aprenderemos:
− Como usar Threads na Linguagem C;
− Como criar um conjunto de artefatos
que ocultem a complexidade do
Sistema Operacional para
programação multi-thread em C.
Motivação
• Gerenciamento de Threads e Processos é algo
intrissecamente ligado ao Sistema Operacional
• Programas que utilizam técnicas Multi-Thread
podem ter código nativo do SO espalhado e
misturado com outros tipos de código (negócio,
persistência, etc…)
• API de SO´s não são muito legíveis
Exemplo
• Excemplo1.c
Modularizando o código
• Nas linguagens Orientadas a Objetos, tal como
Java e C++, existem Classes que encapsulam as
responsabilidades do Thread e do Sistema
Operacional
• Essas Classes permitem Reuso, ao passo que
podem ser Estendidas
• Em C, as coisas são um pouco mais difíceis,
pois não possuímos algumas ferramentas
valiosas, como Herança e Polimorfismo!
Classe Thread de Java
Dando uma olhada na classe Thread de
Java:
http://java.sun.com/j2se/1.5.0/docs/api
/java/lang/Thread.html
Modularizando o código
• A idéia principal é criar uma struct em C que,
junto com algumas funções, se pareça um
pouco com a classe Thread de java
• Dessa forma, poderemos reutilizar a struct em
nossas aplicações, ocultando nela os detalhes
do Sistema Operacional
• Como?
A struct Thread
typedef struct thread{
//um identificador para o Thread
char* nome;
//a funcao que deverá ser executada pelo Thread
EnderecoFuncao* run;
//um manipulador para o Thread
//Utilizado, por exemplo, para saber se o Thread
//ainda está vivo
HANDLE handle;
} Thread;
Funções para a struct
//Construtor do Thread
Thread* newThread(char* nome, EnderecoFuncao*
funcaoThread);
//funcao start inicia a execução do Thread em
//paralelo com a execução atual
void start(Thread* t, void* parametros);
Funções para a struct
//funcao faz o Thread atual dormir por no
//mínimo tempoEmMiliSegundos
void sleep(int tempoEmMiliSegundos);
//Faz a Thread atual aguardar pela conclusão do
// Thread t
void join(Thread* t);
//Faz o Thread atual abdicar pela sua parcela atual
// de tempo na CPU
void yield();
Ops!!!
• Mais na classe Thread de java, run é um
método, e não um atributo!
Explicando
• Em C, não há Herança. Para solucionar
isso, usaremos algo que não é possível
ser feito em java
• Definimos um Ponteiro para uma Função
• Assim nossa Thread em C poderá ser
extensível, mesmo sem herança
Usando a struct Thread
void funcaoSoma (void* param){
int i = 0;
char* nome = (char*) param;
for(i = 0;i<10;i++){
printf("%s : %d \n",nome,i);
yield();
}
}
void funcaoSub (void* param){
int i = 0;
char* nome = (char*) param;
for(i = 9;i>=0;i--){
printf("%s : %d \n",nome,i);
yield();
}
}
Usando a struct Thread
int main(int argc, char *argv[])
{
Thread* t1 =
newThread(“ThreadSoma", funcaoSoma );
Thread* t2 =
newThread(“ThreadSub", funcaoSub );
start(t1, t1->nome);
start(t2, t2->nome);
join(t1);//Aguarda t1
join(t2);//Aguarda t2
system("PAUSE");
}
Exemplo com struct Thread
• O mesmo exemplo do slide 4 pode ser
encontrado no Exemplo2.c, dessa vez,
usando a struct Thread
A implementação
• A implementação das funções de
Thread.h podem ser encontradas na
classe Thread.c
• Lá estão isolados os detalhes do acesso
ao Sistema Operacional
A implementação
• Foram utilizadas as seguintes funções da
API do Windows:
− CreateThread
− GetExitCodeThread
− Sleep
A função CreateThread
• Cria uma Thread para executar em paralelo no processo que a chamou;
• http://msdn.microsoft.com/library/default.asp?url=/library/enus/dllproc/base/createthread.asp
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
A função CreateThread
• Exemplo de chamada de CreateThread:
void funcao(void* p){...}
...
char* parametros = “teste”;
HANDLE handle =
CreateThread(NULL,0, funcao,
parametros,0,NULL);
A função CreateThread
• Para simplificar, daremos ênfase apenas
aos parâmetros:
− lpStartAddress – a função que será
executada pelo Thread
− lpParameter – Parâmetro que será
passado para a função do Thread
A função GetExitCodeThread
• Retorna o código de saída da Thread, usada para descobrir se o
Thread já acabou de executar sua função;
• http://msdn.microsoft.com/library/default.asp?url=/library/enus/dllproc/base/getexitcodethread.asp
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);
A função GetExitCodeThread
• Exemplo de uso de GetExitCodeThread:
HANDLE handle = …;
LPDWORD exitCode;
GetExitCodeThread(handle,&exitCode);
if(exitCode==STILL_ACTIVE){
printf(“Thread ainda Funcionando”);
}else{
printf(“Thread Morto”);
}
A função GetExitCodeThread
• hThread– O “manipulador” da Thread.
Componente que permite obter informações
do ciclo de vida da Thread
• lpExitCode– Parâmetro que contém o código
de saída do Thread. Se o Thread ainda estiver
executando, lpExitCode será igual a
STILL_ACTIVE
A função Sleep
• Similar ao método estático sleep da classe
Java, a função Sleep fará a Thread atual
adormecer por, no mínimo, o tempo
especificado;
• http://msdn.microsoft.com/library/default.asp?url=/l
ibrary/en-us/dllproc/base/sleep.asp
VOID Sleep(
DWORD dwMilliseconds
);
A função Sleep
• Passar o valor zero para Sleep faz com que o
Thread atual abdique de seu tempo na CPU,
deixando para o SO decidir por um novo
Thread a executar. Se nenhum outro Thread
estiver disponível, a função retorna
automaticamente, fazendo com que o Thread
inicial volte à exeução;
• Usamos Sleep(0) para simular a função void
yield().
A função Sleep
• Exemplo de uso de Sleep
int tempo = 10000;
printf(“Fazendo o programa parar por
no mínimo %d milisegundos\n”,
tempo);
Sleep(tempo);
printf(“O programa parou por no
mínimo %d milisegundos\n”, tempo);
Resumo
• Código que usar Thread em C irá
depender do Sistema Operacional
• Podemos usar structs e funções para
modularizar e abstrair o código
dependente do Sistema Operacional
• Assim o restante do código ficará mais
limpo e flexível
Mais informações
• Muita coisa sobre Threads não foram vistas
nessa aula
• O exemplo apresentado poderá ser estendido,
por exemplo, para contemplar sincronização e
prioridades
• Procure mais informações nas fontes:
− http://msdn.microsoft.com/library/default.asp?url
=/library/en-us/dllproc/base/multiple_threads.asp
− http://www.cin.ufpe.br/~adsl/cursos
Download

Threads para Windows com C