17#ifndef TOOLBOX_IO_TIMER_HPP 
   18#define TOOLBOX_IO_TIMER_HPP 
   26#include <boost/intrusive_ptr.hpp> 
   58    Timer(std::nullptr_t = 
nullptr) noexcept {} 
 
   69    bool empty() const noexcept { 
return !impl_; }
 
   70    explicit operator bool() const noexcept { 
return impl_ != 
nullptr; }
 
   71    long id() const noexcept { 
return impl_ ? impl_->id : 0; }
 
   72    bool pending() const noexcept { 
return impl_ != 
nullptr && 
bool{impl_->slot}; }
 
   77    template <
typename RepT, 
typename PeriodT>
 
   78    void set_interval(std::chrono::duration<RepT, PeriodT> interval) 
noexcept 
   81        impl_->interval = duration_cast<Duration>(interval);
 
 
   83    void reset(std::nullptr_t = 
nullptr) noexcept { impl_.reset(); }
 
   84    void swap(
Timer& rhs) 
noexcept { impl_.swap(rhs.impl_); }
 
   85    void cancel() noexcept;
 
   87    std::partial_ordering operator<=>(const 
Timer& rhs) const noexcept
 
   90            return std::partial_ordering::unordered;
 
   92        return id() <=> rhs.id();
 
 
   96    void set_expiry(
MonoTime expiry) 
noexcept { impl_->expiry = expiry; }
 
   97    TimerSlot& slot() noexcept { 
return impl_->slot; }
 
   99    boost::intrusive_ptr<Timer::Impl> impl_;
 
 
  103    using SlabPtr = std::unique_ptr<Timer::Impl[]>;
 
  117    Timer::Impl* allocate();
 
  118    void deallocate(
Timer::Impl* impl) noexcept
 
 
  126    std::vector<SlabPtr> slabs_;
 
 
  136    using SlabPtr = std::unique_ptr<Timer::Impl[]>;
 
  155    std::
size_t size() const noexcept { 
return heap_.size() - cancelled_; }
 
  165        return insert(expiry, Duration::zero(), slot);
 
 
  173    void cancel() noexcept;
 
  176    Timer pop() noexcept;
 
  182    std::vector<Timer> heap_;
 
 
  195    if (impl_ && impl_->slot) {