Squashed 'third_party/ntcore_2016/' content from commit d8de5e4
Change-Id: Id4839f41b6a620d8bae58dcf1710016671cc4992
git-subtree-dir: third_party/ntcore_2016
git-subtree-split: d8de5e4f19e612e7102172c0dbf152ce82d3d63a
diff --git a/src/support/ConcurrentQueue.h b/src/support/ConcurrentQueue.h
new file mode 100644
index 0000000..fa99477
--- /dev/null
+++ b/src/support/ConcurrentQueue.h
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com
+// Subject to the BSD 2-Clause License
+// - see < http://opensource.org/licenses/BSD-2-Clause>
+//
+
+#ifndef NT_SUPPORT_CONCURRENT_QUEUE_H_
+#define NT_SUPPORT_CONCURRENT_QUEUE_H_
+
+#include <queue>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+template <typename T>
+class ConcurrentQueue {
+ public:
+ bool empty() const {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ return queue_.empty();
+ }
+
+ typename std::queue<T>::size_type size() const {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ return queue_.size();
+ }
+
+ T pop() {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ while (queue_.empty()) {
+ cond_.wait(mlock);
+ }
+ auto item = std::move(queue_.front());
+ queue_.pop();
+ return item;
+ }
+
+ void pop(T& item) {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ while (queue_.empty()) {
+ cond_.wait(mlock);
+ }
+ item = queue_.front();
+ queue_.pop();
+ }
+
+ void push(const T& item) {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ queue_.push(item);
+ mlock.unlock();
+ cond_.notify_one();
+ }
+
+ void push(T&& item) {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ queue_.push(std::forward<T>(item));
+ mlock.unlock();
+ cond_.notify_one();
+ }
+
+ template <typename... Args>
+ void emplace(Args&&... args) {
+ std::unique_lock<std::mutex> mlock(mutex_);
+ queue_.emplace(std::forward<Args>(args)...);
+ mlock.unlock();
+ cond_.notify_one();
+ }
+
+ ConcurrentQueue() = default;
+ ConcurrentQueue(const ConcurrentQueue&) = delete;
+ ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
+
+ private:
+ std::queue<T> queue_;
+ mutable std::mutex mutex_;
+ std::condition_variable cond_;
+};
+
+#endif // NT_SUPPORT_CONCURRENT_QUEUE_H_
diff --git a/src/support/timestamp.cpp b/src/support/timestamp.cpp
new file mode 100644
index 0000000..6dd4387
--- /dev/null
+++ b/src/support/timestamp.cpp
@@ -0,0 +1,89 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2015. 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 "timestamp.h"
+
+#ifdef _WIN32
+#include <cassert>
+#include <exception>
+#include <windows.h>
+#else
+#include <chrono>
+#endif
+
+// offset in microseconds
+static unsigned long long zerotime() {
+#ifdef _WIN32
+ FILETIME ft;
+ unsigned long long tmpres = 0;
+ // 100-nanosecond intervals since January 1, 1601 (UTC)
+ // which means 0.1 us
+ GetSystemTimeAsFileTime(&ft);
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+ // January 1st, 1970 - January 1st, 1601 UTC ~ 369 years
+ // or 116444736000000000 us
+ static const unsigned long long deltaepoch = 116444736000000000ull;
+ tmpres -= deltaepoch;
+ return tmpres;
+#else
+ // 100-ns intervals
+ using namespace std::chrono;
+ return duration_cast<nanoseconds>(
+ high_resolution_clock::now().time_since_epoch()).count() / 100u;
+#endif
+}
+
+static unsigned long long timestamp() {
+#ifdef _WIN32
+ LARGE_INTEGER li;
+ QueryPerformanceCounter(&li);
+ // there is an imprecision with the initial value,
+ // but what matters is that timestamps are monotonic and consistent
+ return static_cast<unsigned long long>(li.QuadPart);
+#else
+ // 100-ns intervals
+ using namespace std::chrono;
+ return duration_cast<nanoseconds>(
+ steady_clock::now().time_since_epoch()).count() / 100u;
+#endif
+}
+
+#ifdef _WIN32
+static unsigned long long update_frequency() {
+ LARGE_INTEGER li;
+ if (!QueryPerformanceFrequency(&li) || !li.QuadPart) {
+ // log something
+ std::terminate();
+ }
+ return static_cast<unsigned long long>(li.QuadPart);
+}
+#endif
+
+static const unsigned long long zerotime_val = zerotime();
+static const unsigned long long offset_val = timestamp();
+#ifdef _WIN32
+static const unsigned long long frequency_val = update_frequency();
+#endif
+
+unsigned long long nt::Now() {
+#ifdef _WIN32
+ assert(offset_val > 0u);
+ assert(frequency_val > 0u);
+ unsigned long long delta = timestamp() - offset_val;
+ // because the frequency is in update per seconds, we have to multiply the
+ // delta by 10,000,000
+ unsigned long long delta_in_us = delta * 10000000ull / frequency_val;
+ return delta_in_us + zerotime_val;
+#else
+ return zerotime_val + timestamp() - offset_val;
+#endif
+}
+
+unsigned long long NT_Now() {
+ return nt::Now();
+}
diff --git a/src/support/timestamp.h b/src/support/timestamp.h
new file mode 100644
index 0000000..215aa88
--- /dev/null
+++ b/src/support/timestamp.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2015. 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. */
+/*----------------------------------------------------------------------------*/
+#ifndef NT_SUPPORT_TIMESTAMP_H_
+#define NT_SUPPORT_TIMESTAMP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned long long NT_Now(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+namespace nt {
+
+unsigned long long Now();
+
+} // namespace nt
+#endif
+
+#endif // NT_SUPPORT_TIMESTAMP_H_