separate hook queue algorithms from concurrency logic

This is a very early step towards creating a global hook queue for the uniter, allowing us to implement leader election with a chance of injecting leadership change hooks in a reasonably timely fashion.

It's a long way from perfect; the dependency on params.RelationUnitsChange is extremely yucky, and there's something questionable-at-best about tying the watcher to the consumer of its events, but I think it *is* better than what we currently have. And it is a straight refactor: while it may not be apparent, because I carved pieces out of hookqueue.go until I had something I was happy with, the logic has not changed at all -- the only change to the existing tests is to add an alternative method to the `checker` interface to allow me to clone the existing tests and run them directly against the HookSource interface.

It's also very likely that much of this logic is in the wrong package, but I don't plan to move it until it's clear where it should go: moving it into uniter/hook is the obvious choice, but is not currently possible without import cycles, and this PR is big enough already.