terça-feira, 7 de junho de 2011

Math - Cast , Software Livre, para amantes de Fórmulas.

Um programa simples, de interface eficiente e que cumpre á risca o que promete: Transcrever fórmulas matemáticas de maneira a tornar as mesmas compatíveis com qualquer editor de textos/imagem. Sua principal característica é trabalhar com linguagem XML, favorecendo a compatibilidade entre vários editores.A versão corrente do software pode ser obtida aqui.

A tela de boas vindas é auto-explicativa. Clique em "New Equation List" para iniciar um novo projeto, "Open Equation List" para abrir um arquivo etc... Esta versão contém um arquivo de ajuda vasto, permitindo a qualquer pessoa com o mínimo de conhecimento em expressões matemáticas operar o sistema. Para inserir uma fórmula nova, basta clicar no sinal de soma (1) e iniciar a fórmula na caixa de texto(2) que irá aparecer.
Para executar uma operação matemática, é só escrever na area de entrada(2) a fórmula propriamente dita e pressionar OK.
Para montar expressões mais complexas, devemos utilizar o caractere "‹" para iniciar cada bloco e fechar com o caractere "›".(Não confundir com os caracteres maior e menor! Estes caracteres delimitadores são únicos desta linguagem (XML) e podem ser obtidos através do atalho CONTROL+9 e CONTROL+0, respectivamente.)Para inserir um comentário antes ou depois das formulas, o mesmo deve estar entre "Aspas".
Por exemplo para montar a expressão :
Devemos utilizar a entrada :

 ‹a + b›╱2
Com a fórmula montada, podemos clicar no botão Copy (3) e copiar a fórmula para a área de transferência (clip-board). Feito isto, podemos utilizar desde um processador de textos (O Ms Word, por exemplo) até um processador de imagens (Corel Draw, por exemplo) para tratar das mesmas.O arquivo copiado é um bitmap, ou seja, uma imagem, sendo compatível com qualquer programa de edição.

Se você irá utilizar um processador de textos comum, para imprimir as fórmulas, talvez você note uma pequena distorção na imagem. Isso ocorre, porque no ato de exportar a imagem, o software simplesmente copia a tela do programa, mantendo a resolução do seu monitor. Para um melhor resultado, entre no menu
EDIT > SETTINGS e selecione a opção Enhanced Metafile 2. Assim como na ilustração.


Pronto.Você agora perceberá, com certeza, um ganho na qualidade da imagem exportada.
Para considerações finais, o software é completamente open-soure e freeware, ou seja, é passível de modificação pelo usuário, bem como de traduções para a nossa língua. Eu me candidatei á traduzir o programa para Português-BR e aceito ajuda de todos os interessados.


Enfim, aproveitando esta excelente ferramenta, eu também elaborei uma tabela de fórmulas para a matéria de probabilidade e estatística.(que por ora não terá custo algum). Sinta-se livre para baixar o arquivo aqui, e imprimir.

Aquele abraço, fui!

quinta-feira, 2 de junho de 2011

[OFF] semaphore.h e pthread.h no Dev C [Win32]

Primeiramente, se você veio aqui para dizer "-Pra quê tudo isto.... Pega qualquer distribuição  Linux e  compila o código...." e não entende que as pessoas podem querer utilizar o Ruimdows para fazer este tipo de coisa, eu vou te pedir um favor: Clique aqui. Para o restante, siga.
Segundamente, são dois motivos que me levaram a publicar este conteúdo que me rendeu horas de pesquisa pela web:

  1. Centralizar este tipo de informação, para que as pessoas que encontram problemas na implementação de código C em ambiente Windows.
  2. Ajudar meus nobres e ilustres colegas de graduação.
Explicações à parte, vamos ao que interessa.

Faça o download do pacote Pthreads (Posix Threads) aqui. Este pacote permite a você usar várias bibliotecas nativas do C padrão.Entre elas semaphore.h ,pthread.h e outras relativas à programação concorrente. Após baixar, instale o pacote, dando um duplo-clique no arquivo e seguindo as instruções, se houver.Após a instalação, no menu TOOLS > PACKAGE MANAGER ( FERRAMENTAS > PACKAGE MANAGER em português ) o pacote deve aparecer, como na ilustração abaixo:


Com o pacote instalado, precisamos informar ao programa de link edição do Dev-C que estamos usando uma biblioteca externa à padrão. Para fazer isto, vá até o menu TOOLS e em COMPILER OPTIONS marque a caixa Add theese commands to the linker command line insira o comando " -lpthreadGC2 "(Sem aspas) na caixa logo abaixo. Pressione OK.( Se a sua IDE estiver em Português, a sequência é : Ferramentas > Opções do Compilador >Marque a opção Adicionar estes comandos à linha de comando do linker > Na caixa abaixo insira "-lpthreadGC2" (Sem aspas)).


Feito isto você está apto á começar a usar as bibliotecas. No entanto, as funções para manipular os semáforos são um pouco diferentes das funções aprendidas durante a aula de Sistemas Operacionais.

Para Criar um semáforo, utilizamos o tipo de dado sem_t. Ex:

#include <semaphore.h>

sem_t meuSemaforo;

Para Inicializar um semáforo, utilizamos a função sem_init, que recebe como parâmetro uma referência(&) ao semáforo criado.Em seguida é passado o valor da variável pshared, que se for um numero positivo, permite que o semáforo seja compartilhado por outros processos.E finalmente o valor inicial do nosso semáforo.(No exemplo do consumidor/produtor, os semáforos eram inicializados com uma atribuição.Neste método, precisamos executar a função sem_init, á fim de inicializar a variável interna)Ex:

sem_init (&meuSemaforo,0,1); (semáforo binário, não compartilhado entre processos. È geralmente utilizado como o semaforo de Exclusão Mútua (mutex)).

sem_init (&meuSemaforo,0,10);(semáforo inteiro, não compartilhado entre processos. È geralmente utilizado como contador).

Obs : Como utilizaremos o modelo de threads concorrentes , não compartilhamos os semáforos com outros processos. Caso utlilizassemos o modelo de processos concorrentes, teriamos que setar a  propriedade pshared para 1)

Para utilizar a função P(s), descrita no conteúdo de sistemas operacionais, utilizamos a equivalente sem_wait, que recebe como parâmetro a referência(&) para o semáforo. Esta operação testa se o semáforo é maior que 0. Se for, ela decrementa o valor do semáforo e entra no código da Região Crítica.Ex:

sem_wait(&meuSemaforo);

Para utilizar a função V(s), descrita no conteúdo de sistemas operacionais, utilizamos a equivalente sem_post, que recebe como parâmetro a referência(&) para o semáforo. Esta operação quando executada, incrementa o valor do semáforo, e abre o sinal para que outros processos/threads executem a sua Região Crítica.Ex:

sem_post(&meuSemáforo);

Bom, com estas informações já daria para implementar o código do produtor/consumidor sem problemas.
Porém, ainda não implementamos programação multithread para poder testar nossos códigos. Para isto, utilize a biblioteca <pthread.h>.

O tipo de dado para se declarar uma thread é pthread_t. Ex:

#include <pthread.h>

pthread_t minhaThread;

Para criar e inicializar a thread, utilizamos a função pthread_create que contém 4 argumentos que, devido á sua complexidade, serão tratados individualmente. Ex:

pthread_create(&minhaThread, NULL, minhaFuncao , (void *) &meuArgumento);
  1. O primeiro argumento é uma  referência(&) à thread préviamente declarada.(&minhaThread)
  2. O segundo arrgumento é um ponteiro que define os atributos da thread. Para valores padrão, NULL deve ser passado (NULL)
  3. O terceiro argumento é a função que você irá passar para a thread que se criará e executará à partir de agora.Para o exemplo consumidor/produtor é de suma importancia que sua função retorne um ponteiro de void.(explicado melhor adiante)Neste parametro voce nao deve incluir nada além do nome da função (que ja deve estar declarada, né?) (minhaFuncao).
  4. O quarto parâmetro está relacionado aos parâmetros que estaremos passando para nossa função.Não irei muito além neste ponto, pois para entender este argumento você deve entender sobre troca de mensagens entre processos e isto é uma longa história(que veremos com o professor Botega mais adiante) Aqui passaremos uma referência(&) para um inteiro qualquer (que você também já declarou, né?) que servirá como identificador para nossa thread, junto com um casting(coerção) de tipo para ponteiro nulo ((void *) &meuArgumento)
Se você foi um bom menino e seguiu meus passos até aqui, você já possui uma função assim:

void * minhaFuncao (int * meuArgumento)
{
      blablablá.
          sem_wait(&meuSemaforo)
                   região crítica;
          sem_post(&meuSemáforo)
}

E também possui uma main() mais ou menos assim :

void main ()
{
       int meuArgumento1=1,meuArgumento2=2;
       sem_init(&meuSemaforo,0,1);
       pthread_t minhaThread1,minhaThread2;
       pthread_create(&minhaThread1, NULL, minhaFuncao , (void *) &meuArgumento1);
        pthread_create(&minhaThread2, NULL, minhaFuncao , (void *) &meuArgumento2);
}


Se voce entendeu meu raciocinio até aqui, conseguiu compilar tudo, porém quando executa o programa executa e fecha rapidamente, pensa comigo.
Se todo processo tem pelo menos uma unica thread, e esta thread principal termina sua execução, o processo acaba ,certo? Se um processo acaba, ele acaba com todas as coitadinhas que estavam lá em seu laço infinito trabalhando. Culpa de quem? Culpa do seu S.O. que nem faz ideia do que você estava fazendo dentro de seu processo. Ele não conhece suas threads.
 Quando nosso programa chega ao fim da main é isto que acontece. O processo todo termina e nossas threads vão pro saco. Para que isto não ocorra nós fazemos uma grande P.O.G. (Programação Orientada à Gambiarra, para os não íntimos). Simplesmente falamos para o nosso processo - Ei, essa sua thread principal (main()) já era, pegue uma de nossas threads para continuar com o programa.
E utilizando o seguinte comando, ele atende nosso pedido:

pthread_exit(NULL);


Sendo assim, sua main() deve estar parecida com isto:


void main ()
{
       int meuArgumento1=1,meuArgumento2=2;
       sem_init(&meuSemaforo,0,1);
       pthread_t minhaThread1,minhaThread2;
       pthread_create(&minhaThread1, NULL, minhaFuncao , (void *) &meuArgumento1);
       pthread_create(&minhaThread2, NULL, minhaFuncao , (void *) &meuArgumento2);

       pthread_exit(NULL);
}

Bom, felizmente é isto que posso fazer por vocês por hora, pois mais do que isto seria contribuir para a retirada do seu diploma de bacharelado. E a intenção não é esta, e sim promover o conhecimento mútuo, pois eu também poderei e vou, precisar de vocês adiante.
Também espero poder contar com vocês para a divulgação do blog, bem como a avaliação de vocês nesta página. Comentários serão bem-vindos e respondidos.

Um grande abraço