Bunch of fixes observed during hot standby testing, fixing memory leaks, and tidying API

WIP - FOR REVIEW ONLY.

just discovered one bug i can't seem to track down, where service_up does not recompute itself as true
Regarding @neykov 's comment "Personally prefer double null check (out of the sync block as well) so that we need synchronization on first call only but fine as is."

If you do ever use double-check locking like that, then be sure to declare your field volatile (which then removes much of the performance benefit of the double-check locking). The only time you can get away without the volatile is if it's a primitive (that is 32 bits or less). Otherwise, you risk other threads seeing a semi-initialised object because the writer thread and the second thread don't have a "happens before" relationship.

Double-checked locking is broken (according to the Java memory model spec) in far too many uses of it, but folk "get away with it" (i.e. hardly ever see problems) because of the way the current generations of Intel multi-core chips behave. It's usage is often not worth the performance gain (and consider alternatives like instantiating the field in the constructor, declared final).

But such comments aren't relevant for this particular usage obviously!