Convert all year's robots to proper event loops

Each robot has a couple of event loops, one per thread.  Each of these
threads corresponds to the threads from before the change.  y2016 has
been tested on real hardware.

Change-Id: I99f726a8bc0498204c1a3b99f15508119eed9ad3
diff --git a/frc971/wpilib/loop_output_handler.h b/frc971/wpilib/loop_output_handler.h
index ff8415f..3c95408 100644
--- a/frc971/wpilib/loop_output_handler.h
+++ b/frc971/wpilib/loop_output_handler.h
@@ -21,24 +21,37 @@
 // The intended use is to have a subclass for each loop which implements the
 // pure virtual methods and is then run in a separate thread. The operator()
 // loops writing values until Quit() is called.
+template <typename T>
 class LoopOutputHandler {
  public:
   LoopOutputHandler(
-      ::aos::EventLoop *event_loop,
-      ::std::chrono::nanoseconds timeout = ::std::chrono::milliseconds(100));
+      ::aos::EventLoop *event_loop, const ::std::string &name,
+      ::std::chrono::nanoseconds timeout = ::std::chrono::milliseconds(100))
+      : event_loop_(event_loop), timeout_(timeout) {
+    event_loop_->SetRuntimeRealtimePriority(30);
+    // TODO(austin): Name thread.
+    event_loop_->MakeWatcher(name, [this](const T &t) {
+      // Push the watchdog out a bit further.
+      timer_handler_->Setup(event_loop_->monotonic_now() + timeout_);
+      Write(t);
+    });
 
-  void Quit() { run_ = false; }
+    // TODO(austin): Set name.
+    timer_handler_ = event_loop_->AddTimer([this]() { Stop(); });
 
-  void operator()();
+    event_loop_->OnRun([this, timeout]() {
+      timer_handler_->Setup(event_loop_->monotonic_now() + timeout_);
+    });
+  }
+
+  void Quit() { event_loop_->Exit(); }
+
+  // Note, all subclasses should call Stop.
+  virtual ~LoopOutputHandler() {}
 
  protected:
-  // Read a message from the appropriate queue.
-  // This must block.
-  virtual void Read() = 0;
-
   // Send the output from the appropriate queue to the hardware.
-  // Read() will always be called at least once before per invocation of this.
-  virtual void Write() = 0;
+  virtual void Write(const T &t) = 0;
 
   // Stop all outputs. This will be called in a separate thread (if at all).
   // The subclass implementation should handle any appropriate logging.
@@ -50,46 +63,9 @@
   ::aos::EventLoop *event_loop() { return event_loop_; }
 
  private:
-  // The thread that actually contains a timerfd to implement timeouts. The
-  // idea is to have a timerfd that is repeatedly set to the timeout expiration
-  // in the future so it will never actually expire unless it is not reset for
-  // too long.
-  //
-  // This class nicely encapsulates the raw fd and manipulating it. Its
-  // operator() loops until Quit() is called, calling Stop() on its associated
-  // LoopOutputHandler whenever the timerfd expires.
-  class Watchdog {
-   public:
-    Watchdog(LoopOutputHandler *handler, ::std::chrono::nanoseconds timeout);
-
-    void operator()();
-
-    void Reset();
-
-    void Quit() { run_ = false; }
-
-   private:
-    LoopOutputHandler *const handler_;
-
-    const ::std::chrono::nanoseconds timeout_;
-
-    ::aos::ScopedFD timerfd_;
-
-    ::std::atomic<bool> run_{true};
-  };
-
   ::aos::EventLoop *event_loop_;
-  ::aos::Fetcher<::aos::JoystickState> joystick_state_fetcher_;
-  Watchdog watchdog_;
-
-  ::std::atomic<bool> run_{true};
-
-  ::aos::util::SimpleLogInterval no_joystick_state_ =
-      ::aos::util::SimpleLogInterval(::std::chrono::milliseconds(500), INFO,
-                                     "no joystick state -> not outputting");
-  ::aos::util::SimpleLogInterval fake_joystick_state_ =
-      ::aos::util::SimpleLogInterval(::std::chrono::milliseconds(500), DEBUG,
-                                     "fake joystick state -> not outputting");
+  const ::std::chrono::nanoseconds timeout_;
+  ::aos::TimerHandler *timer_handler_;
 };
 
 }  // namespace wpilib