Estou tentando entender o que é um loop de eventos. Geralmente, a explicação é que, em um loop de eventos, você faz algo até ser notificado de que um evento ocorreu. Você lida com o evento e continua fazendo o que estava fazendo antes.
Para mapear a definição acima com um exemplo. Eu tenho um servidor que 'escuta' em um loop de eventos e, quando uma conexão de soquete é detectada, os dados são lidos e exibidos, após o que o servidor continua / começa a escutar como antes.
No entanto, esse evento acontecendo e nós sermos notificados 'exatamente assim' são muito para eu lidar. Você pode dizer: "Não é 'exatamente assim' que você precisa registrar um ouvinte de evento". Mas o que é um ouvinte de eventos, mas uma função que, por algum motivo, não está retornando. Está em seu próprio loop, aguardando para ser notificado quando um evento acontece? O ouvinte de evento também deve registrar um ouvinte de evento? Onde isso termina?
Eventos são uma boa abstração para se trabalhar, mas apenas uma abstração. Acredito que, no final, as pesquisas são inevitáveis. Talvez não estejamos fazendo isso em nosso código, mas os níveis mais baixos (a implementação da linguagem de programação ou o SO) estão fazendo isso por nós.
Basicamente, resume-se ao pseudo-código a seguir, que está sendo executado em algum lugar baixo o suficiente para não resultar em espera ocupada:
while(True):
do stuff
check if event has happened (poll)
do other stuff
Esta é a minha compreensão de toda a ideia e gostaria de saber se isso está correto. Estou aberto a aceitar que toda a idéia está fundamentalmente errada, caso em que eu gostaria da explicação correta.
fonte
EventSource
fazendo se não estiver pesquisando a entrada do teclado?Respostas:
A maioria dos loops de eventos será suspensa se não houver eventos prontos, o que significa que o sistema operacional não dará à tarefa nenhum tempo de execução até que um evento aconteça.
Digamos que o evento seja uma tecla pressionada. Você pode perguntar se há um loop em algum lugar do sistema operacional, procurando por pressionamentos de tecla. A resposta é não. As teclas pressionadas geram uma interrupção , que é tratada de forma assíncrona pelo hardware. Da mesma forma para temporizadores, movimentos do mouse, chegada de um pacote etc.
De fato, para a maioria dos sistemas operacionais, a pesquisa de eventos é a abstração. O hardware e o sistema operacional lidam com eventos de forma assíncrona e os colocam em uma fila que pode ser pesquisada por aplicativos. Você realmente vê a sondagem verdadeira no nível do hardware nos sistemas incorporados e nem sempre existe.
fonte
Most event loops will block
. Como isso se encaixa no "paradigma do loop de eventos, em oposição ao uso de threads, usa chamadas assíncronas sem bloqueio"?Penso em um ouvinte de evento não como uma função executando seu próprio loop, mas como uma corrida de revezamento com o primeiro corredor esperando a arma de partida. Uma razão significativa para usar eventos em vez de pesquisar é que eles são mais eficientes nos ciclos da CPU. Por quê? Olhe para ele a partir do hardware (em vez do código fonte para baixo).
Considere um servidor da Web. Quando o servidor chama
listen()
e bloqueia, seu código está assumindo seu lugar como corredor de retransmissão. Quando o primeiro pacote de uma nova conexão chega, a placa de rede inicia a corrida interrompendo o sistema operacional. O sistema operacional executa uma rotina de serviço de interrupção (ISR) que agarra o pacote. O ISR passa o bastão para uma rotina de nível superior que estabelece a conexão. Quando a conexão está ativa, essa rotina passa o bastão paralisten()
, que passa o bastão para o seu código. Nesse ponto, você pode fazer o que quiser com a conexão. Pelo que sabemos, entre as corridas, cada corredor de revezamento poderia ir ao pub. Uma força da abstração do evento é que seu código não precisa saber ou se importar.Alguns sistemas operacionais incluem código de manipulação de eventos que executa sua parte da corrida, retira o bastão e volta ao ponto inicial para aguardar o início da próxima corrida. Nesse sentido, a manipulação de eventos é otimizada em vários loops simultâneos. No entanto, sempre há um gatilho externo que inicia o processo. O ouvinte de eventos não é uma função que não está retornando, mas uma função que aguarda esse gatilho externo antes de ser executado. Ao invés de:
Eu penso nisso como:
e entre a
signal
e a próxima vez que o manipulador for executado, conceitualmente não há código em execução ou em loop.fonte
forever: { select(); do stuff; }
, você estará entrando novamente na corrida todas as vezes através do loop. Se você faz isso repetidamente a partir de um único thread ou em paralelo em threads ou processadores separados, penso em cada evento como sua própria raça. Por exemplo, um navegador da Web é um programa multithread com vários loops de eventos em threads separados, pelo menos um para a interface do usuário e um para cada página que está baixando. A pergunta que faço ao codificar é "como posso processar eventos com rapidez suficiente?" Às vezes a resposta é um loop, às vezes threads, geralmente uma combinação.Não. Não é "pesquisa otimizada". Um loop de eventos usa E / S orientada a interrupção em vez de pesquisa.
Enquanto, Até, Para etc., os loops são loops de polling.
"Polling" é o processo de verificar repetidamente algo. Como o código do loop é executado continuamente e por ser um loop pequeno e "apertado", há pouco tempo para o processador alternar tarefas e fazer qualquer outra coisa. Quase todos os "travamentos", "congelamentos", "travamentos" ou o que você quiser chamar quando o computador não responde, são a manifestação do código preso em um loop de pesquisa não intencional. A instrumentação mostrará 100% de uso da CPU.
Os loops de eventos controlados por interrupções são muito mais eficientes do que os loops de polling. A pesquisa é um uso extremamente inútil dos ciclos da CPU, portanto, são feitos todos os esforços para eliminá-lo ou minimizá-lo.
No entanto, para otimizar a qualidade do código, a maioria dos idiomas tenta usar o paradigma do loop de polling o mais próximo possível dos comandos de entrega de eventos, pois eles servem a propósitos funcionalmente semelhantes em um programa. Assim, com a pesquisa sendo a maneira mais familiar de esperar por um pressionamento de tecla ou algo assim, é fácil para os inexperientes usá-la e acabar com um programa que pode funcionar bem por si só, mas nada funciona enquanto está sendo executado. Ele "assumiu" a máquina.
Conforme explicado em outras respostas, na entrega de eventos acionada por interrupção, essencialmente um "sinalizador" é definido na CPU e o processo é "suspenso" (não é permitido executar) até que esse sinalizador seja alterado por algum outro processo (como o teclado driver mudando quando o usuário pressiona uma tecla). Se o sinalizador for uma condição real de hardware, como uma linha sendo "puxada para o alto", será chamada de "interrupção" ou "interrupção de hardware". No entanto, a maioria é implementada como apenas um endereço de memória na CPU ou na memória principal (RAM) e é chamada de "semáforos".
Os semáforos podem ser alterados sob controle de software e, portanto, podem fornecer um mecanismo de sinalização muito rápido e simples entre os processos de software.
Interrupções, no entanto, só podem ser alteradas por hardware. O uso mais onipresente de interrupções é o acionado em intervalos regulares pelo chip de relógio interno. Um dos inúmeros tipos de ações de software ativadas por interrupções do relógio é a alteração de semáforos.
Eu deixei muito de fora, mas tive que parar em algum lugar. Por favor, pergunte se você precisar de mais detalhes.
fonte
Normalmente, a resposta é hardware, o sistema operacional e os threads de plano de fundo que você não controla conspiram para torná-lo fácil. A placa de rede recebe alguns dados e gera uma interrupção para informar a CPU. O manipulador de interrupções do sistema operacional lida com isso. Em seguida, um encadeamento em segundo plano que você não controla (que foi criado ao se registrar no evento e está em suspensão desde que você se registrou no evento) é acordado pelo sistema operacional como parte do tratamento do evento e executa seu manipulador de eventos.
fonte
Vou contra todas as outras respostas que vejo até agora e digo "sim" . Eu acho que as outras respostas estão complicando demais as coisas. Do ponto de vista conceitual, todos os loops de eventos são essencialmente:
Se você estiver tentando entender os loops de eventos pela primeira vez, pensar neles como um loop simples não fará mal. Alguma estrutura subjacente está aguardando o sistema operacional entregar um evento, depois o encaminha para um ou mais manipuladores, aguarda o próximo evento e assim por diante. Isso é realmente tudo o que existe, da perspectiva do software aplicativo.
fonte
Nem todos os gatilhos de eventos são manipulados em loops. A maneira como costumo escrever meus próprios mecanismos de eventos seria assim:
Observe que, embora o Memo 1 esteja em um loop, o loop é para notificar cada ouvinte. O gatilho de evento em si não está necessariamente em um loop.
Em teoria, os principais eventos no nível do sistema operacional podem usar a mesma técnica (embora eu ache que eles costumam fazer pesquisas? Estou apenas especulando aqui), desde que o sistema operacional exponha algum tipo de
registerListener
API.fonte