Rodrigo Strauss :: Blog
|
|
|
Talvez você ache interessante ver a lista com todos os posts ou minha lista com os melhores posts.
WebCast sobre DLR no .NET Framework 4.0
Amanhã 12:00hs estarei apresentando o "MSDN Webcast: Trabalhando com o DLR no .NET Framework 4. Falarei da versão nova da DLR (Dynamic Language Runtime) que fará parte do .NET 4.0, de IronPython e sobre como integrar scripts Python no C#.
Parece que ainda consta o nome do Alfred Myers como apresentador, mas eles devem arrumar isso logo
Em 18/11/2009 17:04 - Comentários (1)
Meu Twitter
Também é sobre programação e afins (com poucos avisos úteis tipo "acabou a luz aqui, catso, perdi meus fontes #apagão"). Não espere saber se eu acordei de bom humor ou se o filme xpto é bom ou não.
http://www.twitter.com/rodrigostrauss
Em 18/11/2009 09:55 - Comentários (0)
Lendo e medindo o tempo em C e C++
Existem vários motivos para um programa consultar o "horário da máquina". Os mais comuns são registrar a data e hora de um acontecimento ou ação do usuário (data de acesso à um arquivo, por exemplo) ou medir o intervalo entre dois momentos para saber o tempo que algo levou.
Em C e C++ existem diversas maneiras de ler uma representação numérica de um determinado instante no tempo, e cada uma tem seu uso e característica. Essa salada de funções e APIs existem porque usando C e/ou C++ você tem acesso à todas as camadas de abstração (ou não-abstração), desde o relógio da placa mãe, passando pela BIOS, pelas APIs do sistema operacional até as funções da runtime do C ou do boost::datetime. Nessa série de posts vamos ver as características de cada forma de ler o "horário da máquina".
Toda representação numérica de um instante no tempo é dada pela diferença entre o instante da medição e um instante tido como referência. Quando usamos uma data e hora no nosso calendário gregoriano, tomamos como referência a "data tradicional da encarnação de Jesus Cristo". Isso é uma referência. 26 de maio de 1980 é tradução de (instance referência) + (1980 anos) + (5 meses) + (26 dias). Passando essa data para qualquer pessoa/programa que use a mesma refererência, ela consigirá saber de que instante no tempo você está falando. É importante saber esse conceito porque em programação a referência muitas vezes é diferente da referência do calendário gregoriano (por motivos técnicos e não religiosos. Sem teorias da conspiracão, pelamordedeus).
Quando usamos uma data e hora "normal" (ou seja, do calendário), ainda temos outra variável na verificação do horário: o fuso e o horário de verão. O horário de Brasília (fuso de São Paulo, onde eu moro) é de -3 horas em relação ao horário GMT, que é tido como a referência mundial para os fusos (GMT é Greenwich Mean Time, horário de Greenwich na Inglaterra). O horário de verão não muda o fuso do país, mas adianta o horário em uma hora. Na prática, é como se São Paulo virasse GMT-2. O fuso é uma informação controlada pelo SO, e mudar o fuso pode causar mais problemas ainda. Os SOs tratam o horário de verão explicitamente. Quem cuida de sistemas de produção onde a data e hora é algo importante sabe o inferno que é quando começa ou quando termina o horário de verão.
Saindo da história e voltando para a programação, existem alguns fatores importantes para escolher qual sistema de medição usar. Um fator importante é se o instante referência é fixo ou não (calendário gregoriano x quantidade de segundos desde que a máquina foi ligada). O outro é a precisão da medição, geralmente em segundos ou menos. Se você precisa medir o tempo que leva para concatenar uma string, medir em segundos não vai adiantar nada (isso geralmente leva nanosegundos).
Resumindo o que precisamos saber para escolher que função ou API de tempo usar:
- Referência: se é uma referência fixa (início do calendário gregoriano) ou uma referência relativa (hora de início da máquina ou de inicialização do sistema operacional)
- Precisão do retorno. Não adiantar usar uma função que retorna a hora com precisão de segundos se vou fazer um cálculo de período que leva microsegundos.
- Precisão de leitura. Existem funções que retornam em milisegundos, mas a precisão é menor que isso. A função GetTickCount da API Win32 retorna a quantidade de millisegundos desde o início do sistema, mas sempre em intervalos maiores do que 15ms. Ou seja, ele não consegue medir algo que leva menos do que 15ms
- Performance. Algumas funções de leitura de hora são mais rápidas que outras. Se vocês faz isso dentro de um loop, isso faz diferença
Por exemplo, uma função com precisão baixa pode ser usada para medir o tempo de abandono do meu blog, já que faz muuuito tempo que eu não atualizo isso aqui :-)
O próximo post terá código. Não se preocupem, estou mais ansioso por isso do que vocês.
Em 17/11/2009 17:32 - Comentários (4)
Win32: sincronização parte 2
Preparando esse post eu percebi que o post de sincronização parte 1 não explica nada sobre sincronização, só apresenta o problema que a sincronização resolve. Estou parecendo aqueles vendedores de empresas de software que gastam mais tempo tentando provar que você tem um problema do que realmente mostrando a solução. Agora chegou a hora de mostrar a solução. :-)
Como vimos na primeira parte, o maior problema em programação multithread é o compartilhamento de dados entre as threads. Existem duas solução para isso. A primeira e mais usada é sincronizar o acesso aos dados, de forma que somente uma thread por vez manipule os dados em questão. Ou seja, a solução envolve "eliminar" (notou as aspas?) o multithread da parte que ele atrapalha. A segunda e pouco usada opção é eliminar o compartilhamento dos dados, usando filas, controle restrito de ownership e trabalhando com cópias do dados. Esse é o enfoque usado pelo Erlang, uma nova linguagem de programação.
A forma mais básica para sincronização em vários SOs é o critical section. Esse recurso permite definir um trecho de código que é executado por várias threads, mas que precisa ser sincronizado entre elas. Sincronizado == somente uma thread pode executar esse trecho de código por vez.
Revisando a nossa classe de lista ligada, vamos ver quais são os dados da classe:
template<typename T> class LinkedList { struct NODE { NODE* previous; NODE* next; T data; }; NODE rootNode_; unsigned int count_; ...
A princípio parece que precisamos sincronizar o rootNode_ e o count_. Apesar disso estar correto, não é simples assim, não esqueça que todos os nós apontados pelo rootNode_ são dados controlados pela classe, que também precisam ser sincronizados.
Olhando o fonte dessa classe, todos os métodos manipulam ou lêem essas duas variáveis. A forma mais fácil e óbvia seria cercar com um critical section o corpo de todas as funções da classe.
Em Win32, um critical section é definido pelo objeto (surpresa!) CRITICAL_SECTION. Esse objeto deve ser inicializado e terminado, dessa forma:
CRITICAL_SECTION cs; // // adivinha? // InitializeCriticalSection(&cs); // // aqui entramos no critical section. Quando uma thread está "dentro" de // um critical section, se alguma outra thread tentar entrar ficará // travada dentro da funcão EnterCriticalSection até que a primeira // thread chame LeaveCriticalSection. Isso garante que somente uma thread // executará esse trecho de código em um dado momento. // EnterCriticalSection(&cs); // // Saímos do critical section. Isso faz com que a próxima thread que estiver // esperando no ponto do EnterCriticalSection seja liberada. Note que somente // uma thread é liberada por vez. Caso mais de uma thread esteja esperando, elas // são liberadas na ordem que chegaram "na portinha" do critical section // LeaveCriticalSection(&cs); // // análogo ao CloseHandle // DeleteCriticalSection(&cs);
Resumindo: o Critical Section cria um "gargalo", onde só passa uma thread de cada vez. Ah, existe uma coisa interessante a ser acrescentada à explicação do post sobre threads: as threads permitem que um processo execute várias linhas de execução ao mesmo tempo, mas essas linhas de execução podem rodar o mesmo código, que está no mesmo lugar na memória. Ou seja, elas compartilham dados e código executável.
No próximo post iremos para o exemplo prático.
Em 30/01/2009 10:17 - Comentários (8)
Ferramentas de apoio Win32: pskill
O pskill é mais um ferramenta Sysinternals sem a qual a vida fica muito difícil. A única coisa que ele faz - e bem feito - é matar um processo. Parece simples, mas quando você precisa matar 7 processos toda vez que seu servidor dá pau, uma bat cheia de chamadas ao pskill pode salvar a sua vida.
Alguns usos:
- Ela aceita tanto o nome do processo quanto o PID: você pode chamar pskill notepad.exe ou pskill 4576.
- Quando você usa o nome, ele mata TODOS os processos com o mesmo nome: Ou seja, um pskill notepad.exe vai matar TODAS as instância do notepad. Se você quer matar uma instância específica, use o PID. Se precisar saber o PID do processo em command line, use o pslist, ferramenta que veremos em mais detalhes depois.
- Matar um processo e todos criados por ele: pskill -t meu-servico.exe. Mata o processo pai e toda sua família.
- Funciona remotamente: você pode chamar pskill \\outra-maquina notepad.exe ou pskill \\outra-maquina 4576. Como sempre, você precisa ter permissão para isso na máquina remota
Informação muito importante: pskill \\maquina-remota winlogon.exe causa um BugCheck (tela azul) instantâneamente na máquina remota. Use com moderação.
Em 31/10/2008 13:55 - Comentários (4)
Posts anteriores >>





