Squashed 'third_party/allwpilib_2017/' content from commit 35ac87d

Change-Id: I7bb6f5556c30d3f5a092e68de0be9c710c60c9f4
git-subtree-dir: third_party/allwpilib_2017
git-subtree-split: 35ac87d6ff8b7f061c4f18c9ea316e5dccd4888a
diff --git a/hal/include/HAL/cpp/Log.h b/hal/include/HAL/cpp/Log.h
new file mode 100644
index 0000000..4ddbd4f
--- /dev/null
+++ b/hal/include/HAL/cpp/Log.h
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <chrono>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+inline std::string NowTime();
+
+enum TLogLevel {
+  logNONE,
+  logERROR,
+  logWARNING,
+  logINFO,
+  logDEBUG,
+  logDEBUG1,
+  logDEBUG2,
+  logDEBUG3,
+  logDEBUG4
+};
+
+class Log {
+ public:
+  Log();
+  virtual ~Log();
+  std::ostringstream& Get(TLogLevel level = logINFO);
+
+ public:
+  static TLogLevel& ReportingLevel();
+  static std::string ToString(TLogLevel level);
+  static TLogLevel FromString(const std::string& level);
+
+ protected:
+  std::ostringstream os;
+
+ private:
+  Log(const Log&);
+  Log& operator=(const Log&);
+};
+
+inline Log::Log() {}
+
+inline std::ostringstream& Log::Get(TLogLevel level) {
+  os << "- " << NowTime();
+  os << " " << ToString(level) << ": ";
+  os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
+  return os;
+}
+
+inline Log::~Log() {
+  os << std::endl;
+  std::cerr << os.str();
+}
+
+inline TLogLevel& Log::ReportingLevel() {
+  static TLogLevel reportingLevel = logDEBUG4;
+  return reportingLevel;
+}
+
+inline std::string Log::ToString(TLogLevel level) {
+  static const char* const buffer[] = {"NONE",   "ERROR",  "WARNING",
+                                       "INFO",   "DEBUG",  "DEBUG1",
+                                       "DEBUG2", "DEBUG3", "DEBUG4"};
+  return buffer[level];
+}
+
+inline TLogLevel Log::FromString(const std::string& level) {
+  if (level == "DEBUG4") return logDEBUG4;
+  if (level == "DEBUG3") return logDEBUG3;
+  if (level == "DEBUG2") return logDEBUG2;
+  if (level == "DEBUG1") return logDEBUG1;
+  if (level == "DEBUG") return logDEBUG;
+  if (level == "INFO") return logINFO;
+  if (level == "WARNING") return logWARNING;
+  if (level == "ERROR") return logERROR;
+  if (level == "NONE") return logNONE;
+  Log().Get(logWARNING) << "Unknown logging level '" << level
+                        << "'. Using INFO level as default.";
+  return logINFO;
+}
+
+typedef Log FILELog;
+
+#define FILE_LOG(level)                  \
+  if (level > FILELog::ReportingLevel()) \
+    ;                                    \
+  else                                   \
+  Log().Get(level)
+
+inline std::string NowTime() {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2);
+
+  using namespace std::chrono;
+  auto now = system_clock::now().time_since_epoch();
+
+  ss << duration_cast<hours>(now).count() % 24 << ":"
+     << duration_cast<minutes>(now).count() % 60 << ":"
+     << duration_cast<seconds>(now).count() % 60 << "."
+     << duration_cast<milliseconds>(now).count() % 1000;
+
+  return ss.str();
+}
diff --git a/hal/include/HAL/cpp/Semaphore.h b/hal/include/HAL/cpp/Semaphore.h
new file mode 100644
index 0000000..53e17d7
--- /dev/null
+++ b/hal/include/HAL/cpp/Semaphore.h
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <condition_variable>
+
+#include "HAL/cpp/priority_mutex.h"
+#include "support/deprecated.h"
+
+class WPI_DEPRECATED(
+    "Semaphore scheduled for removal in 2018. Recommended to replace with a "
+    "std::mutex and std::condition_variable") Semaphore {
+ public:
+  explicit Semaphore(int32_t count = 0);
+  Semaphore(Semaphore&&);
+  Semaphore& operator=(Semaphore&&);
+
+  void give();
+  void take();
+
+  // @return true if semaphore was locked successfully. false if not.
+  bool tryTake();
+
+  static const int32_t kNoWait = 0;
+  static const int32_t kWaitForever = -1;
+
+  static const int32_t kEmpty = 0;
+  static const int32_t kFull = 1;
+
+ private:
+  priority_mutex m_mutex;
+  std::condition_variable_any m_condition;
+  int32_t m_count = 0;
+};
diff --git a/hal/include/HAL/cpp/SerialHelper.h b/hal/include/HAL/cpp/SerialHelper.h
new file mode 100644
index 0000000..f416818
--- /dev/null
+++ b/hal/include/HAL/cpp/SerialHelper.h
@@ -0,0 +1,51 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "HAL/SerialPort.h"
+#include "HAL/cpp/priority_mutex.h"
+#include "llvm/SmallString.h"
+#include "llvm/SmallVector.h"
+
+namespace hal {
+class SerialHelper {
+ public:
+  SerialHelper();
+
+  std::string GetVISASerialPortName(HAL_SerialPort port, int32_t* status);
+  std::string GetOSSerialPortName(HAL_SerialPort port, int32_t* status);
+
+  std::vector<std::string> GetVISASerialPortList(int32_t* status);
+  std::vector<std::string> GetOSSerialPortList(int32_t* status);
+
+ private:
+  void SortHubPathVector();
+  void CoiteratedSort(llvm::SmallVectorImpl<llvm::SmallString<16>>& vec);
+  void QueryHubPaths(int32_t* status);
+
+  int32_t GetIndexForPort(HAL_SerialPort port, int32_t* status);
+
+  // Vectors to hold data before sorting.
+  // Note we will most likely have at max 2 instances, and the longest string
+  // is around 12, so these should never touch the heap;
+  llvm::SmallVector<llvm::SmallString<16>, 4> m_visaResource;
+  llvm::SmallVector<llvm::SmallString<16>, 4> m_osResource;
+  llvm::SmallVector<llvm::SmallString<16>, 4> m_unsortedHubPath;
+  llvm::SmallVector<llvm::SmallString<16>, 4> m_sortedHubPath;
+
+  int32_t m_resourceHandle;
+
+  static priority_mutex m_nameMutex;
+  static std::string m_usbNames[2];
+};
+}  // namespace hal
diff --git a/hal/include/HAL/cpp/make_unique.h b/hal/include/HAL/cpp/make_unique.h
new file mode 100644
index 0000000..d70f873
--- /dev/null
+++ b/hal/include/HAL/cpp/make_unique.h
@@ -0,0 +1,47 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// Define make_unique for C++11-only compilers
+#if __cplusplus == 201103L
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace std {
+template <class T>
+struct _Unique_if {
+  typedef unique_ptr<T> _Single_object;
+};
+
+template <class T>
+struct _Unique_if<T[]> {
+  typedef unique_ptr<T[]> _Unknown_bound;
+};
+
+template <class T, size_t N>
+struct _Unique_if<T[N]> {
+  typedef void _Known_bound;
+};
+
+template <class T, class... Args>
+typename _Unique_if<T>::_Single_object make_unique(Args&&... args) {
+  return unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+template <class T>
+typename _Unique_if<T>::_Unknown_bound make_unique(size_t n) {
+  typedef typename remove_extent<T>::type U;
+  return unique_ptr<T>(new U[n]());
+}
+
+template <class T, class... Args>
+typename _Unique_if<T>::_Known_bound make_unique(Args&&...) = delete;
+}  // namespace std
+#endif
diff --git a/hal/include/HAL/cpp/priority_condition_variable.h b/hal/include/HAL/cpp/priority_condition_variable.h
new file mode 100644
index 0000000..12aeba9
--- /dev/null
+++ b/hal/include/HAL/cpp/priority_condition_variable.h
@@ -0,0 +1,132 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+/* std::condition_variable provides the native_handle() method to return its
+ * underlying pthread_cond_t*. WPILib uses this to interface with the FRC
+ * network communication library. Since WPILib uses a custom mutex class and
+ * not std::mutex, std::condition_variable_any must be used instead.
+ * std::condition_variable_any doesn't expose its internal handle, so this
+ * class provides the same interface and implementation in addition to a
+ * native_handle() method.
+ */
+
+#include <condition_variable>
+#include <memory>
+#include <utility>
+
+#include "priority_mutex.h"
+
+class priority_condition_variable {
+  typedef std::chrono::system_clock clock;
+
+ public:
+  typedef std::condition_variable::native_handle_type native_handle_type;
+
+  priority_condition_variable() : m_mutex(std::make_shared<std::mutex>()) {}
+  ~priority_condition_variable() = default;
+
+  priority_condition_variable(const priority_condition_variable&) = delete;
+  priority_condition_variable& operator=(const priority_condition_variable&) =
+      delete;
+
+  void notify_one() noexcept {
+    std::lock_guard<std::mutex> lock(*m_mutex);
+    m_cond.notify_one();
+  }
+
+  void notify_all() noexcept {
+    std::lock_guard<std::mutex> lock(*m_mutex);
+    m_cond.notify_all();
+  }
+
+  template <typename Lock>
+  void wait(Lock& _lock) {
+    std::shared_ptr<std::mutex> _mutex = m_mutex;
+    std::unique_lock<std::mutex> my_lock(*_mutex);
+    Unlock<Lock> unlock(_lock);
+
+    // *mutex must be unlocked before re-locking _lock so move
+    // ownership of *_mutex lock to an object with shorter lifetime.
+    std::unique_lock<std::mutex> my_lock2(std::move(my_lock));
+    m_cond.wait(my_lock2);
+  }
+
+  template <typename Lock, typename Predicate>
+  void wait(Lock& lock, Predicate p) {
+    while (!p()) {
+      wait(lock);
+    }
+  }
+
+  template <typename Lock, typename Clock, typename Duration>
+  std::cv_status wait_until(
+      Lock& _lock, const std::chrono::time_point<Clock, Duration>& atime) {
+    std::shared_ptr<std::mutex> _mutex = m_mutex;
+    std::unique_lock<std::mutex> my_lock(*_mutex);
+    Unlock<Lock> unlock(_lock);
+
+    // *_mutex must be unlocked before re-locking _lock so move
+    // ownership of *_mutex lock to an object with shorter lifetime.
+    std::unique_lock<std::mutex> my_lock2(std::move(my_lock));
+    return m_cond.wait_until(my_lock2, atime);
+  }
+
+  template <typename Lock, typename Clock, typename Duration,
+            typename Predicate>
+  bool wait_until(Lock& lock,
+                  const std::chrono::time_point<Clock, Duration>& atime,
+                  Predicate p) {
+    while (!p()) {
+      if (wait_until(lock, atime) == std::cv_status::timeout) {
+        return p();
+      }
+    }
+    return true;
+  }
+
+  template <typename Lock, typename Rep, typename Period>
+  std::cv_status wait_for(Lock& lock,
+                          const std::chrono::duration<Rep, Period>& rtime) {
+    return wait_until(lock, clock::now() + rtime);
+  }
+
+  template <typename Lock, typename Rep, typename Period, typename Predicate>
+  bool wait_for(Lock& lock, const std::chrono::duration<Rep, Period>& rtime,
+                Predicate p) {
+    return wait_until(lock, clock::now() + rtime, std::move(p));
+  }
+
+  native_handle_type native_handle() { return m_cond.native_handle(); }
+
+ private:
+  std::condition_variable m_cond;
+  std::shared_ptr<std::mutex> m_mutex;
+
+  // scoped unlock - unlocks in ctor, re-locks in dtor
+  template <typename Lock>
+  struct Unlock {
+    explicit Unlock(Lock& lk) : m_lock(lk) { lk.unlock(); }
+
+    ~Unlock() /*noexcept(false)*/ {
+      if (std::uncaught_exception()) {
+        try {
+          m_lock.lock();
+        } catch (...) {
+        }
+      } else {
+        m_lock.lock();
+      }
+    }
+
+    Unlock(const Unlock&) = delete;
+    Unlock& operator=(const Unlock&) = delete;
+
+    Lock& m_lock;
+  };
+};
diff --git a/hal/include/HAL/cpp/priority_mutex.h b/hal/include/HAL/cpp/priority_mutex.h
new file mode 100644
index 0000000..c156bed
--- /dev/null
+++ b/hal/include/HAL/cpp/priority_mutex.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2016-2017. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// Allows usage with std::lock_guard without including <mutex> separately
+#include <mutex>
+
+#if defined(FRC_SIMULATOR) || defined(_WIN32)
+// We do not want to use pthreads if in the simulator; however, in the
+// simulator, we do not care about priority inversion.
+typedef std::mutex priority_mutex;
+typedef std::recursive_mutex priority_recursive_mutex;
+#else  // Covers rest of file.
+
+#include <pthread.h>
+
+class priority_recursive_mutex {
+ public:
+  typedef pthread_mutex_t* native_handle_type;
+
+  constexpr priority_recursive_mutex() noexcept = default;
+  priority_recursive_mutex(const priority_recursive_mutex&) = delete;
+  priority_recursive_mutex& operator=(const priority_recursive_mutex&) = delete;
+
+  // Lock the mutex, blocking until it's available.
+  void lock();
+
+  // Unlock the mutex.
+  void unlock();
+
+  // Tries to lock the mutex.
+  bool try_lock() noexcept;
+
+  pthread_mutex_t* native_handle();
+
+ private:
+// Do the equivalent of setting PTHREAD_PRIO_INHERIT and
+// PTHREAD_MUTEX_RECURSIVE_NP.
+#if __WORDSIZE == 64
+  pthread_mutex_t m_mutex = {
+      {0, 0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, {0, 0}}};
+#else
+  pthread_mutex_t m_mutex = {
+      {0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, {0}}};
+#endif
+};
+
+class priority_mutex {
+ public:
+  typedef pthread_mutex_t* native_handle_type;
+
+  constexpr priority_mutex() noexcept = default;
+  priority_mutex(const priority_mutex&) = delete;
+  priority_mutex& operator=(const priority_mutex&) = delete;
+
+  // Lock the mutex, blocking until it's available.
+  void lock();
+
+  // Unlock the mutex.
+  void unlock();
+
+  // Tries to lock the mutex.
+  bool try_lock() noexcept;
+
+  pthread_mutex_t* native_handle();
+
+ private:
+// Do the equivalent of setting PTHREAD_PRIO_INHERIT.
+#if __WORDSIZE == 64
+  pthread_mutex_t m_mutex = {{0, 0, 0, 0, 0x20, 0, 0, {0, 0}}};
+#else
+  pthread_mutex_t m_mutex = {{0, 0, 0, 0x20, 0, {0}}};
+#endif
+};
+
+#endif  // FRC_SIMULATOR