Terminology
event: A type of thing that can happen.
event firing: A specific occurrence of an event; an event happening.
event listener: Something that looks out for event firings.
event handler: Something that occurs when an event listener detects an event firing.
event subscriber: A response that the event handler's supposed to call.
These definitions don't depend on implementation, so they can be implemented different ways.
Some of these terms are commonly mistaken for synonyms since there's often not a need for users to distinguish between them.
Common scenarios
Programming-logic events.
The event is when some method gets called.
An event firing is a particular call to that method.
The event listener is a hook in the event method that's called on each event firing that calls the event handler.
The event handler calls a collection of event subscribers.
The event subscriber(s) perform whatever action(s) the system means to happen in response to the event's occurrence.
External events.
The event is an external happening that can be inferred from observables.
An event firing is when that external happening can be recognized as having occurred.
The event listener somehow detects event firings, often by polling the observable(s), then it calls the event handler upon detecting an event firing.
The event handler calls a collection of event subscribers.
The event subscriber(s) perform whatever action(s) the system means to happen in response to the event's occurrence.
Polling vs. inserting hooks into the event's firing mechanism
The point made by others is that polling often isn't necessary. This is because event listeners can be implemented by having event firings automatically call the event handler, which is frequently the most efficient way to implement things when the events are system-level occurrences.
By analogy, you don't need to check your mail box for the mail every day if the postal worker knocks on your door and hands the mail directly to you.
However, event listeners can also work by polling. Polling doesn't necessarily need to be checking a specific value or other observable; it can be more complex. But, overall, the point of polling is to infer when some event has occurred such that it can be responded to.
By analogy, you have to check your mail box every day when the postal worker just drops mail in it. You wouldn't have to do this polling work if you could instruct the postal worker to knock on your door, but that's often not a possibility.
Chaining event logic
In many programming languages, you can write an event that's just called when a key on the keyboard is pressed or at a certain time. Though these are external events, you don't need to poll for them. Why?
It's because the operating system is polling for you. For example, Windows checks for stuff like keyboard state changes, and if it detects one, it'll call event subscribers. So, when you subscribe to a keyboard press event, you're actually subscribing to an event that is itself a subscriber to an event that polls.
By analogy, say that you're living an apartment complex and a postal worker drops mail off into a communal mail receipt area. Then, an operating-system-like worker can check for that mail for everyone, delivering mail to the apartments of those who received something. This spares everyone else the trouble of having to poll the mail-receipt area.
My intuition would assume that the event listener constantly checks if the event has been fired, meaning, in my scenario, it would be no different than checking every frame if the event has been fired.
Based on the discussion in class, it seems that event listener works in a different way.
How does an event listener work?
As you've suspected, an event can work through polling. And if an event is somehow related to external happenings, e.g. a keyboard key getting pressed, then polling does have to happen at some point.
It's just also true that events don't necessarily need to involve polling. For example, if the event is when a button gets pressed, then that button's event listener is a method that the GUI framework might call when it determines that a mouse-click hits the button. In this case, polling still had to happen for the mouse click to be detected, but the mouse-listener is a more passive element connected to the primitive polling mechanism through event-chaining.
Update: On low-level hardware polling
It turns out that USB devices and other modern communication protocols have a rather fascinating networking-like set of protocols for interactions, enabling I/O devices including keyboards and mice to engage in ad hoc topologies.
Interestingly, "interrupts" are fairly imperative, synchronous things, so they don't handle ad hoc networking topologies. To fix this, "interrupts" have been generalized into asynchronous high-priority packets called "interrupt transactions" (in the context of USB) or "message-signaled interrupts" (in the context of PCI). This protocol is described in a USB specification:
-"Figure 8-31. Bulk/Control/Interrupt OUT Transaction Host State Machine" in "Universal Serial Bus Specification, Revision 2.0", printed-page-222; PDF-page-250 (2000-04-27)
The gist seems to be that I/O devices and communication components (like USB hubs) basically act like network devices. So, they send messages, which requires polling their ports and such. This alleviates the need for dedicated hardware lines.
Operating systems like Windows seem to handle the polling process itself, e.g. as described in the MSDN documentation for the USB_ENDPOINT_DESCRIPTOR
's which describes how to control how often Windows polls a USB host controller for interrupt/isochronous messages:
The bInterval
value contains the polling interval for interrupt and isochronous endpoints. For other types of endpoint, this value should be ignored. This value reflects the device's configuration in firmware. Drivers cannot change it.
The polling interval, together with the speed of the device and the type of host controller, determine the frequency with which the driver should initiate an interrupt or an isochronous transfer. The value in bInterval
does not represent a fixed amount of time. It is a relative value, and the actual polling frequency will also depend on whether the device and the USB host controller operate at low, full or high speed.
-"USB_ENDPOINT_DESCRIPTOR structure", Hardware Dev Center, Microsoft
Newer monitor connection protocols like DisplayPort seem to do the same:
Multi-Stream Transport (MST)
-Slide #14 from "DisplayPortTM Ver.1.2 Overview" (2010-12-06)
This abstraction allows for some neat features, like running 3 monitors from one connection:
DisplayPort Multi-Stream Transport also allows connecting three or more devices together but in the opposite, less "consumer"-oriented configuration: simultaneously driving multiple displays from a single output port.
-"DisplayPort", Wikipedia
Conceptually, the point to take away from this is that polling mechanisms allow for more generalized serial communications, which is awesome when you want more general functionality. So, the hardware and OS do a lot of polling for the logical system. Then, consumers that subscribe to events can enjoy those details being handled for them by the lower-level system, without having to write their own polling/message-passing protocols.
Ultimately, events like key-presses seem to go through a rather interesting series of events before getting to the software-level's imperative event-firing mechanism.