Rename our allwpilib (which is now 2020) to not have 2019 in the name

Change-Id: I3c07f85ed32ab8b97db765a9b43f2a6ce7da964a
diff --git a/hal/src/main/native/sim/Notifier.cpp b/hal/src/main/native/sim/Notifier.cpp
new file mode 100644
index 0000000..211f7b2
--- /dev/null
+++ b/hal/src/main/native/sim/Notifier.cpp
@@ -0,0 +1,223 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2019 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "hal/Notifier.h"
+
+#include <atomic>
+#include <chrono>
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include <wpi/condition_variable.h>
+#include <wpi/mutex.h>
+#include <wpi/timestamp.h>
+
+#include "HALInitializer.h"
+#include "NotifierInternal.h"
+#include "hal/HAL.h"
+#include "hal/cpp/fpga_clock.h"
+#include "hal/handles/UnlimitedHandleResource.h"
+#include "mockdata/NotifierData.h"
+
+namespace {
+struct Notifier {
+  std::string name;
+  uint64_t waitTime;
+  bool active = true;
+  bool running = false;
+  wpi::mutex mutex;
+  wpi::condition_variable cond;
+};
+}  // namespace
+
+using namespace hal;
+
+class NotifierHandleContainer
+    : public UnlimitedHandleResource<HAL_NotifierHandle, Notifier,
+                                     HAL_HandleEnum::Notifier> {
+ public:
+  ~NotifierHandleContainer() {
+    ForEach([](HAL_NotifierHandle handle, Notifier* notifier) {
+      {
+        std::scoped_lock lock(notifier->mutex);
+        notifier->active = false;
+        notifier->running = false;
+      }
+      notifier->cond.notify_all();  // wake up any waiting threads
+    });
+  }
+};
+
+static NotifierHandleContainer* notifierHandles;
+static std::atomic<bool> notifiersPaused{false};
+
+namespace hal {
+namespace init {
+void InitializeNotifier() {
+  static NotifierHandleContainer nH;
+  notifierHandles = &nH;
+}
+}  // namespace init
+
+void PauseNotifiers() { notifiersPaused = true; }
+
+void ResumeNotifiers() {
+  notifiersPaused = false;
+  WakeupNotifiers();
+}
+
+void WakeupNotifiers() {
+  notifierHandles->ForEach([](HAL_NotifierHandle handle, Notifier* notifier) {
+    notifier->cond.notify_all();
+  });
+}
+}  // namespace hal
+
+extern "C" {
+
+HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status) {
+  hal::init::CheckInit();
+  std::shared_ptr<Notifier> notifier = std::make_shared<Notifier>();
+  HAL_NotifierHandle handle = notifierHandles->Allocate(notifier);
+  if (handle == HAL_kInvalidHandle) {
+    *status = HAL_HANDLE_ERROR;
+    return HAL_kInvalidHandle;
+  }
+  return handle;
+}
+
+void HAL_SetNotifierName(HAL_NotifierHandle notifierHandle, const char* name,
+                         int32_t* status) {
+  auto notifier = notifierHandles->Get(notifierHandle);
+  if (!notifier) return;
+  std::scoped_lock lock(notifier->mutex);
+  notifier->name = name;
+}
+
+void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
+  auto notifier = notifierHandles->Get(notifierHandle);
+  if (!notifier) return;
+
+  {
+    std::scoped_lock lock(notifier->mutex);
+    notifier->active = false;
+    notifier->running = false;
+  }
+  notifier->cond.notify_all();
+}
+
+void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
+  auto notifier = notifierHandles->Free(notifierHandle);
+  if (!notifier) return;
+
+  // Just in case HAL_StopNotifier() wasn't called...
+  {
+    std::scoped_lock lock(notifier->mutex);
+    notifier->active = false;
+    notifier->running = false;
+  }
+  notifier->cond.notify_all();
+}
+
+void HAL_UpdateNotifierAlarm(HAL_NotifierHandle notifierHandle,
+                             uint64_t triggerTime, int32_t* status) {
+  auto notifier = notifierHandles->Get(notifierHandle);
+  if (!notifier) return;
+
+  {
+    std::scoped_lock lock(notifier->mutex);
+    notifier->waitTime = triggerTime;
+    notifier->running = true;
+  }
+
+  // We wake up any waiters to change how long they're sleeping for
+  notifier->cond.notify_all();
+}
+
+void HAL_CancelNotifierAlarm(HAL_NotifierHandle notifierHandle,
+                             int32_t* status) {
+  auto notifier = notifierHandles->Get(notifierHandle);
+  if (!notifier) return;
+
+  {
+    std::scoped_lock lock(notifier->mutex);
+    notifier->running = false;
+  }
+}
+
+uint64_t HAL_WaitForNotifierAlarm(HAL_NotifierHandle notifierHandle,
+                                  int32_t* status) {
+  auto notifier = notifierHandles->Get(notifierHandle);
+  if (!notifier) return 0;
+
+  std::unique_lock lock(notifier->mutex);
+  while (notifier->active) {
+    double waitTime;
+    if (!notifier->running || notifiersPaused) {
+      waitTime = (HAL_GetFPGATime(status) * 1e-6) + 1000.0;
+      // If not running, wait 1000 seconds
+    } else {
+      waitTime = notifier->waitTime * 1e-6;
+    }
+
+    auto timeoutTime =
+        hal::fpga_clock::epoch() + std::chrono::duration<double>(waitTime);
+    notifier->cond.wait_until(lock, timeoutTime);
+    if (!notifier->running) continue;
+    if (!notifier->active) break;
+    uint64_t curTime = HAL_GetFPGATime(status);
+    if (curTime < notifier->waitTime) continue;
+    notifier->running = false;
+    return curTime;
+  }
+  return 0;
+}
+
+uint64_t HALSIM_GetNextNotifierTimeout(void) {
+  uint64_t timeout = UINT64_MAX;
+  notifierHandles->ForEach([&](HAL_NotifierHandle, Notifier* notifier) {
+    std::scoped_lock lock(notifier->mutex);
+    if (notifier->active && notifier->running && timeout > notifier->waitTime)
+      timeout = notifier->waitTime;
+  });
+  return timeout;
+}
+
+int32_t HALSIM_GetNumNotifiers(void) {
+  int32_t count = 0;
+  notifierHandles->ForEach([&](HAL_NotifierHandle, Notifier* notifier) {
+    std::scoped_lock lock(notifier->mutex);
+    if (notifier->active) ++count;
+  });
+  return count;
+}
+
+int32_t HALSIM_GetNotifierInfo(struct HALSIM_NotifierInfo* arr, int32_t size) {
+  int32_t num = 0;
+  notifierHandles->ForEach([&](HAL_NotifierHandle handle, Notifier* notifier) {
+    std::scoped_lock lock(notifier->mutex);
+    if (!notifier->active) return;
+    if (num < size) {
+      arr[num].handle = handle;
+      if (notifier->name.empty()) {
+        std::snprintf(arr[num].name, sizeof(arr[num].name), "Notifier%d",
+                      static_cast<int>(getHandleIndex(handle)));
+      } else {
+        std::strncpy(arr[num].name, notifier->name.c_str(),
+                     sizeof(arr[num].name));
+        arr[num].name[sizeof(arr[num].name) - 1] = '\0';
+      }
+      arr[num].timeout = notifier->waitTime;
+      arr[num].running = notifier->running;
+    }
+    ++num;
+  });
+  return num;
+}
+
+}  // extern "C"