We added a 4th state, so we have "Canceling and Canceled". We are in canceling state if we previously were running, and will not transition to canceled till after the interrupt has been sent. So at the end if we are not running, or already canceled, we will sleep, waiting for the interrupt to occur so we can be sure we handle it before we let the thread complete.
This also fixes a condition where we returned true on a cancel after a task has already been canceled
This also changes ConcurrentLinkedQueue to implement the Queue interface, and just throw exceptions for operations which are not currently implemented.
Previously, I used a shell script to extract modification date ranges
from the Git history, but that was complicated and unreliable, so now
every file just gets the same year range in its copyright header. If
someone needs to know when a specific file was modified and by whom,
they can look at the Git history themselves; no need to include it
redundantly in the header.