Nosso próximo programa de exemplo utiliza o provedor profile do DTrace para implementar um contador simples baseado em hora. O provedor de perfil pode criar novos testes com base nas descrições encontradas no programa em D. Se você criar um teste chamado profile:::tick-nsec para algum inteiro n, o provedor de perfil criará um teste que dispare a cada n segundos. Digite o seguinte código-fonte e salve-o em um arquivo chamado counter.d:
/* * Count off and report the number of seconds elapsed */ dtrace:::BEGIN { i = 0; } profile:::tick-1sec { i = i + 1; trace(i); } dtrace:::END { trace(i); }
Quando executado, o programa conta o número de segundos decorridos até que você pressione Control-C e depois imprime o total no final:
# dtrace -s counter.d dtrace: script 'counter.d' matched 3 probes CPU ID FUNCTION:NAME 0 25499 :tick-1sec 1 0 25499 :tick-1sec 2 0 25499 :tick-1sec 3 0 25499 :tick-1sec 4 0 25499 :tick-1sec 5 0 25499 :tick-1sec 6 ^C 0 2 :END 6 # |
As primeiras três linhas do programa são um comentário para explicar o que o programa faz. Similar às linguagens de programação C, C++ e Java, o compilador de D ignora os caracteres entre os símbolos /* e */. Os comentários podem ser usados em qualquer lugar de um programa em D, incluindo dentro e fora das cláusulas do teste.
A cláusula do teste BEGIN define uma nova variável denominada i e atribui a ela o valor inteiro zero usando a instrução:
i = 0;
Ao contrário das linguagens de programação C, C++ e Java, as variáveis de D podem ser criadas simplesmente usando-as em uma instrução do programa; declarações explícitas de variável não são necessárias. Quando uma variável é usada pela primeira vez em um programa, o tipo da variável é definido com base no tipo da sua primeira atribuição. Cada variável possui somente um tipo durante a duração do programa, sendo assim, as referências subseqüentes devem estar de acordo com o mesmo tipo da atribuição inicial. Em counter.d, a primeira atribuição da variável i é uma constante de inteiro zero, sendo assim, seu tipo é definido como int. D fornece os mesmos tipos básicos de dados de inteiro que C, incluindo:
char |
Caractere ou inteiro de byte único |
int |
Inteiro padrão |
short |
Inteiro curto |
long |
Inteiro longo |
long long |
Inteiro longo estendido |
Os tamanhos destes tipos dependem do modelo de dados do kernel do sistema operacional, descrito no Capítulo 2Tipos, operadores e expressões. D também fornece nomes amigáveis internos para tipos de inteiros atribuídos e não atribuídos de vários tamanhos fixos, assim como milhares de outros tipos que são definidos pelo sistema operacional.
A parte central de counter.d é a cláusula do teste que incrementa o contador i:
profile:::tick-1sec { i = i + 1; trace(i); }
Esta cláusula nomeia o teste profile:::tick-1sec, que informa ao provedor profile para criar um novo teste que é disparado uma vez por segundo em um processador disponível. A cláusula contém duas instruções, a primeira atribuindo i como o valor anterior mais um e a segunda rastreando o novo valor de i. Todos os operadores aritméticos usuais de C estão disponíveis em D. A lista completa pode ser encontrada no Capítulo 2Tipos, operadores e expressões. Além disso, como em C, o operador ++ pode ser usado como abreviação para incrementar a variável correspondente em um. A função trace() toma qualquer expressão de D como argumento, assim, você poderia escrever counter.d de forma mais concisa, como a seguir:
profile:::tick-1sec { trace(++i); }
Se você desejar controlar explicitamente o tipo da variável i, poderá colocar o tipo desejado entre parênteses quando atribuí-lo para converter o inteiro zero em um tipo específico. Por exemplo, caso desejasse determinar o tamanho máximo de um char em D, você poderia alterar a cláusula BEGIN da seguinte maneira:
dtrace:::BEGIN { i = (char)0; }
Após executar counter.d por um tempo, você verá o valor tracejado aumentar e depois voltar para zero. Se você não tiver paciência para esperar o valor voltar para zero, tente alterar o nome do teste profile para profile:::tick-100msec para fazer um contador que aumente a cada 100 milissegundos ou 10 vezes por segundo.