Set fiber_properties::sched_algo_ every time through awakened().

Instead of setting a fiber_properties subclass's sched_algo_ back pointer once
at construction time, unconditionally set it every time that fiber becomes
READY (and is therefore passed to sched_algorithm::awakened()). This handles
the case in which that fiber migrates to a different thread with a different
sched_algorithm subclass instance.

Break out fiber_properties::notify() implementation to a separate .cpp
implementation file so it can bring in algorithm.hpp. We don't want
properties.hpp to depend on algorithm.hpp.
Define sched_algorithm methods on fiber_base*, not worker_fiber*.

Some reviewers disliked that to build a custom sched_algorithm subclass, you
must necessarily manipulate pointers to classes in the boost::fibers::detail
namespace. Redefine all such methods to use fiber_base* rather than
detail::worker_fiber*.

Hoist fiber_base* into boost::fibers namespace. We considered an opaque
typedef rather than fiber_base*, but in fact a sched_algorithm subclass may
need is_ready().

Moreover, a sched_algorithm subclass may well want to use an intrusive linked
list to queue fibers. Hoist worker_fiber::nxt_ pointer into fiber_base, and
remove worker_fiber::next() and next_reset() methods. This allows recasting
detail::fifo in terms of fiber_base*, therefore round_robin can be stated
almost entirely in terms of fiber_base* rather than worker_fiber*.

Recast fiber constructor taking worker_fiber* to take fiber_base* instead.
This constructor is used solely for fiber migration; with relevant functions
now returning fiber_base*, we think we no longer need fiber(worker_fiber*).
Simplify detail::fifo by making tail_ point to last link pointer.

Maintaining a singly-linked list is tricky when you walk it with a node*
pointer. But if you use a node** pointer starting at &head_ and advancing to
point to each &nxt_ pointer, you can coalesce the empty-list case into the
normal case.
Reimplement waiting_queue::push() using pointer-to-pointer trick.

Change waiting_queue::head_ from worker_fiber* to fiber_base* for uniformity
with worker_fiber::nxt_. This lets push() scan from head_ with a fiber_base**,
looking for the right insertion point. Insertion then becomes a couple
unconditional assignments.

Because push() always scans from head_, tail_ was actually never used. Remove
it.
Reimplement waiting_queue::move_to() using fiber_base** scan.

This simplifies unlinking from the queue.
Make bounded_queue::tail_ a ptr* to simplify appending new nodes.
Make unbounded_queue::tail_ a ptr* to simplify linking new nodes.