Squashed 'third_party/allwpilib_2019/' changes from 99e4f7dd2..c36bbcc9a

936627bd9 wpilibc: Remove direct CameraServer dependency (#1989)
8e333c0aa Use FPGA Time instead of wall clock time for odometry (#1996)
d4430b765 Gearsbot example: Use standard argument order (#1995)
75438ab2c Add RamseteCommand (#1951)
989df1b46 Bump Native Utils and OpenCV dependencies (#1993)
dbc33b61e Fix Timer usage in TrapezoidProfileCommand (#1992)
79f8c5644 Add TrapezoidProfileCommand (#1962)
9440edf2b Refactor TrajectoryGenerator (#1972)
73a30182c Add frc2::Timer (#1968)
36ea865ed Add toString for geometry and trajectory classes (#1991)
cbe05e7e8 Update ProfiledPIDController API (#1967)
d04eb3546 Deprecate old PID classes (#1964)
02264db69 Add JNI dependencies to myRobotCpp (#1980)
2a76c996e Use VID/PID detection for PS3Eye (#1977)
a3820bbdf Remove HAL_BaseInitialize (#1981)
a83fb4793 Update to 2020v5 image (#1983)
4b0ed910e Make SwerveDriveKinematics.toChassisSpeeds() public (#1976)
103c1b121 Remove DS caching from the HAL level (#1971)
6635ea75e Fix NPE in SendableRegistry.foreachLiveWindow() (#1974)
cfe23c5cd Fix grammar error in comment for configureButtonBindings (#1969)
4bde2654e Fix mac azure build (#1973)
4f034e6c1 generateTrajectory: default reversed param to false (#1953)
acf960f72 Sim GUI: Add option to disable outputs on DS disable
2d3dac99f Sim GUI: Handle low resolutions and scale default window positions
07c86e0cd Sim GUI: Support High DPI monitors
46ad95512 SimDeviceData: Add missing null check
5bce489b9 Add ProggyDotted font to imgui (both cmake and gradle)
55af553ac Simulation GUI: Map gamepad the same way as DS
c59f9cea5 CameraServer: Add VID/PID support for Linux USB devices (#1960)
3fc89c84d Make splinePointsFromSplines public (#1963)
2c5093797 Fix implicitly deleted move constructors (#1954)
f3ad927f4 Update Java SmartDashboard and LiveWindow to match C++
05c25deb7 Fix move handling of C++ Sendable in SmartDashboard and LiveWindow
d726591ce Fix Gazebo sim plugin build (#1959)
2ff694fa4 Unbreak gradle build when other compilers installed (#1958)
53816155b Improve command decorator names (#1945)
a38f183a9 Fix GenResources.cmake so it's usable in a submodule (#1956)
b3398dca3 Set gradlebase correctly for all examples (#1950)
2c311013d Add Aarch64Bionic platform detection (#1922)
c10f2003c Add generateTrajectory overload (#1944)
63cfa64fb Add getters for pose in odometry classes (#1943)
2402c2bad Fix C++ command group recursive constructor bug (#1941)
f4eedf597 Fix ConcurrentModificationException in CommandScheduler (#1938)
bb0b207d2 Fix array out of bounds exception caused by parallel race group (#1935)
7bd69e591 Fix typo in temperature (#1940)
ec9738245 Bump to 2020 v4 image (#1931)
46303a822 Add messaging to extension loading in the HAL (#1926)
d169d6be9 Set extract_static for Doxygen config so that static members show up (#1930)
4e183eb10 Bump to 2020 v3 image (#1929)
84c185803 LiveWindow: catch errors in callback/builder functions (#1921)
0e3b0f3da Remove deprecated free() calls (#1925)
7f839b87c Remove timeouts from azure builds (#1924)
45b766a5d Fix main thread ID being potentially incorrect for simulation (#1923)
56d782b16 Add secondary camera name for PS3Eye (#1920)
2b4894038 Add simulation GUI plugin
f97d16073 Add imgui build to cmake
55a844a3e HAL sim: Add encoder channel B access
10deba854 Remove sendables from SendableRegistry when close() is called (#1917)
a9f0e4668 Implement sim devices for ADXL345, ADXL362, ADXRS450, Ultrasonic
aa9064586 Add ability to associate other devices with a SimDevice
81c2c8a7d Add simulation generic device/value support
e8d6f8a2c Move mockdata/HAL_Value.h to hal/Value.h
1b266717a Add simulation module support to cmake build (#1906)
fb8f3bd06 Add testbench yaml file (#1915)
846d8def0 Update to 2020 v2 image (#1913)
d6ac6e512 Fix PortForwarder package declaration (#1912)
227157086 Fix PS3Eye exposure setting (#1911)
885744d7e Add myRobot C++ version to cmake build (#1907)
366091fa8 Document that ConditionalCommand requires all subsystems (#1909)
c58b072c8 Fix Drive usage reporting order (#1908)
762c88adb Update compiler versions in readme (#1905)
af8ce568d Add Ramsete unicycle controller (#1790)
b2c2934d0 Fix javadoc warnings about invalid usage of ">" (#1904)
cce26ec78 Replace CRLF line endings with LF (#1902)
cb54602d4 Add support for writing RTR CAN Frames to the CAN API (#1900)
9f740e590 Use OS for serial port instead of NI VISA (#1875)
b23baf611 Add ability to run robot main loop in a separate thread (#1895)
457f94ba2 Add trajectory generation using hermite splines (#1843)
fd612052f Update native utils to use new frchome directory (#1884)
8858ec55c Remove periodic can read call (#1868)
41efb8015 Update CANAPITypes.h (#1860)
c93be1b2d Remove LabVIEW HAL support (#1901)
680f8919e Remove eigen, units and libuv from doxygen generation (#1898)
c5812524f Bump GradleJNI plugin version (#1899)
971303da8 Add PortForwarder class (#1890)
50db77bf2 Fix wpiutil cmake eigen install source directory (#1891)
85d42c199 C++ PIDCommand: Add GetMeasurement() and UseOutput() (#1892)
2dfbb855d wpilibj: Fix SwerveDriveKinematics ctor parameter name (#1889)
471f375a3 Simplify Sendable interface (#1864)
1d8c4d016 Replace ::value and ::type with _v and _t suffixes (#1885)
a5650b943 Add Units Utility class for Java (#1829)
904479ad4 Deprecate GearTooth class for removal (#1878)
86b666bba Add equality comparator to geometry classes (#1882)
62f07c182 Make one-arg Rotation2d constructor implicit (#1883)
f405582f8 Add kinematics suite (#1787)
561cbbd14 Deprecate Filter class for removal (#1876)
84e2973aa Remove unused include from Filesystem.h (#1877)
f49859ebf Remove NI VISA headers, as they are now included in NI Libraries (#1879)
bc59db5e6 Rename DEBUG macro to DEBUG0 (#1871)
dd928b4cb Remove JNI logging (#1872)
3e0f7d099 Use units for new NotifierCommand (#1869)
5ffe15d5f Remove ability to build all combined artifacts (#1867)
516cbef2c  Remove RoboRIO ifdef from simulation headers (#1859)
9b6ffc201 Replace SetOutputRange() with SetIntegratorRange()
ff8b8f0a8 Remove percent tolerance from PID controller
0ca8d667d Clean up AutoCloseable and other Java warnings (#1866)
7112add67 Watchdog: use units::second_t instead of double (#1863)
761bc3ef8 Change C++ WaitCommand to use units (#1865)
1fb301123 Add MathUtils.clamp() for Java (#1861)
eb3e0c9c9 Fix cmake Eigen include directory (#1862)
2250b7fbe Rename GearsBotNew example to GearsBot
c9f9feff1 Replace deprecated API usage in C++ examples
d6b9c7e14 CONTRIBUTING.md: Point to frc-docs instead of screensteps (#1858)
d10a1a797 Fix eigen build in vcpkg (#1856)
2bdb44325 Add frc2 includes to list of "other lib" regexes (#1855)
4b2b21d24 Replace outdated Java collections (#508)
8993ce5bf Move Eigen headers out of main include folder (#1854)
0f532a117 Add PWMSparkMax (#1751)
f7ad363d8 Add jni cross compile options for aarch64 (#1853)
9afea3340 Add support for aarch64 jetson bionic builds (#1844)
d787b5d60 Add more items to .gitignore (#1850)
5dd0d1b7d Use units in SPI
07ac711b3 Fix units deprecated warning in IterativeRobot
decfd858b Correctly report -1 for POV on disconnected joystick (#1852)
076ed7770 Add new C++ Command framework (#1785)
a0be07c37 Refactor HAL handle move construction/assignment (#1845)
558c38308 Add new Java Command framework (#1682)
1379735af Delete RobotState and SensorUtil constructors (#1847)
e3d86fee4 Move circular buffer class from wpilib to wpiutil (#1840)
4cd8a5667 TimedRobot.cpp: Fix deprecation warning (#1846)
b2861f894 Use 2020 artifacts and artifactory server (#1838)
98cc32703 Update to use artifactory to publish artifacts (#1833)
fa0640300 Move drive integration tests into wpilibj/src/test (#1836)
e716c36b8 Fix Nat.java generation to be incremental (#1831)
9fd2b5e3f Fix MSVC builds on cmake windows in vcpkg (#1835)
7e95010a2 Add compile-time EJML matrix wrapper to wpiutil (#1804)
3ebc5a6d3 Add ProfiledPIDController
fc98a79db Clean up PIDController interface in preparation for ProfiledPIDController
fdc098267 Fix compilation error in elevator trapezoid profile example (#1826)
a3dd84e85 Make XBoxController Button enum public (#1823)
a216b9e9e Add TrapezoidProfile example (#1814)
8f386f6bb wpilibc: Add unit-safety to C++ geometry classes (#1811)
c07ac2353 wpilibc: Add overloads for units (#1815)
f1d71da8a Move GetStackTrace and Demangle to wpiutil, add Windows support (#1819)
ef037457e Make LinearFilter copyable and moveable (#1789)
76930250c Remove objective-cpp support (#1816)
1c246418f Move TrapezoidProfileTest to trajectory folder (#1812)
95a54a0f2 Add java arcade drive example (#1810)
a4530243e HAL sim: Fix incorrectly setting dio port to initialized on cleanup (#1813)
09d00a622 Update Java examples to use new PIDController (#1809)
ba9b51742 Add missing Java examples (#841)
6411bd79c InterruptableSensorBase: Fix callback function deletion (#1807)
810e58ea8 I2C: Add tip about writeBulk() to transaction() (#1806)
607d6c148 Fix wpilibj integration tests jar name (#1808)
c9873e81b Remove PIDControllerRunner and mutex from new PIDController (#1795)
98d0706de Fix cscore build with OpenCV 4 (#1803)
fbe67c90c Make Sendable setters synchronous (#1799)
c67a488a0 Format SendableBuilderImpl javadocs (#1802)
8e93ce892 Fix PIDControllerRunner member destruction order (#1801)
c98ca7310 Add EJML dependency to wpiutil (#1769)
3b12276bc SendableBase: remove unnecessary synchronization (#1797)
e6d348f38 Fix missing default name in Java PIDController (#1792)
df12fc2a8 Java cleanups (#1776)
39561751f Update GradleVSCode version (#1786)
37d316aa0 Add C++20 std::math constants shim (#1788)
dd4310959 Deprecate frc/WPILib.h (#1779)
823174f30 Update native utils to 2020.0.4 (#1783)
37c695266 Squelch -Wdeprecated-copy for Eigen with GCC >= 9
04c9b000f Revert "Fix build of Eigen 3.3.7 with GCC 9"
ca3e71e21 wpiutil: Fix Process::Spawn() (#1778)
d946d5a2b Fix Eigen compilation errors and add tests (#1777)
8b1b9ac75 Fix build of Eigen 3.3.7 with GCC 9
2f680ba99 Add Eigen linear algebra library
a885db7d4 Make MotorEncoderTest use LinearFilter (#1775)
ee2410169 Add geometry classes (#1766)
48fe54271 Add HALSIM_SetSendError implementation (#1773)
dff58c87f Fix unused warning in release build (#1771)
dde61aad3 Remove TimerEventHandler typedef from Notifier class (#1767)
0f6ef80ab Add RobotState#IsEStopped and DriverStation#IsEStopped (#952)
e48886187 Move unit tests from integration test suite (#1170)
dffa1a5cb Make null checks more descriptive (#1688)
fe59d854d Notifier: add null check (#1684)
10731f3d6 Update uv Udp wrapper for latest features
89f7b72b6 Update libuv to 1.30.1 release
85f2f8740 wpiutil: Add unique_function (#1761)
73ec94078 Remove SampleRobot (#1658)
62be0392b Replace std::lock_guard and std::lock with std::scoped_lock (#1758)
24d31df55 Make sure move constructor is generated for TrapezoidProfile (#1757)
841ef5d73 Remove template types from lock RAII wrapper usages (#1756)
e582518ba Fix some move constructors (#1754)
8757bc471 Remove pre-C++17 shims (#1752)
ea9512977 Add replacement PIDController class (#1300)
9b798d228 Add TrapezoidProfile class (#1673)
804926fb5 Unconditionally skip athena builds for sim (#1748)
118e9d29d Add C++14 units library (#1749)
c705953d7 Add usage reporting to LinearFilter (#1750)
852d1b9ca Don't cross-build gazebo for raspbian (#1747)
eedb3a1ad Fix GCC 9 warnings (#1730)
60dce66a4 Remove wpi::ArrayRef std::initializer_list constructor (#1745)
9e19b29c3 Use base azure image for primary wpilib build (#1744)
299425071 Update jni library, fix cross builds of the jni symbol check (#1742)
a6b0e9b85 Only disable execution of cross compile google tests (#1741)
3c2093119 Use docker container to run wpiformat (#1740)
5fe2eebce Revert "Don't build halsim_gazebo on raspbian (#1737)" (#1743)
4b1b92bb7 Replace wpi::optional with C++17 std::optional (#1732)
0fbb0d989 Update to 2020 compilers (#1733)
2dc94e605 Disable google tests on cross compilers (#1738)
d9cb57a42 Don't build halsim_gazebo on raspbian (#1737)
f7cfdd7ce Replace crlf line endings with lf (#1731)
b6d5d90d9 Add JaCoCo Support (#1734)
c7ab2baa6 Add way to disable the jni check tasks from a property (#1736)
0c45c5b7e Fix skip athena and skip raspbian flags (#1735)
3dfb01d45 Update to new Native Utils (#1696)
30e936837 Clean up LinearDigitalFilter class (#782)
311e2de4c Remove deprecated Joystick constants (#1715)
c08fd6682 Update CAN manufacturer list (#1706)
258bba0c2 ErrorBase and WPIError improvements (#1727)
372ca4f45 cmake: Enable googletest unit tests (#1720)
223d47af0 HALSIM: support mocking of HAL_SendError() (#1728)
55cb683db Change compiler flags to C++17 (#1723)
ee8a33c56 wpiutil: SafeThread: Add thread id, support getting shared_ptr (#1722)
61426d08d wpiutil: Signal: make operator() const (#1721)
b630b63ef Remove functions in LiveWindow deprecated since 2018 (#1716)
1d0c05d4f Styleguide fixes for #1718 (#1719)
f07569df1 Fix newer GCC/clang compiler warnings (#1718)
0120f3124 C++ SPI: Fix SetClockRate to take int (#1717)
c2829ed98 Configure gradle to ignore unresolved headers (#1711)
221e66f46 Allow disabling static init of JNI libraries (#1672)
738852e11 cmake: Add cross toolchain files for Rio and Pi (#1710)
27b697b08 Remove frc directory include shims (#1714)
9e45373a7 Remove functions and classes deprecated for 2018 season (#1059)
eeb1025ac SPI: Report port as instance for usage reporting (#1704)
bc6f1e246 Windows compiler options improvements (#1709)
bb48ae391 cmake: Move example programs into folders (#1654)
221011494 Update for C++17 and fix MSVC warnings (#1694)
fb1239a2a Add raw sources and sinks to cscore (#1670)
7de947734 Add lambda overloads for interrupts (#1636)
90957aeea Move libuv to its own subfolder in build (#1661)
47aae502a Styleguide fixes (#1702)
0bff98b5e Correct DifferentialDrive::ArcadeDrive param docs (#1698)
b52e40b80 Allow widgets to be added by passing value suppliers (#1690)
4a00cd77b Add usage reporting for the Shuffleboard API (#1685)
e25e515f2  Publish artifacts on azure (#1678)
322ef9b96 Force Java 11, fix javadoc generation (#1695)
d42ef5df0 Fix Watchdog print formatting (#1693)
f432f65be Update copyright year in license to 2019 (#1524)
1726b77ac wpiutil: uv: Remove copy from SimpleBufferPool (#1680)
620bec9ca wpiutil: uv: Add LoopClosing status to Handle (#1647)
7cd6e2e7f UsbCamera: Solve race in windows initialization (#1638)
7732836bd Completely disable watchdog tests on mac (#1679)
698edfda9 Remove framework load, disable mac timeout test (#1676)
1c454b000 Add Shuffleboard calls to IterativeRobotBase in C++ (#1607)
f42905b32 Include missing headers in HAL.h (#1660)
bdc822fad Only generate passthrough URLs for RoboRIO (#1624)
d3affb16b Make failure of HAL_GetFPGATime() more descriptive (#1633)
2de3bf7f5 Update LLVM from stable upstream (#1653)
3cf4f38f5 Fix build on macos10.14.4 (#1648)
4e0c10f48 Fix CAN Clean using wrong ID (#1668)
3b0631324 Fix Gray to BGR conversion in CameraServer (#1665)
6cd1c73ef Fix GUID comparison creating weird symbol (#1659)
063bbab6f MavenArtifacts.md: update links to HTTPS (#1674)
aab4c494d Fix type in build.gradle (#1604)
bf46af260 Disable extraneous data warnings in libjpeg (#1630)
655763a9a Limit length of message sent to DS SendError call (#1618)
a095ec2d8 Fix linker errors with free functions in Threads.h (#1625)
12ab035aa Fix receive side of LabVIEW USB streams (#1621)

Change-Id: Ibd382e1a48925c200850cf90a8121e35c0fcffe3
git-subtree-dir: third_party/allwpilib_2019
git-subtree-split: c36bbcc9a9095489fc078229db4fba3ecd0f9b78
diff --git a/ntcore/CMakeLists.txt b/ntcore/CMakeLists.txt
index 47e2264..1852702 100644
--- a/ntcore/CMakeLists.txt
+++ b/ntcore/CMakeLists.txt
@@ -1,5 +1,8 @@
 project(ntcore)
 
+include(CompileWarnings)
+include(AddTest)
+
 file(GLOB
     ntcore_native_src src/main/native/cpp/*.cpp
     ntcore_native_src src/main/native/cpp/networktables/*.cpp
@@ -9,6 +12,7 @@
 target_include_directories(ntcore PUBLIC
                 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
                             $<INSTALL_INTERFACE:${include_dest}/ntcore>)
+wpilib_target_warnings(ntcore)
 target_link_libraries(ntcore PUBLIC wpiutil)
 
 set_property(TARGET ntcore PROPERTY FOLDER "libraries")
@@ -16,13 +20,14 @@
 install(TARGETS ntcore EXPORT ntcore DESTINATION "${main_lib_dest}")
 install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/ntcore")
 
-if (MSVC)
+if (MSVC OR FLAT_INSTALL_WPILIB)
     set (ntcore_config_dir ${wpilib_dest})
 else()
     set (ntcore_config_dir share/ntcore)
 endif()
 
-install(FILES ntcore-config.cmake DESTINATION ${ntcore_config_dir})
+configure_file(ntcore-config.cmake.in ${CMAKE_BINARY_DIR}/ntcore-config.cmake )
+install(FILES ${CMAKE_BINARY_DIR}/ntcore-config.cmake DESTINATION ${ntcore_config_dir})
 install(EXPORT ntcore DESTINATION ${ntcore_config_dir})
 
 # Java bindings
@@ -51,6 +56,7 @@
     set_property(TARGET ntcore_jar PROPERTY FOLDER "java")
 
     add_library(ntcorejni ${ntcore_jni_src})
+    wpilib_target_warnings(ntcorejni)
     target_link_libraries(ntcorejni PUBLIC ntcore wpiutil)
 
     set_property(TARGET ntcorejni PROPERTY FOLDER "libraries")
@@ -70,3 +76,9 @@
     install(TARGETS ntcorejni EXPORT ntcorejni DESTINATION "${main_lib_dest}")
 
 endif()
+
+if (WITH_TESTS)
+    wpilib_add_test(ntcore src/test/native/cpp)
+    target_include_directories(ntcore_test PRIVATE src/main/native/cpp)
+    target_link_libraries(ntcore_test ntcore gmock_main)
+endif()
diff --git a/ntcore/build.gradle b/ntcore/build.gradle
index 659b0f9..5739b71 100644
--- a/ntcore/build.gradle
+++ b/ntcore/build.gradle
@@ -5,45 +5,29 @@
 
 apply from: "${rootDir}/shared/jni/setupBuild.gradle"
 
-model {
-    // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
-    // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
-    // where some extra symbols are added that cannot be resolved at link time. This configuration
-    // lets you specify specific symbols to exlude from exporting.
-    exportsConfigs {
-        ntcore(ExportsConfig) {
-            x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
-                                 '_CT??_R0?AVbad_cast',
-                                 '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
-                                 '_TI5?AVfailure']
-            x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
-                                 '_CT??_R0?AVbad_cast',
-                                 '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
-                                 '_TI5?AVfailure']
+nativeUtils.exportsConfigs {
+    ntcore {
+        x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
+                            '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
+                            '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
+                            '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
+        x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
+                            '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
+                            '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
+                            '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
+    }
+    ntcoreJNI {
+        x86SymbolFilter = { symbols ->
+            symbols.removeIf({ !it.startsWith('NT_') })
         }
-        ntcoreJNI(ExportsConfig) {
-            x86SymbolFilter = { symbols ->
-                def retList = []
-                symbols.each { symbol ->
-                    if (symbol.startsWith('NT_')) {
-                        retList << symbol
-                    }
-                }
-                return retList
-            }
-            x64SymbolFilter = { symbols ->
-                def retList = []
-                symbols.each { symbol ->
-                    if (symbol.startsWith('NT_')) {
-                        retList << symbol
-                    }
-                }
-                return retList
-            }
+        x64SymbolFilter = { symbols ->
+            symbols.removeIf({ !it.startsWith('NT_') })
         }
     }
 }
 
-pmdMain {
-    pmdMain.enabled = false
+if (!project.hasProperty('skipPMD')) {
+    pmdMain {
+        pmdMain.enabled = false
+    }
 }
diff --git a/ntcore/ntcore-config.cmake b/ntcore/ntcore-config.cmake
deleted file mode 100644
index 6be1dda..0000000
--- a/ntcore/ntcore-config.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-include(CMakeFindDependencyMacro)

-find_dependency(wpiutil)

-

-get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)

-include(${SELF_DIR}/ntcore.cmake)

diff --git a/ntcore/ntcore-config.cmake.in b/ntcore/ntcore-config.cmake.in
new file mode 100644
index 0000000..fb677b3
--- /dev/null
+++ b/ntcore/ntcore-config.cmake.in
@@ -0,0 +1,5 @@
+include(CMakeFindDependencyMacro)
+@FILENAME_DEP_REPLACE@
+@WPIUTIL_DEP_REPLACE@
+
+include(${SELF_DIR}/ntcore.cmake)
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTable.java b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTable.java
index 1cd21bf..ad25f23 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTable.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTable.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -218,7 +218,7 @@
     final int prefixLen = m_path.length() + 1;
     final NetworkTable parent = this;
 
-    return m_inst.addEntryListener(m_pathWithSep, new Consumer<EntryNotification>() {
+    return m_inst.addEntryListener(m_pathWithSep, new Consumer<>() {
       final Set<String> m_notifiedTables = new HashSet<>();
 
       @Override
@@ -358,7 +358,7 @@
    *
    * @param key the key
    * @param defaultValue the default value to set if key doesn't exist.
-   * @returns False if the table key exists with a different type
+   * @return False if the table key exists with a different type
    */
   boolean setDefaultValue(String key, NetworkTableValue defaultValue) {
     return getEntry(key).setDefaultValue(defaultValue);
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableEntry.java b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableEntry.java
index 63ed984..6eea5ca 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableEntry.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableEntry.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -280,7 +280,7 @@
       switch (((NetworkTableValue) defaultValue).getType()) {
         case kBoolean:
           return NetworkTablesJNI.setDefaultBoolean(m_handle, time,
-              ((Boolean) otherValue).booleanValue());
+              (Boolean) otherValue);
         case kDouble:
           return NetworkTablesJNI.setDefaultDouble(m_handle, time,
               ((Number) otherValue).doubleValue());
@@ -438,7 +438,7 @@
       Object otherValue = ((NetworkTableValue) value).getValue();
       switch (((NetworkTableValue) value).getType()) {
         case kBoolean:
-          return NetworkTablesJNI.setBoolean(m_handle, time, ((Boolean) otherValue).booleanValue(),
+          return NetworkTablesJNI.setBoolean(m_handle, time, (Boolean) otherValue,
               false);
         case kDouble:
           return NetworkTablesJNI.setDouble(m_handle, time, ((Number) otherValue).doubleValue(),
@@ -612,7 +612,7 @@
       Object otherValue = ((NetworkTableValue) value).getValue();
       switch (((NetworkTableValue) value).getType()) {
         case kBoolean:
-          NetworkTablesJNI.setBoolean(m_handle, time, ((Boolean) otherValue).booleanValue(), true);
+          NetworkTablesJNI.setBoolean(m_handle, time, (Boolean) otherValue, true);
           return;
         case kDouble:
           NetworkTablesJNI.setDouble(m_handle, time, ((Number) otherValue).doubleValue(), true);
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableInstance.java b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableInstance.java
index 2564f70..29813a5 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableInstance.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableInstance.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -60,11 +60,6 @@
     m_handle = handle;
   }
 
-  @Deprecated
-  public void free() {
-    close();
-  }
-
   /**
    * Destroys the instance (if created by {@link #create()}).
    */
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableValue.java b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableValue.java
index e1179ea..eb7e2c2 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableValue.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTableValue.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -153,7 +153,7 @@
     if (m_type != NetworkTableType.kBoolean) {
       throw new ClassCastException("cannot convert " + m_type + " to boolean");
     }
-    return ((Boolean) m_value).booleanValue();
+    return (Boolean) m_value;
   }
 
   /**
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java
index 1d736fc..d24f066 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -9,6 +9,7 @@
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import edu.wpi.first.wpiutil.RuntimeLoader;
 
@@ -16,8 +17,20 @@
   static boolean libraryLoaded = false;
   static RuntimeLoader<NetworkTablesJNI> loader = null;
 
+  public static class Helper {
+    private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
+
+    public static boolean getExtractOnStaticLoad() {
+      return extractOnStaticLoad.get();
+    }
+
+    public static void setExtractOnStaticLoad(boolean load) {
+      extractOnStaticLoad.set(load);
+    }
+  }
+
   static {
-    if (!libraryLoaded) {
+    if (Helper.getExtractOnStaticLoad()) {
       try {
         loader = new RuntimeLoader<>("ntcorejni", RuntimeLoader.getDefaultExtractionRoot(), NetworkTablesJNI.class);
         loader.loadLibrary();
@@ -29,6 +42,18 @@
     }
   }
 
+  /**
+   * Force load the library.
+   */
+  public static synchronized void forceLoad() throws IOException {
+    if (libraryLoaded) {
+      return;
+    }
+    loader = new RuntimeLoader<>("ntcorejni", RuntimeLoader.getDefaultExtractionRoot(), NetworkTablesJNI.class);
+    loader.loadLibrary();
+    libraryLoaded = true;
+  }
+
   public static native int getDefaultInstance();
   public static native int createInstance();
   public static native void destroyInstance(int inst);
diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/RpcCall.java b/ntcore/src/main/java/edu/wpi/first/networktables/RpcCall.java
index 1b377f6..b9148c9 100644
--- a/ntcore/src/main/java/edu/wpi/first/networktables/RpcCall.java
+++ b/ntcore/src/main/java/edu/wpi/first/networktables/RpcCall.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -22,11 +22,6 @@
     m_call = call;
   }
 
-  @Deprecated
-  public void free() {
-    close();
-  }
-
   /**
    * Cancels the result if no other action taken.
    */
diff --git a/ntcore/src/main/native/cpp/CallbackManager.h b/ntcore/src/main/native/cpp/CallbackManager.h
index 0fd9617..2d9b11d 100644
--- a/ntcore/src/main/native/cpp/CallbackManager.h
+++ b/ntcore/src/main/native/cpp/CallbackManager.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -74,7 +74,7 @@
   struct Poller {
     void Terminate() {
       {
-        std::lock_guard<wpi::mutex> lock(poll_mutex);
+        std::scoped_lock lock(poll_mutex);
         terminating = true;
       }
       poll_cond.notify_all();
@@ -94,7 +94,7 @@
     auto poller = m_pollers[poller_uid];
     if (!poller) return;
     {
-      std::lock_guard<wpi::mutex> lock(poller->poll_mutex);
+      std::scoped_lock lock(poller->poll_mutex);
       poller->poll_queue.emplace(std::forward<Args>(args)...);
     }
     poller->poll_cond.notify_one();
@@ -104,7 +104,7 @@
 template <typename Derived, typename TUserInfo, typename TListenerData,
           typename TNotifierData>
 void CallbackThread<Derived, TUserInfo, TListenerData, TNotifierData>::Main() {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   while (m_active) {
     while (m_queue.empty()) {
       m_cond.wait(lock);
@@ -138,7 +138,8 @@
           if (!listener) continue;
           if (!static_cast<Derived*>(this)->Matches(listener, item.second))
             continue;
-          static_cast<Derived*>(this)->SetListener(&item.second, i);
+          static_cast<Derived*>(this)->SetListener(&item.second,
+                                                   static_cast<unsigned>(i));
           if (listener.callback) {
             lock.unlock();
             static_cast<Derived*>(this)->DoCallback(listener.callback,
@@ -240,7 +241,7 @@
       if (!poller) return infos;
     }
 
-    std::unique_lock<wpi::mutex> lock(poller->poll_mutex);
+    std::unique_lock lock(poller->poll_mutex);
     auto timeout_time = std::chrono::steady_clock::now() +
                         std::chrono::duration<double>(timeout);
     *timed_out = false;
@@ -285,7 +286,7 @@
     }
 
     {
-      std::lock_guard<wpi::mutex> lock(poller->poll_mutex);
+      std::scoped_lock lock(poller->poll_mutex);
       poller->cancelling = true;
     }
     poller->poll_cond.notify_one();
diff --git a/ntcore/src/main/native/cpp/Dispatcher.cpp b/ntcore/src/main/native/cpp/Dispatcher.cpp
index ea54fe4..8164f45 100644
--- a/ntcore/src/main/native/cpp/Dispatcher.cpp
+++ b/ntcore/src/main/native/cpp/Dispatcher.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -119,7 +119,7 @@
     const Twine& persist_filename,
     std::unique_ptr<wpi::NetworkAcceptor> acceptor) {
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     if (m_active) return;
     m_active = true;
   }
@@ -151,7 +151,7 @@
 
 void DispatcherBase::StartClient() {
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     if (m_active) return;
     m_active = true;
   }
@@ -170,7 +170,7 @@
 
   // wake up client thread with a reconnect
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     m_client_connector = nullptr;
   }
   ClientReconnect();
@@ -184,7 +184,7 @@
 
   std::vector<std::shared_ptr<INetworkConnection>> conns;
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     conns.swap(m_connections);
   }
 
@@ -202,14 +202,14 @@
 }
 
 void DispatcherBase::SetIdentity(const Twine& name) {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   m_identity = name.str();
 }
 
 void DispatcherBase::Flush() {
   auto now = std::chrono::steady_clock::now();
   {
-    std::lock_guard<wpi::mutex> lock(m_flush_mutex);
+    std::scoped_lock lock(m_flush_mutex);
     // don't allow flushes more often than every 10 ms
     if ((now - m_last_flush) < std::chrono::milliseconds(10)) return;
     m_last_flush = now;
@@ -222,7 +222,7 @@
   std::vector<ConnectionInfo> conns;
   if (!m_active) return conns;
 
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   for (auto& conn : m_connections) {
     if (conn->state() != NetworkConnection::kActive) continue;
     conns.emplace_back(conn->info());
@@ -234,7 +234,7 @@
 bool DispatcherBase::IsConnected() const {
   if (!m_active) return false;
 
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   for (auto& conn : m_connections) {
     if (conn->state() == NetworkConnection::kActive) return true;
   }
@@ -245,7 +245,7 @@
 unsigned int DispatcherBase::AddListener(
     std::function<void(const ConnectionNotification& event)> callback,
     bool immediate_notify) const {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   unsigned int uid = m_notifier.Add(callback);
   // perform immediate notifications
   if (immediate_notify) {
@@ -259,7 +259,7 @@
 
 unsigned int DispatcherBase::AddPolledListener(unsigned int poller_uid,
                                                bool immediate_notify) const {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   unsigned int uid = m_notifier.AddPolled(poller_uid);
   // perform immediate notifications
   if (immediate_notify) {
@@ -272,17 +272,17 @@
 }
 
 void DispatcherBase::SetConnector(Connector connector) {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   m_client_connector = std::move(connector);
 }
 
 void DispatcherBase::SetConnectorOverride(Connector connector) {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   m_client_connector_override = std::move(connector);
 }
 
 void DispatcherBase::ClearConnectorOverride() {
-  std::lock_guard<wpi::mutex> lock(m_user_mutex);
+  std::scoped_lock lock(m_user_mutex);
   m_client_connector_override = nullptr;
 }
 
@@ -319,11 +319,11 @@
     }
 
     {
-      std::lock_guard<wpi::mutex> user_lock(m_user_mutex);
+      std::scoped_lock user_lock(m_user_mutex);
       bool reconnect = false;
 
       if (++count > 10) {
-        DEBUG("dispatch running " << m_connections.size() << " connections");
+        DEBUG0("dispatch running " << m_connections.size() << " connections");
         count = 0;
       }
 
@@ -350,7 +350,7 @@
 void DispatcherBase::QueueOutgoing(std::shared_ptr<Message> msg,
                                    INetworkConnection* only,
                                    INetworkConnection* except) {
-  std::lock_guard<wpi::mutex> user_lock(m_user_mutex);
+  std::scoped_lock user_lock(m_user_mutex);
   for (auto& conn : m_connections) {
     if (conn.get() == except) continue;
     if (only && conn.get() != only) continue;
@@ -379,8 +379,8 @@
       m_networkMode = NT_NET_MODE_NONE;
       return;
     }
-    DEBUG("server: client connection from " << stream->getPeerIP() << " port "
-                                            << stream->getPeerPort());
+    DEBUG0("server: client connection from " << stream->getPeerIP() << " port "
+                                             << stream->getPeerPort());
 
     // add to connections list
     using namespace std::placeholders;
@@ -392,7 +392,7 @@
         std::bind(&IStorage::ProcessIncoming, &m_storage, _1, _2,
                   std::weak_ptr<NetworkConnection>(conn)));
     {
-      std::lock_guard<wpi::mutex> lock(m_user_mutex);
+      std::scoped_lock lock(m_user_mutex);
       // reuse dead connection slots
       bool placed = false;
       for (auto& c : m_connections) {
@@ -417,7 +417,7 @@
 
     // get next server to connect to
     {
-      std::lock_guard<wpi::mutex> lock(m_user_mutex);
+      std::scoped_lock lock(m_user_mutex);
       if (m_client_connector_override) {
         connect = m_client_connector_override;
       } else {
@@ -430,16 +430,16 @@
     }
 
     // try to connect (with timeout)
-    DEBUG("client trying to connect");
+    DEBUG0("client trying to connect");
     auto stream = connect();
     if (!stream) {
       m_networkMode = NT_NET_MODE_CLIENT | NT_NET_MODE_FAILURE;
       continue;  // keep retrying
     }
-    DEBUG("client connected");
+    DEBUG0("client connected");
     m_networkMode = NT_NET_MODE_CLIENT;
 
-    std::unique_lock<wpi::mutex> lock(m_user_mutex);
+    std::unique_lock lock(m_user_mutex);
     using namespace std::placeholders;
     auto conn = std::make_shared<NetworkConnection>(
         ++m_connections_uid, std::move(stream), m_notifier, m_logger,
@@ -469,19 +469,19 @@
   // get identity
   std::string self_id;
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     self_id = m_identity;
   }
 
   // send client hello
-  DEBUG("client: sending hello");
+  DEBUG0("client: sending hello");
   send_msgs(Message::ClientHello(self_id));
 
   // wait for response
   auto msg = get_msg();
   if (!msg) {
     // disconnected, retry
-    DEBUG("client: server disconnected before first response");
+    DEBUG0("client: server disconnected before first response");
     return false;
   }
 
@@ -505,7 +505,7 @@
   for (;;) {
     if (!msg) {
       // disconnected, retry
-      DEBUG("client: server disconnected during initial entries");
+      DEBUG0("client: server disconnected during initial entries");
       return false;
     }
     DEBUG4("received init str=" << msg->str() << " id=" << msg->id()
@@ -518,9 +518,9 @@
     }
     if (!msg->Is(Message::kEntryAssign)) {
       // unexpected message
-      DEBUG("client: received message ("
-            << msg->type()
-            << ") other than entry assignment during initial handshake");
+      DEBUG0("client: received message ("
+             << msg->type()
+             << ") other than entry assignment during initial handshake");
       return false;
     }
     incoming.emplace_back(std::move(msg));
@@ -549,18 +549,18 @@
   // Wait for the client to send us a hello.
   auto msg = get_msg();
   if (!msg) {
-    DEBUG("server: client disconnected before sending hello");
+    DEBUG0("server: client disconnected before sending hello");
     return false;
   }
   if (!msg->Is(Message::kClientHello)) {
-    DEBUG("server: client initial message was not client hello");
+    DEBUG0("server: client initial message was not client hello");
     return false;
   }
 
   // Check that the client requested version is not too high.
   unsigned int proto_rev = msg->id();
   if (proto_rev > 0x0300) {
-    DEBUG("server: client requested proto > 0x0300");
+    DEBUG0("server: client requested proto > 0x0300");
     send_msgs(Message::ProtoUnsup());
     return false;
   }
@@ -568,7 +568,7 @@
   if (proto_rev >= 0x0300) conn.set_remote_id(msg->str());
 
   // Set the proto version to the client requested version
-  DEBUG("server: client protocol " << proto_rev);
+  DEBUG0("server: client protocol " << proto_rev);
   conn.set_proto_rev(proto_rev);
 
   // Send initial set of assignments
@@ -576,7 +576,7 @@
 
   // Start with server hello.  TODO: initial connection flag
   if (proto_rev >= 0x0300) {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     outgoing.emplace_back(Message::ServerHello(0u, m_identity));
   }
 
@@ -587,7 +587,7 @@
   outgoing.emplace_back(Message::ServerHelloDone());
 
   // Batch transmit
-  DEBUG("server: sending initial assignments");
+  DEBUG0("server: sending initial assignments");
   send_msgs(outgoing);
 
   // In proto rev 3.0 and later, the handshake concludes with a client hello
@@ -601,7 +601,7 @@
     for (;;) {
       if (!msg) {
         // disconnected, retry
-        DEBUG("server: disconnected waiting for initial entries");
+        DEBUG0("server: disconnected waiting for initial entries");
         return false;
       }
       if (msg->Is(Message::kClientHelloDone)) break;
@@ -612,9 +612,9 @@
       }
       if (!msg->Is(Message::kEntryAssign)) {
         // unexpected message
-        DEBUG("server: received message ("
-              << msg->type()
-              << ") other than entry assignment during initial handshake");
+        DEBUG0("server: received message ("
+               << msg->type()
+               << ") other than entry assignment during initial handshake");
         return false;
       }
       incoming.push_back(msg);
@@ -633,7 +633,7 @@
 void DispatcherBase::ClientReconnect(unsigned int proto_rev) {
   if ((m_networkMode & NT_NET_MODE_SERVER) != 0) return;
   {
-    std::lock_guard<wpi::mutex> lock(m_user_mutex);
+    std::scoped_lock lock(m_user_mutex);
     m_reconnect_proto_rev = proto_rev;
     m_do_reconnect = true;
   }
diff --git a/ntcore/src/main/native/cpp/DsClient.cpp b/ntcore/src/main/native/cpp/DsClient.cpp
index 8b97be7..32a756f 100644
--- a/ntcore/src/main/native/cpp/DsClient.cpp
+++ b/ntcore/src/main/native/cpp/DsClient.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -63,7 +63,7 @@
         std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
     unsigned int port;
     {
-      std::unique_lock<wpi::mutex> lock(m_mutex);
+      std::unique_lock lock(m_mutex);
       m_cond.wait_until(lock, timeout_time, [&] { return !m_active; });
       port = m_port;
     }
diff --git a/ntcore/src/main/native/cpp/EntryNotifier.cpp b/ntcore/src/main/native/cpp/EntryNotifier.cpp
index 5fde687..c8f8d76 100644
--- a/ntcore/src/main/native/cpp/EntryNotifier.cpp
+++ b/ntcore/src/main/native/cpp/EntryNotifier.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -82,8 +82,8 @@
   // optimization: don't generate needless local queue entries if we have
   // no local listeners (as this is a common case on the server side)
   if ((flags & NT_NOTIFY_LOCAL) != 0 && !m_local_notifiers) return;
-  DEBUG("notifying '" << name << "' (local=" << local_id
-                      << "), flags=" << flags);
+  DEBUG0("notifying '" << name << "' (local=" << local_id
+                       << "), flags=" << flags);
   Send(only_listener, 0, Handle(m_inst, local_id, Handle::kEntry).handle(),
        name, value, flags);
 }
diff --git a/ntcore/src/main/native/cpp/InstanceImpl.cpp b/ntcore/src/main/native/cpp/InstanceImpl.cpp
index 3b34292..cd35fb0 100644
--- a/ntcore/src/main/native/cpp/InstanceImpl.cpp
+++ b/ntcore/src/main/native/cpp/InstanceImpl.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -43,7 +43,7 @@
   }
 
   // slow path
-  std::lock_guard<wpi::mutex> lock(s_mutex);
+  std::scoped_lock lock(s_mutex);
 
   // static fast-path block
   if (static_cast<unsigned int>(inst) <
@@ -66,7 +66,7 @@
   if (inst >= 0) return inst;
 
   // slow path
-  std::lock_guard<wpi::mutex> lock(s_mutex);
+  std::scoped_lock lock(s_mutex);
 
   // double-check
   inst = s_default;
@@ -79,7 +79,7 @@
 }
 
 int InstanceImpl::Alloc() {
-  std::lock_guard<wpi::mutex> lock(s_mutex);
+  std::scoped_lock lock(s_mutex);
   return AllocImpl();
 }
 
@@ -96,7 +96,7 @@
 }
 
 void InstanceImpl::Destroy(int inst) {
-  std::lock_guard<wpi::mutex> lock(s_mutex);
+  std::scoped_lock lock(s_mutex);
   if (inst < 0 || static_cast<unsigned int>(inst) >= s_instances.size()) return;
 
   if (static_cast<unsigned int>(inst) <
diff --git a/ntcore/src/main/native/cpp/Log.h b/ntcore/src/main/native/cpp/Log.h
index b8a3daf..eba8f04 100644
--- a/ntcore/src/main/native/cpp/Log.h
+++ b/ntcore/src/main/native/cpp/Log.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -17,7 +17,7 @@
 #define WARNING(x) WPI_WARNING(m_logger, x)
 #define INFO(x) WPI_INFO(m_logger, x)
 
-#define DEBUG(x) WPI_DEBUG(m_logger, x)
+#define DEBUG0(x) WPI_DEBUG(m_logger, x)
 #define DEBUG1(x) WPI_DEBUG1(m_logger, x)
 #define DEBUG2(x) WPI_DEBUG2(m_logger, x)
 #define DEBUG3(x) WPI_DEBUG3(m_logger, x)
diff --git a/ntcore/src/main/native/cpp/NetworkConnection.cpp b/ntcore/src/main/native/cpp/NetworkConnection.cpp
index cb1e333..8cc8312 100644
--- a/ntcore/src/main/native/cpp/NetworkConnection.cpp
+++ b/ntcore/src/main/native/cpp/NetworkConnection.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -49,7 +49,7 @@
   while (!m_outgoing.empty()) m_outgoing.pop();
   // reset shutdown flags
   {
-    std::lock_guard<wpi::mutex> lock(m_shutdown_mutex);
+    std::scoped_lock lock(m_shutdown_mutex);
     m_read_shutdown = false;
     m_write_shutdown = false;
   }
@@ -68,7 +68,7 @@
   m_outgoing.push(Outgoing());
   // wait for threads to terminate, with timeout
   if (m_write_thread.joinable()) {
-    std::unique_lock<wpi::mutex> lock(m_shutdown_mutex);
+    std::unique_lock lock(m_shutdown_mutex);
     auto timeout_time =
         std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
     if (m_write_shutdown_cv.wait_until(lock, timeout_time,
@@ -78,7 +78,7 @@
       m_write_thread.detach();  // timed out, detach it
   }
   if (m_read_thread.joinable()) {
-    std::unique_lock<wpi::mutex> lock(m_shutdown_mutex);
+    std::unique_lock lock(m_shutdown_mutex);
     auto timeout_time =
         std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
     if (m_read_shutdown_cv.wait_until(lock, timeout_time,
@@ -104,12 +104,12 @@
 }
 
 NetworkConnection::State NetworkConnection::state() const {
-  std::lock_guard<wpi::mutex> lock(m_state_mutex);
+  std::scoped_lock lock(m_state_mutex);
   return m_state;
 }
 
 void NetworkConnection::set_state(State state) {
-  std::lock_guard<wpi::mutex> lock(m_state_mutex);
+  std::scoped_lock lock(m_state_mutex);
   // Don't update state any more once we've died
   if (m_state == kDead) return;
   // One-shot notify state changes
@@ -121,12 +121,12 @@
 }
 
 std::string NetworkConnection::remote_id() const {
-  std::lock_guard<wpi::mutex> lock(m_remote_id_mutex);
+  std::scoped_lock lock(m_remote_id_mutex);
   return m_remote_id;
 }
 
 void NetworkConnection::set_remote_id(StringRef remote_id) {
-  std::lock_guard<wpi::mutex> lock(m_remote_id_mutex);
+  std::scoped_lock lock(m_remote_id_mutex);
   m_remote_id = remote_id;
 }
 
@@ -140,7 +140,8 @@
                      decoder.set_proto_rev(m_proto_rev);
                      auto msg = Message::Read(decoder, m_get_entry_type);
                      if (!msg && decoder.error())
-                       DEBUG("error reading in handshake: " << decoder.error());
+                       DEBUG0(
+                           "error reading in handshake: " << decoder.error());
                      return msg;
                    },
                    [&](wpi::ArrayRef<std::shared_ptr<Message>> msgs) {
@@ -177,7 +178,7 @@
 done:
   // use condition variable to signal thread shutdown
   {
-    std::lock_guard<wpi::mutex> lock(m_shutdown_mutex);
+    std::scoped_lock lock(m_shutdown_mutex);
     m_read_shutdown = true;
     m_read_shutdown_cv.notify_one();
   }
@@ -214,14 +215,14 @@
 
   // use condition variable to signal thread shutdown
   {
-    std::lock_guard<wpi::mutex> lock(m_shutdown_mutex);
+    std::scoped_lock lock(m_shutdown_mutex);
     m_write_shutdown = true;
     m_write_shutdown_cv.notify_one();
   }
 }
 
 void NetworkConnection::QueueOutgoing(std::shared_ptr<Message> msg) {
-  std::lock_guard<wpi::mutex> lock(m_pending_mutex);
+  std::scoped_lock lock(m_pending_mutex);
 
   // Merge with previous.  One case we don't combine: delete/assign loop.
   switch (msg->type()) {
@@ -317,7 +318,7 @@
 }
 
 void NetworkConnection::PostOutgoing(bool keep_alive) {
-  std::lock_guard<wpi::mutex> lock(m_pending_mutex);
+  std::scoped_lock lock(m_pending_mutex);
   auto now = std::chrono::steady_clock::now();
   if (m_pending_outgoing.empty()) {
     if (!keep_alive) return;
diff --git a/ntcore/src/main/native/cpp/RpcServer.h b/ntcore/src/main/native/cpp/RpcServer.h
index 5afe62a..cca490f 100644
--- a/ntcore/src/main/native/cpp/RpcServer.h
+++ b/ntcore/src/main/native/cpp/RpcServer.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -64,7 +64,7 @@
     RpcIdPair lookup_uid{local_id, call_uid};
     callback(data);
     {
-      std::lock_guard<wpi::mutex> lock(m_mutex);
+      std::scoped_lock lock(m_mutex);
       auto i = m_response_map.find(lookup_uid);
       if (i != m_response_map.end()) {
         // post an empty response and erase it
diff --git a/ntcore/src/main/native/cpp/Storage.cpp b/ntcore/src/main/native/cpp/Storage.cpp
index 0d8d467..cf0d26c 100644
--- a/ntcore/src/main/native/cpp/Storage.cpp
+++ b/ntcore/src/main/native/cpp/Storage.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -30,7 +30,7 @@
 }
 
 void Storage::SetDispatcher(IDispatcher* dispatcher, bool server) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   m_dispatcher = dispatcher;
   m_server = server;
 }
@@ -38,7 +38,7 @@
 void Storage::ClearDispatcher() { m_dispatcher = nullptr; }
 
 NT_Type Storage::GetMessageEntryType(unsigned int id) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   if (id >= m_idmap.size()) return NT_UNASSIGNED;
   Entry* entry = m_idmap[id];
   if (!entry || !entry->value) return NT_UNASSIGNED;
@@ -86,7 +86,7 @@
 
 void Storage::ProcessIncomingEntryAssign(std::shared_ptr<Message> msg,
                                          INetworkConnection* conn) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   unsigned int id = msg->id();
   StringRef name = msg->str();
   Entry* entry;
@@ -110,7 +110,7 @@
       // ignore arbitrary entry assignments
       // this can happen due to e.g. assignment to deleted entry
       lock.unlock();
-      DEBUG("server: received assignment to unknown entry");
+      DEBUG0("server: received assignment to unknown entry");
       return;
     }
     entry = m_idmap[id];
@@ -118,7 +118,7 @@
     // clients simply accept new assignments
     if (id == 0xffff) {
       lock.unlock();
-      DEBUG("client: received entry assignment request?");
+      DEBUG0("client: received entry assignment request?");
       return;
     }
     if (id >= m_idmap.size()) m_idmap.resize(id + 1);
@@ -171,7 +171,7 @@
   // sanity check: name should match id
   if (msg->str() != entry->name) {
     lock.unlock();
-    DEBUG("entry assignment for same id with different name?");
+    DEBUG0("entry assignment for same id with different name?");
     return;
   }
 
@@ -211,13 +211,13 @@
 
 void Storage::ProcessIncomingEntryUpdate(std::shared_ptr<Message> msg,
                                          INetworkConnection* conn) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   unsigned int id = msg->id();
   if (id >= m_idmap.size() || !m_idmap[id]) {
     // ignore arbitrary entry updates;
     // this can happen due to deleted entries
     lock.unlock();
-    DEBUG("received update to unknown entry");
+    DEBUG0("received update to unknown entry");
     return;
   }
   Entry* entry = m_idmap[id];
@@ -248,13 +248,13 @@
 
 void Storage::ProcessIncomingFlagsUpdate(std::shared_ptr<Message> msg,
                                          INetworkConnection* conn) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   unsigned int id = msg->id();
   if (id >= m_idmap.size() || !m_idmap[id]) {
     // ignore arbitrary entry updates;
     // this can happen due to deleted entries
     lock.unlock();
-    DEBUG("received flags update to unknown entry");
+    DEBUG0("received flags update to unknown entry");
     return;
   }
 
@@ -272,13 +272,13 @@
 
 void Storage::ProcessIncomingEntryDelete(std::shared_ptr<Message> msg,
                                          INetworkConnection* conn) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   unsigned int id = msg->id();
   if (id >= m_idmap.size() || !m_idmap[id]) {
     // ignore arbitrary entry updates;
     // this can happen due to deleted entries
     lock.unlock();
-    DEBUG("received delete to unknown entry");
+    DEBUG0("received delete to unknown entry");
     return;
   }
 
@@ -296,7 +296,7 @@
 
 void Storage::ProcessIncomingClearEntries(std::shared_ptr<Message> msg,
                                           INetworkConnection* conn) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   // update local
   DeleteAllEntriesImpl(false);
 
@@ -312,20 +312,20 @@
 void Storage::ProcessIncomingExecuteRpc(
     std::shared_ptr<Message> msg, INetworkConnection* /*conn*/,
     std::weak_ptr<INetworkConnection> conn_weak) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (!m_server) return;  // only process on server
   unsigned int id = msg->id();
   if (id >= m_idmap.size() || !m_idmap[id]) {
     // ignore call to non-existent RPC
     // this can happen due to deleted entries
     lock.unlock();
-    DEBUG("received RPC call to unknown entry");
+    DEBUG0("received RPC call to unknown entry");
     return;
   }
   Entry* entry = m_idmap[id];
   if (!entry->value || !entry->value->IsRpc()) {
     lock.unlock();
-    DEBUG("received RPC call to non-RPC entry");
+    DEBUG0("received RPC call to non-RPC entry");
     return;
   }
   ConnectionInfo conn_info;
@@ -351,20 +351,20 @@
 
 void Storage::ProcessIncomingRpcResponse(std::shared_ptr<Message> msg,
                                          INetworkConnection* /*conn*/) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (m_server) return;  // only process on client
   unsigned int id = msg->id();
   if (id >= m_idmap.size() || !m_idmap[id]) {
     // ignore response to non-existent RPC
     // this can happen due to deleted entries
     lock.unlock();
-    DEBUG("received rpc response to unknown entry");
+    DEBUG0("received rpc response to unknown entry");
     return;
   }
   Entry* entry = m_idmap[id];
   if (!entry->value || !entry->value->IsRpc()) {
     lock.unlock();
-    DEBUG("received RPC response to non-RPC entry");
+    DEBUG0("received RPC response to non-RPC entry");
     return;
   }
   m_rpc_results.insert(std::make_pair(
@@ -374,7 +374,7 @@
 
 void Storage::GetInitialAssignments(
     INetworkConnection& conn, std::vector<std::shared_ptr<Message>>* msgs) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   conn.set_state(INetworkConnection::kSynchronized);
   for (auto& i : m_entries) {
     Entry* entry = i.getValue();
@@ -388,7 +388,7 @@
 void Storage::ApplyInitialAssignments(
     INetworkConnection& conn, wpi::ArrayRef<std::shared_ptr<Message>> msgs,
     bool /*new_server*/, std::vector<std::shared_ptr<Message>>* out_msgs) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (m_server) return;  // should not do this on server
 
   conn.set_state(INetworkConnection::kSynchronized);
@@ -404,13 +404,13 @@
   // apply assignments
   for (auto& msg : msgs) {
     if (!msg->Is(Message::kEntryAssign)) {
-      DEBUG("client: received non-entry assignment request?");
+      DEBUG0("client: received non-entry assignment request?");
       continue;
     }
 
     unsigned int id = msg->id();
     if (id == 0xffff) {
-      DEBUG("client: received entry assignment request?");
+      DEBUG0("client: received entry assignment request?");
       continue;
     }
 
@@ -476,14 +476,14 @@
 }
 
 std::shared_ptr<Value> Storage::GetEntryValue(StringRef name) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   auto i = m_entries.find(name);
   if (i == m_entries.end()) return nullptr;
   return i->getValue()->value;
 }
 
 std::shared_ptr<Value> Storage::GetEntryValue(unsigned int local_id) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return nullptr;
   return m_localmap[local_id]->value;
 }
@@ -492,7 +492,7 @@
                                    std::shared_ptr<Value> value) {
   if (name.empty()) return false;
   if (!value) return false;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   Entry* entry = GetOrNew(name);
 
   // we return early if value already exists; if types match return true
@@ -505,7 +505,7 @@
 bool Storage::SetDefaultEntryValue(unsigned int local_id,
                                    std::shared_ptr<Value> value) {
   if (!value) return false;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return false;
   Entry* entry = m_localmap[local_id].get();
 
@@ -519,7 +519,7 @@
 bool Storage::SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
   if (name.empty()) return true;
   if (!value) return true;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   Entry* entry = GetOrNew(name);
 
   if (entry->value && entry->value->type() != value->type())
@@ -532,7 +532,7 @@
 bool Storage::SetEntryValue(unsigned int local_id,
                             std::shared_ptr<Value> value) {
   if (!value) return true;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return true;
   Entry* entry = m_localmap[local_id].get();
 
@@ -595,7 +595,7 @@
 void Storage::SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value) {
   if (name.empty()) return;
   if (!value) return;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   Entry* entry = GetOrNew(name);
 
   SetEntryValueImpl(entry, value, lock, true);
@@ -604,7 +604,7 @@
 void Storage::SetEntryTypeValue(unsigned int local_id,
                                 std::shared_ptr<Value> value) {
   if (!value) return;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return;
   Entry* entry = m_localmap[local_id].get();
   if (!entry) return;
@@ -614,14 +614,14 @@
 
 void Storage::SetEntryFlags(StringRef name, unsigned int flags) {
   if (name.empty()) return;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   auto i = m_entries.find(name);
   if (i == m_entries.end()) return;
   SetEntryFlagsImpl(i->getValue(), flags, lock, true);
 }
 
 void Storage::SetEntryFlags(unsigned int id_local, unsigned int flags) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (id_local >= m_localmap.size()) return;
   SetEntryFlagsImpl(m_localmap[id_local].get(), flags, lock, true);
 }
@@ -654,27 +654,27 @@
 }
 
 unsigned int Storage::GetEntryFlags(StringRef name) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   auto i = m_entries.find(name);
   if (i == m_entries.end()) return 0;
   return i->getValue()->flags;
 }
 
 unsigned int Storage::GetEntryFlags(unsigned int local_id) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return 0;
   return m_localmap[local_id]->flags;
 }
 
 void Storage::DeleteEntry(StringRef name) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   auto i = m_entries.find(name);
   if (i == m_entries.end()) return;
   DeleteEntryImpl(i->getValue(), lock, true);
 }
 
 void Storage::DeleteEntry(unsigned int local_id) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return;
   DeleteEntryImpl(m_localmap[local_id].get(), lock, true);
 }
@@ -745,7 +745,7 @@
 }
 
 void Storage::DeleteAllEntries() {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (m_entries.empty()) return;
 
   DeleteAllEntriesImpl(true);
@@ -773,7 +773,7 @@
   if (name.isTriviallyEmpty() ||
       (name.isSingleStringRef() && name.getSingleStringRef().empty()))
     return UINT_MAX;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   return GetOrNew(name)->local_id;
 }
 
@@ -781,7 +781,7 @@
                                               unsigned int types) {
   wpi::SmallString<128> prefixBuf;
   StringRef prefixStr = prefix.toStringRef(prefixBuf);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   std::vector<unsigned int> ids;
   for (auto& i : m_entries) {
     Entry* entry = i.getValue();
@@ -800,7 +800,7 @@
   info.flags = 0;
   info.last_change = 0;
 
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return info;
   Entry* entry = m_localmap[local_id].get();
   if (!entry->value) return info;
@@ -814,13 +814,13 @@
 }
 
 std::string Storage::GetEntryName(unsigned int local_id) const {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return std::string{};
   return m_localmap[local_id]->name;
 }
 
 NT_Type Storage::GetEntryType(unsigned int local_id) const {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return NT_UNASSIGNED;
   Entry* entry = m_localmap[local_id].get();
   if (!entry->value) return NT_UNASSIGNED;
@@ -828,7 +828,7 @@
 }
 
 uint64_t Storage::GetEntryLastChange(unsigned int local_id) const {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return 0;
   Entry* entry = m_localmap[local_id].get();
   if (!entry->value) return 0;
@@ -839,7 +839,7 @@
                                              unsigned int types) {
   wpi::SmallString<128> prefixBuf;
   StringRef prefixStr = prefix.toStringRef(prefixBuf);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   std::vector<EntryInfo> infos;
   for (auto& i : m_entries) {
     Entry* entry = i.getValue();
@@ -863,7 +863,7 @@
     unsigned int flags) const {
   wpi::SmallString<128> prefixBuf;
   StringRef prefixStr = prefix.toStringRef(prefixBuf);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   unsigned int uid = m_notifier.Add(callback, prefixStr, flags);
   // perform immediate notifications
   if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0) {
@@ -881,7 +881,7 @@
     unsigned int local_id,
     std::function<void(const EntryNotification& event)> callback,
     unsigned int flags) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   unsigned int uid = m_notifier.Add(callback, local_id, flags);
   // perform immediate notifications
   if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0 &&
@@ -900,7 +900,7 @@
                                         unsigned int flags) const {
   wpi::SmallString<128> prefixBuf;
   StringRef prefixStr = prefix.toStringRef(prefixBuf);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   unsigned int uid = m_notifier.AddPolled(poller, prefixStr, flags);
   // perform immediate notifications
   if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0) {
@@ -918,7 +918,7 @@
 unsigned int Storage::AddPolledListener(unsigned int poller,
                                         unsigned int local_id,
                                         unsigned int flags) const {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   unsigned int uid = m_notifier.AddPolled(poller, local_id, flags);
   // perform immediate notifications
   if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0 &&
@@ -939,7 +939,7 @@
     const {
   // copy values out of storage as quickly as possible so lock isn't held
   {
-    std::lock_guard<wpi::mutex> lock(m_mutex);
+    std::scoped_lock lock(m_mutex);
     // for periodic, don't re-save unless something has changed
     if (periodic && !m_persistent_dirty) return false;
     m_persistent_dirty = false;
@@ -969,7 +969,7 @@
   StringRef prefixStr = prefix.toStringRef(prefixBuf);
   // copy values out of storage as quickly as possible so lock isn't held
   {
-    std::lock_guard<wpi::mutex> lock(m_mutex);
+    std::scoped_lock lock(m_mutex);
     entries->reserve(m_entries.size());
     for (auto& i : m_entries) {
       Entry* entry = i.getValue();
@@ -990,7 +990,7 @@
 
 void Storage::CreateRpc(unsigned int local_id, StringRef def,
                         unsigned int rpc_uid) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return;
   Entry* entry = m_localmap[local_id].get();
 
@@ -1028,7 +1028,7 @@
 }
 
 unsigned int Storage::CallRpc(unsigned int local_id, StringRef params) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   if (local_id >= m_localmap.size()) return 0;
   Entry* entry = m_localmap[local_id].get();
 
@@ -1055,7 +1055,7 @@
     unsigned int call_uid = msg->seq_num_uid();
     m_rpc_server.ProcessRpc(local_id, call_uid, name, msg->str(), conn_info,
                             [=](StringRef result) {
-                              std::lock_guard<wpi::mutex> lock(m_mutex);
+                              std::scoped_lock lock(m_mutex);
                               m_rpc_results.insert(std::make_pair(
                                   RpcIdPair{local_id, call_uid}, result));
                               m_rpc_results_cond.notify_all();
@@ -1078,7 +1078,7 @@
 bool Storage::GetRpcResult(unsigned int local_id, unsigned int call_uid,
                            std::string* result, double timeout,
                            bool* timed_out) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
 
   RpcIdPair call_pair{local_id, call_uid};
 
@@ -1124,7 +1124,7 @@
 }
 
 void Storage::CancelRpcResult(unsigned int local_id, unsigned int call_uid) {
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   // safe to erase even if id does not exist
   m_rpc_blocking_calls.erase(RpcIdPair{local_id, call_uid});
   m_rpc_results_cond.notify_all();
diff --git a/ntcore/src/main/native/cpp/Storage_load.cpp b/ntcore/src/main/native/cpp/Storage_load.cpp
index 3716412..69eb173 100644
--- a/ntcore/src/main/native/cpp/Storage_load.cpp
+++ b/ntcore/src/main/native/cpp/Storage_load.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -370,7 +370,7 @@
 
   // copy values into storage as quickly as possible so lock isn't held
   std::vector<std::shared_ptr<Message>> msgs;
-  std::unique_lock<wpi::mutex> lock(m_mutex);
+  std::unique_lock lock(m_mutex);
   for (auto& i : entries) {
     Entry* entry = GetOrNew(i.first);
     auto old_value = entry->value;
diff --git a/ntcore/src/main/native/cpp/Storage_save.cpp b/ntcore/src/main/native/cpp/Storage_save.cpp
index 3f352da..797eb8b 100644
--- a/ntcore/src/main/native/cpp/Storage_save.cpp
+++ b/ntcore/src/main/native/cpp/Storage_save.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -203,7 +203,7 @@
     err = "could not open file";
     goto done;
   }
-  DEBUG("saving persistent file '" << filename << "'");
+  DEBUG0("saving persistent file '" << filename << "'");
   SavePersistentImpl(os).Save(entries);
   os.close();
   if (os.has_error()) {
@@ -252,7 +252,7 @@
   if (ec.value() != 0) {
     return "could not open file";
   }
-  DEBUG("saving file '" << filename << "'");
+  DEBUG0("saving file '" << filename << "'");
   SavePersistentImpl(os).Save(entries);
   os.close();
   if (os.has_error()) {
diff --git a/ntcore/src/main/native/cpp/Value.cpp b/ntcore/src/main/native/cpp/Value.cpp
index 61390f0..3f58b73 100644
--- a/ntcore/src/main/native/cpp/Value.cpp
+++ b/ntcore/src/main/native/cpp/Value.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include <wpi/memory.h>
+#include <wpi/MemAlloc.h>
 #include <wpi/timestamp.h>
 
 #include "Value_internal.h"
@@ -123,7 +123,7 @@
     case NT_BOOLEAN_ARRAY: {
       auto v = in.GetBooleanArray();
       out->data.arr_boolean.arr =
-          static_cast<int*>(wpi::CheckedMalloc(v.size() * sizeof(int)));
+          static_cast<int*>(wpi::safe_malloc(v.size() * sizeof(int)));
       out->data.arr_boolean.size = v.size();
       std::copy(v.begin(), v.end(), out->data.arr_boolean.arr);
       break;
@@ -131,7 +131,7 @@
     case NT_DOUBLE_ARRAY: {
       auto v = in.GetDoubleArray();
       out->data.arr_double.arr =
-          static_cast<double*>(wpi::CheckedMalloc(v.size() * sizeof(double)));
+          static_cast<double*>(wpi::safe_malloc(v.size() * sizeof(double)));
       out->data.arr_double.size = v.size();
       std::copy(v.begin(), v.end(), out->data.arr_double.arr);
       break;
@@ -139,7 +139,7 @@
     case NT_STRING_ARRAY: {
       auto v = in.GetStringArray();
       out->data.arr_string.arr = static_cast<NT_String*>(
-          wpi::CheckedMalloc(v.size() * sizeof(NT_String)));
+          wpi::safe_malloc(v.size() * sizeof(NT_String)));
       for (size_t i = 0; i < v.size(); ++i)
         ConvertToC(v[i], &out->data.arr_string.arr[i]);
       out->data.arr_string.size = v.size();
@@ -154,7 +154,7 @@
 
 void nt::ConvertToC(wpi::StringRef in, NT_String* out) {
   out->len = in.size();
-  out->str = static_cast<char*>(wpi::CheckedMalloc(in.size() + 1));
+  out->str = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
   std::memcpy(out->str, in.data(), in.size());
   out->str[in.size()] = '\0';
 }
diff --git a/ntcore/src/main/native/cpp/WireDecoder.cpp b/ntcore/src/main/native/cpp/WireDecoder.cpp
index 132e8a2..07c85d2 100644
--- a/ntcore/src/main/native/cpp/WireDecoder.cpp
+++ b/ntcore/src/main/native/cpp/WireDecoder.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -14,8 +14,8 @@
 #include <cstring>
 
 #include <wpi/MathExtras.h>
+#include <wpi/MemAlloc.h>
 #include <wpi/leb128.h>
-#include <wpi/memory.h>
 
 using namespace nt;
 
@@ -53,7 +53,7 @@
   // Start with a 1K temporary buffer.  Use malloc instead of new so we can
   // realloc.
   m_allocated = 1024;
-  m_buf = static_cast<char*>(wpi::CheckedMalloc(m_allocated));
+  m_buf = static_cast<char*>(wpi::safe_malloc(m_allocated));
   m_proto_rev = proto_rev;
   m_error = nullptr;
 }
@@ -72,7 +72,7 @@
   if (m_allocated >= len) return;
   size_t newlen = m_allocated * 2;
   while (newlen < len) newlen *= 2;
-  m_buf = static_cast<char*>(wpi::CheckedRealloc(m_buf, newlen));
+  m_buf = static_cast<char*>(wpi::safe_realloc(m_buf, newlen));
   m_allocated = newlen;
 }
 
diff --git a/ntcore/src/main/native/cpp/networktables/NetworkTable.cpp b/ntcore/src/main/native/cpp/networktables/NetworkTable.cpp
index 1ec0942..6d41976 100644
--- a/ntcore/src/main/native/cpp/networktables/NetworkTable.cpp
+++ b/ntcore/src/main/native/cpp/networktables/NetworkTable.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -21,6 +21,8 @@
 
 #ifdef __GNUC__
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif _WIN32
+#pragma warning(disable : 4996)
 #endif
 
 const char NetworkTable::PATH_SEPARATOR_CHAR = '/';
@@ -204,7 +206,7 @@
 NetworkTableEntry NetworkTable::GetEntry(const Twine& key) const {
   wpi::SmallString<128> keyBuf;
   StringRef keyStr = key.toStringRef(keyBuf);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   NT_Entry& entry = m_entries[keyStr];
   if (entry == 0) {
     entry = nt::GetEntry(m_inst, m_path + Twine(PATH_SEPARATOR_CHAR) + keyStr);
@@ -257,7 +259,7 @@
 
 void NetworkTable::AddTableListenerEx(ITableListener* listener,
                                       unsigned int flags) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   wpi::SmallString<128> path(m_path);
   path += PATH_SEPARATOR_CHAR;
   size_t prefix_len = path.size();
@@ -281,7 +283,7 @@
 
 void NetworkTable::AddTableListenerEx(StringRef key, ITableListener* listener,
                                       unsigned int flags) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   size_t prefix_len = m_path.size() + 1;
   auto entry = GetEntry(key);
   NT_EntryListener id = nt::AddEntryListener(
@@ -334,7 +336,7 @@
 
 void NetworkTable::AddSubTableListener(ITableListener* listener,
                                        bool localNotify) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   size_t prefix_len = m_path.size() + 1;
 
   // The lambda needs to be copyable, but StringMap is not, so use
@@ -360,7 +362,7 @@
 }
 
 void NetworkTable::RemoveTableListener(ITableListener* listener) {
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   auto matches_begin =
       std::remove_if(m_listeners.begin(), m_listeners.end(),
                      [=](const Listener& x) { return x.first == listener; });
@@ -395,7 +397,7 @@
   std::vector<std::string> keys;
   size_t prefix_len = m_path.size() + 1;
   auto infos = GetEntryInfo(m_inst, m_path + Twine(PATH_SEPARATOR_CHAR), types);
-  std::lock_guard<wpi::mutex> lock(m_mutex);
+  std::scoped_lock lock(m_mutex);
   for (auto& info : infos) {
     auto relative_key = StringRef(info.name).substr(prefix_len);
     if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) continue;
diff --git a/ntcore/src/main/native/cpp/ntcore_c.cpp b/ntcore/src/main/native/cpp/ntcore_c.cpp
index 6c71e55..7ca68f5 100644
--- a/ntcore/src/main/native/cpp/ntcore_c.cpp
+++ b/ntcore/src/main/native/cpp/ntcore_c.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -10,7 +10,7 @@
 #include <cassert>
 #include <cstdlib>
 
-#include <wpi/memory.h>
+#include <wpi/MemAlloc.h>
 #include <wpi/timestamp.h>
 
 #include "Value_internal.h"
@@ -21,7 +21,7 @@
 // Conversion helpers
 
 static void ConvertToC(wpi::StringRef in, char** out) {
-  *out = static_cast<char*>(wpi::CheckedMalloc(in.size() + 1));
+  *out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
   std::memmove(*out, in.data(), in.size());
   (*out)[in.size()] = '\0';
 }
@@ -58,13 +58,13 @@
 
   out->num_params = in.params.size();
   out->params = static_cast<NT_RpcParamDef*>(
-      wpi::CheckedMalloc(in.params.size() * sizeof(NT_RpcParamDef)));
+      wpi::safe_malloc(in.params.size() * sizeof(NT_RpcParamDef)));
   for (size_t i = 0; i < in.params.size(); ++i)
     ConvertToC(in.params[i], &out->params[i]);
 
   out->num_results = in.results.size();
   out->results = static_cast<NT_RpcResultDef*>(
-      wpi::CheckedMalloc(in.results.size() * sizeof(NT_RpcResultDef)));
+      wpi::safe_malloc(in.results.size() * sizeof(NT_RpcResultDef)));
   for (size_t i = 0; i < in.results.size(); ++i)
     ConvertToC(in.results[i], &out->results[i]);
 }
@@ -105,7 +105,7 @@
   if (!out_len) return nullptr;
   *out_len = in.size();
   if (in.empty()) return nullptr;
-  O* out = static_cast<O*>(wpi::CheckedMalloc(sizeof(O) * in.size()));
+  O* out = static_cast<O*>(wpi::safe_malloc(sizeof(O) * in.size()));
   for (size_t i = 0; i < in.size(); ++i) ConvertToC(in[i], &out[i]);
   return out;
 }
@@ -188,7 +188,7 @@
 
   // create array and copy into it
   NT_Entry* info = static_cast<NT_Entry*>(
-      wpi::CheckedMalloc(info_v.size() * sizeof(NT_Entry)));
+      wpi::safe_malloc(info_v.size() * sizeof(NT_Entry)));
   std::memcpy(info, info_v.data(), info_v.size() * sizeof(NT_Entry));
   return info;
 }
@@ -519,9 +519,9 @@
 
   // create array and copy into it
   NT_Value** values = static_cast<NT_Value**>(
-      wpi::CheckedMalloc(values_v.size() * sizeof(NT_Value*)));
+      wpi::safe_malloc(values_v.size() * sizeof(NT_Value*)));
   for (size_t i = 0; i < values_v.size(); ++i) {
-    values[i] = static_cast<NT_Value*>(wpi::CheckedMalloc(sizeof(NT_Value)));
+    values[i] = static_cast<NT_Value*>(wpi::safe_malloc(sizeof(NT_Value)));
     ConvertToC(*values_v[i], values[i]);
   }
   return values;
@@ -802,27 +802,27 @@
 
 /* Allocates a char array of the specified size.*/
 char* NT_AllocateCharArray(size_t size) {
-  char* retVal = static_cast<char*>(wpi::CheckedMalloc(size * sizeof(char)));
+  char* retVal = static_cast<char*>(wpi::safe_malloc(size * sizeof(char)));
   return retVal;
 }
 
 /* Allocates an integer or boolean array of the specified size. */
 int* NT_AllocateBooleanArray(size_t size) {
-  int* retVal = static_cast<int*>(wpi::CheckedMalloc(size * sizeof(int)));
+  int* retVal = static_cast<int*>(wpi::safe_malloc(size * sizeof(int)));
   return retVal;
 }
 
 /* Allocates a double array of the specified size. */
 double* NT_AllocateDoubleArray(size_t size) {
   double* retVal =
-      static_cast<double*>(wpi::CheckedMalloc(size * sizeof(double)));
+      static_cast<double*>(wpi::safe_malloc(size * sizeof(double)));
   return retVal;
 }
 
 /* Allocates an NT_String array of the specified size. */
 struct NT_String* NT_AllocateStringArray(size_t size) {
   NT_String* retVal =
-      static_cast<NT_String*>(wpi::CheckedMalloc(size * sizeof(NT_String)));
+      static_cast<NT_String*>(wpi::safe_malloc(size * sizeof(NT_String)));
   return retVal;
 }
 
@@ -944,7 +944,7 @@
   *last_change = value->last_change;
   *str_len = value->data.v_string.len;
   char* str =
-      static_cast<char*>(wpi::CheckedMalloc(value->data.v_string.len + 1));
+      static_cast<char*>(wpi::safe_malloc(value->data.v_string.len + 1));
   std::memcpy(str, value->data.v_string.str, value->data.v_string.len + 1);
   return str;
 }
@@ -955,7 +955,7 @@
   *last_change = value->last_change;
   *raw_len = value->data.v_string.len;
   char* raw =
-      static_cast<char*>(wpi::CheckedMalloc(value->data.v_string.len + 1));
+      static_cast<char*>(wpi::safe_malloc(value->data.v_string.len + 1));
   std::memcpy(raw, value->data.v_string.str, value->data.v_string.len + 1);
   return raw;
 }
@@ -966,7 +966,7 @@
   *last_change = value->last_change;
   *arr_size = value->data.arr_boolean.size;
   NT_Bool* arr = static_cast<int*>(
-      wpi::CheckedMalloc(value->data.arr_boolean.size * sizeof(NT_Bool)));
+      wpi::safe_malloc(value->data.arr_boolean.size * sizeof(NT_Bool)));
   std::memcpy(arr, value->data.arr_boolean.arr,
               value->data.arr_boolean.size * sizeof(NT_Bool));
   return arr;
@@ -978,7 +978,7 @@
   *last_change = value->last_change;
   *arr_size = value->data.arr_double.size;
   double* arr = static_cast<double*>(
-      wpi::CheckedMalloc(value->data.arr_double.size * sizeof(double)));
+      wpi::safe_malloc(value->data.arr_double.size * sizeof(double)));
   std::memcpy(arr, value->data.arr_double.arr,
               value->data.arr_double.size * sizeof(double));
   return arr;
@@ -990,11 +990,11 @@
   *last_change = value->last_change;
   *arr_size = value->data.arr_string.size;
   NT_String* arr = static_cast<NT_String*>(
-      wpi::CheckedMalloc(value->data.arr_string.size * sizeof(NT_String)));
+      wpi::safe_malloc(value->data.arr_string.size * sizeof(NT_String)));
   for (size_t i = 0; i < value->data.arr_string.size; ++i) {
     size_t len = value->data.arr_string.arr[i].len;
     arr[i].len = len;
-    arr[i].str = static_cast<char*>(wpi::CheckedMalloc(len + 1));
+    arr[i].str = static_cast<char*>(wpi::safe_malloc(len + 1));
     std::memcpy(arr[i].str, value->data.arr_string.arr[i].str, len + 1);
   }
   return arr;
@@ -1099,7 +1099,7 @@
   *last_change = v->last_change();
   auto vArr = v->GetBooleanArray();
   NT_Bool* arr =
-      static_cast<int*>(wpi::CheckedMalloc(vArr.size() * sizeof(NT_Bool)));
+      static_cast<int*>(wpi::safe_malloc(vArr.size() * sizeof(NT_Bool)));
   *arr_size = vArr.size();
   std::copy(vArr.begin(), vArr.end(), arr);
   return arr;
@@ -1112,7 +1112,7 @@
   *last_change = v->last_change();
   auto vArr = v->GetDoubleArray();
   double* arr =
-      static_cast<double*>(wpi::CheckedMalloc(vArr.size() * sizeof(double)));
+      static_cast<double*>(wpi::safe_malloc(vArr.size() * sizeof(double)));
   *arr_size = vArr.size();
   std::copy(vArr.begin(), vArr.end(), arr);
   return arr;
@@ -1125,7 +1125,7 @@
   *last_change = v->last_change();
   auto vArr = v->GetStringArray();
   NT_String* arr = static_cast<NT_String*>(
-      wpi::CheckedMalloc(vArr.size() * sizeof(NT_String)));
+      wpi::safe_malloc(vArr.size() * sizeof(NT_String)));
   for (size_t i = 0; i < vArr.size(); ++i) {
     ConvertToC(vArr[i], &arr[i]);
   }
diff --git a/ntcore/src/main/native/cpp/ntcore_cpp.cpp b/ntcore/src/main/native/cpp/ntcore_cpp.cpp
index 18256f5..5a2b8af 100644
--- a/ntcore/src/main/native/cpp/ntcore_cpp.cpp
+++ b/ntcore/src/main/native/cpp/ntcore_cpp.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -959,7 +959,7 @@
   auto ii = InstanceImpl::GetDefault();
   static wpi::mutex mutex;
   static unsigned int logger = 0;
-  std::lock_guard<wpi::mutex> lock(mutex);
+  std::scoped_lock lock(mutex);
   if (logger != 0) ii->logger_impl.Remove(logger);
   logger = ii->logger_impl.Add(
       [=](const LogMessage& msg) {
diff --git a/ntcore/src/main/native/cpp/ntcore_test.cpp b/ntcore/src/main/native/cpp/ntcore_test.cpp
index f74172e..d633fc5 100644
--- a/ntcore/src/main/native/cpp/ntcore_test.cpp
+++ b/ntcore/src/main/native/cpp/ntcore_test.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved.                        */
+/* 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.                                                               */
@@ -7,14 +7,14 @@
 
 #include "ntcore_test.h"
 
-#include <wpi/memory.h>
+#include <wpi/MemAlloc.h>
 
 #include "Value_internal.h"
 
 extern "C" {
 struct NT_String* NT_GetStringForTesting(const char* string, int* struct_size) {
   struct NT_String* str =
-      static_cast<NT_String*>(wpi::CheckedCalloc(1, sizeof(NT_String)));
+      static_cast<NT_String*>(wpi::safe_calloc(1, sizeof(NT_String)));
   nt::ConvertToC(wpi::StringRef(string), str);
   *struct_size = sizeof(NT_String);
   return str;
@@ -26,7 +26,7 @@
                                                uint64_t last_change,
                                                int* struct_size) {
   struct NT_EntryInfo* entry_info =
-      static_cast<NT_EntryInfo*>(wpi::CheckedCalloc(1, sizeof(NT_EntryInfo)));
+      static_cast<NT_EntryInfo*>(wpi::safe_calloc(1, sizeof(NT_EntryInfo)));
   nt::ConvertToC(wpi::StringRef(name), &entry_info->name);
   entry_info->type = type;
   entry_info->flags = flags;
@@ -44,7 +44,7 @@
     const char* remote_id, const char* remote_ip, unsigned int remote_port,
     uint64_t last_update, unsigned int protocol_version, int* struct_size) {
   struct NT_ConnectionInfo* conn_info = static_cast<NT_ConnectionInfo*>(
-      wpi::CheckedCalloc(1, sizeof(NT_ConnectionInfo)));
+      wpi::safe_calloc(1, sizeof(NT_ConnectionInfo)));
   nt::ConvertToC(wpi::StringRef(remote_id), &conn_info->remote_id);
   nt::ConvertToC(wpi::StringRef(remote_ip), &conn_info->remote_ip);
   conn_info->remote_port = remote_port;
@@ -63,7 +63,7 @@
 struct NT_Value* NT_GetValueBooleanForTesting(uint64_t last_change, int val,
                                               int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_BOOLEAN;
   value->last_change = last_change;
   value->data.v_boolean = val;
@@ -74,7 +74,7 @@
 struct NT_Value* NT_GetValueDoubleForTesting(uint64_t last_change, double val,
                                              int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_DOUBLE;
   value->last_change = last_change;
   value->data.v_double = val;
@@ -86,7 +86,7 @@
                                              const char* str,
                                              int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_STRING;
   value->last_change = last_change;
   nt::ConvertToC(wpi::StringRef(str), &value->data.v_string);
@@ -97,7 +97,7 @@
 struct NT_Value* NT_GetValueRawForTesting(uint64_t last_change, const char* raw,
                                           int raw_len, int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_RAW;
   value->last_change = last_change;
   nt::ConvertToC(wpi::StringRef(raw, raw_len), &value->data.v_string);
@@ -110,7 +110,7 @@
                                                    size_t array_len,
                                                    int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_BOOLEAN_ARRAY;
   value->last_change = last_change;
   value->data.arr_boolean.arr = NT_AllocateBooleanArray(array_len);
@@ -126,7 +126,7 @@
                                                   size_t array_len,
                                                   int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_BOOLEAN;
   value->last_change = last_change;
   value->data.arr_double.arr = NT_AllocateDoubleArray(array_len);
@@ -142,7 +142,7 @@
                                                   size_t array_len,
                                                   int* struct_size) {
   struct NT_Value* value =
-      static_cast<NT_Value*>(wpi::CheckedCalloc(1, sizeof(NT_Value)));
+      static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
   value->type = NT_BOOLEAN;
   value->last_change = last_change;
   value->data.arr_string.arr = NT_AllocateStringArray(array_len);
@@ -151,7 +151,7 @@
     size_t len = arr[i].len;
     value->data.arr_string.arr[i].len = len;
     value->data.arr_string.arr[i].str =
-        static_cast<char*>(wpi::CheckedMalloc(len + 1));
+        static_cast<char*>(wpi::safe_malloc(len + 1));
     std::memcpy(value->data.arr_string.arr[i].str, arr[i].str, len + 1);
   }
   *struct_size = sizeof(NT_Value);
@@ -173,8 +173,8 @@
 struct NT_RpcParamDef* NT_GetRpcParamDefForTesting(const char* name,
                                                    const struct NT_Value* val,
                                                    int* struct_size) {
-  struct NT_RpcParamDef* def = static_cast<NT_RpcParamDef*>(
-      wpi::CheckedCalloc(1, sizeof(NT_RpcParamDef)));
+  struct NT_RpcParamDef* def =
+      static_cast<NT_RpcParamDef*>(wpi::safe_calloc(1, sizeof(NT_RpcParamDef)));
   nt::ConvertToC(wpi::StringRef(name), &def->name);
   CopyNtValue(val, &def->def_value);
   *struct_size = sizeof(NT_RpcParamDef);
@@ -191,7 +191,7 @@
                                                       enum NT_Type type,
                                                       int* struct_size) {
   struct NT_RpcResultDef* def = static_cast<NT_RpcResultDef*>(
-      wpi::CheckedCalloc(1, sizeof(NT_RpcResultDef)));
+      wpi::safe_calloc(1, sizeof(NT_RpcResultDef)));
   nt::ConvertToC(wpi::StringRef(name), &def->name);
   def->type = type;
   *struct_size = sizeof(NT_RpcResultDef);
@@ -208,19 +208,19 @@
     const struct NT_RpcParamDef* params, size_t num_results,
     const struct NT_RpcResultDef* results, int* struct_size) {
   struct NT_RpcDefinition* def = static_cast<NT_RpcDefinition*>(
-      wpi::CheckedCalloc(1, sizeof(NT_RpcDefinition)));
+      wpi::safe_calloc(1, sizeof(NT_RpcDefinition)));
   def->version = version;
   nt::ConvertToC(wpi::StringRef(name), &def->name);
   def->num_params = num_params;
   def->params = static_cast<NT_RpcParamDef*>(
-      wpi::CheckedMalloc(num_params * sizeof(NT_RpcParamDef)));
+      wpi::safe_malloc(num_params * sizeof(NT_RpcParamDef)));
   for (size_t i = 0; i < num_params; ++i) {
     CopyNtString(&params[i].name, &def->params[i].name);
     CopyNtValue(&params[i].def_value, &def->params[i].def_value);
   }
   def->num_results = num_results;
   def->results = static_cast<NT_RpcResultDef*>(
-      wpi::CheckedMalloc(num_results * sizeof(NT_RpcResultDef)));
+      wpi::safe_malloc(num_results * sizeof(NT_RpcResultDef)));
   for (size_t i = 0; i < num_results; ++i) {
     CopyNtString(&results[i].name, &def->results[i].name);
     def->results[i].type = results[i].type;
@@ -234,7 +234,7 @@
     unsigned int rpc_id, unsigned int call_uid, const char* name,
     const char* params, size_t params_len, int* struct_size) {
   struct NT_RpcAnswer* info =
-      static_cast<NT_RpcAnswer*>(wpi::CheckedCalloc(1, sizeof(NT_RpcAnswer)));
+      static_cast<NT_RpcAnswer*>(wpi::safe_calloc(1, sizeof(NT_RpcAnswer)));
   info->entry = rpc_id;
   info->call = call_uid;
   nt::ConvertToC(wpi::StringRef(name), &info->name);
diff --git a/ntcore/src/main/native/include/networktables/NetworkTable.h b/ntcore/src/main/native/include/networktables/NetworkTable.h
index 6bc2af6..6504e09 100644
--- a/ntcore/src/main/native/include/networktables/NetworkTable.h
+++ b/ntcore/src/main/native/include/networktables/NetworkTable.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -36,6 +36,9 @@
 #ifdef __GNUC__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif _WIN32
+#pragma warning(push)
+#pragma warning(disable : 4996)
 #endif
 
 /**
@@ -765,6 +768,8 @@
 
 #ifdef __GNUC__
 #pragma GCC diagnostic pop
+#elif _WIN32
+#pragma warning(pop)
 #endif
 
 }  // namespace nt
diff --git a/ntcore/src/main/native/include/networktables/NetworkTableEntry.h b/ntcore/src/main/native/include/networktables/NetworkTableEntry.h
index 16b5c61..8fdedc6 100644
--- a/ntcore/src/main/native/include/networktables/NetworkTableEntry.h
+++ b/ntcore/src/main/native/include/networktables/NetworkTableEntry.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -10,6 +10,7 @@
 
 #include <stdint.h>
 
+#include <initializer_list>
 #include <memory>
 #include <string>
 #include <vector>
@@ -177,6 +178,23 @@
   std::vector<int> GetBooleanArray(ArrayRef<int> defaultValue) const;
 
   /**
+   * Gets the entry's value as a boolean array. If the entry does not exist
+   * or is of different type, it will return the default value.
+   *
+   * @param defaultValue the value to be returned if no value is found
+   * @return the entry's value or the given default value
+   *
+   * @note This makes a copy of the array.  If the overhead of this is a
+   *       concern, use GetValue() instead.
+   *
+   * @note The returned array is std::vector<int> instead of std::vector<bool>
+   *       because std::vector<bool> is special-cased in C++.  0 is false, any
+   *       non-zero value is true.
+   */
+  std::vector<int> GetBooleanArray(
+      std::initializer_list<int> defaultValue) const;
+
+  /**
    * Gets the entry's value as a double array. If the entry does not exist
    * or is of different type, it will return the default value.
    *
@@ -189,6 +207,19 @@
   std::vector<double> GetDoubleArray(ArrayRef<double> defaultValue) const;
 
   /**
+   * Gets the entry's value as a double array. If the entry does not exist
+   * or is of different type, it will return the default value.
+   *
+   * @param defaultValue the value to be returned if no value is found
+   * @return the entry's value or the given default value
+   *
+   * @note This makes a copy of the array.  If the overhead of this is a
+   *       concern, use GetValue() instead.
+   */
+  std::vector<double> GetDoubleArray(
+      std::initializer_list<double> defaultValue) const;
+
+  /**
    * Gets the entry's value as a string array. If the entry does not exist
    * or is of different type, it will return the default value.
    *
@@ -202,6 +233,19 @@
       ArrayRef<std::string> defaultValue) const;
 
   /**
+   * Gets the entry's value as a string array. If the entry does not exist
+   * or is of different type, it will return the default value.
+   *
+   * @param defaultValue the value to be returned if no value is found
+   * @return the entry's value or the given default value
+   *
+   * @note This makes a copy of the array.  If the overhead of this is a
+   *       concern, use GetValue() instead.
+   */
+  std::vector<std::string> GetStringArray(
+      std::initializer_list<std::string> defaultValue) const;
+
+  /**
    * Sets the entry's value if it does not exist.
    *
    * @param defaultValue the default value to set
@@ -255,6 +299,14 @@
    * @param defaultValue the default value to set
    * @return False if the entry exists with a different type
    */
+  bool SetDefaultBooleanArray(std::initializer_list<int> defaultValue);
+
+  /**
+   * Sets the entry's value if it does not exist.
+   *
+   * @param defaultValue the default value to set
+   * @return False if the entry exists with a different type
+   */
   bool SetDefaultDoubleArray(ArrayRef<double> defaultValue);
 
   /**
@@ -263,9 +315,25 @@
    * @param defaultValue the default value to set
    * @return False if the entry exists with a different type
    */
+  bool SetDefaultDoubleArray(std::initializer_list<double> defaultValue);
+
+  /**
+   * Sets the entry's value if it does not exist.
+   *
+   * @param defaultValue the default value to set
+   * @return False if the entry exists with a different type
+   */
   bool SetDefaultStringArray(ArrayRef<std::string> defaultValue);
 
   /**
+   * Sets the entry's value if it does not exist.
+   *
+   * @param defaultValue the default value to set
+   * @return False if the entry exists with a different type
+   */
+  bool SetDefaultStringArray(std::initializer_list<std::string> defaultValue);
+
+  /**
    * Sets the entry's value.
    *
    * @param value the value to set
@@ -311,6 +379,22 @@
    * @param value the value to set
    * @return False if the entry exists with a different type
    */
+  bool SetBooleanArray(ArrayRef<bool> value);
+
+  /**
+   * Sets the entry's value.
+   *
+   * @param value the value to set
+   * @return False if the entry exists with a different type
+   */
+  bool SetBooleanArray(std::initializer_list<bool> value);
+
+  /**
+   * Sets the entry's value.
+   *
+   * @param value the value to set
+   * @return False if the entry exists with a different type
+   */
   bool SetBooleanArray(ArrayRef<int> value);
 
   /**
@@ -319,6 +403,14 @@
    * @param value the value to set
    * @return False if the entry exists with a different type
    */
+  bool SetBooleanArray(std::initializer_list<int> value);
+
+  /**
+   * Sets the entry's value.
+   *
+   * @param value the value to set
+   * @return False if the entry exists with a different type
+   */
   bool SetDoubleArray(ArrayRef<double> value);
 
   /**
@@ -327,9 +419,25 @@
    * @param value the value to set
    * @return False if the entry exists with a different type
    */
+  bool SetDoubleArray(std::initializer_list<double> value);
+
+  /**
+   * Sets the entry's value.
+   *
+   * @param value the value to set
+   * @return False if the entry exists with a different type
+   */
   bool SetStringArray(ArrayRef<std::string> value);
 
   /**
+   * Sets the entry's value.
+   *
+   * @param value the value to set
+   * @return False if the entry exists with a different type
+   */
+  bool SetStringArray(std::initializer_list<std::string> value);
+
+  /**
    * Sets the entry's value.  If the value is of different type, the type is
    * changed to match the new value.
    *
@@ -375,6 +483,22 @@
    *
    * @param value the value to set
    */
+  void ForceSetBooleanArray(ArrayRef<bool> value);
+
+  /**
+   * Sets the entry's value.  If the value is of different type, the type is
+   * changed to match the new value.
+   *
+   * @param value the value to set
+   */
+  void ForceSetBooleanArray(std::initializer_list<bool> value);
+
+  /**
+   * Sets the entry's value.  If the value is of different type, the type is
+   * changed to match the new value.
+   *
+   * @param value the value to set
+   */
   void ForceSetBooleanArray(ArrayRef<int> value);
 
   /**
@@ -383,6 +507,14 @@
    *
    * @param value the value to set
    */
+  void ForceSetBooleanArray(std::initializer_list<int> value);
+
+  /**
+   * Sets the entry's value.  If the value is of different type, the type is
+   * changed to match the new value.
+   *
+   * @param value the value to set
+   */
   void ForceSetDoubleArray(ArrayRef<double> value);
 
   /**
@@ -391,9 +523,25 @@
    *
    * @param value the value to set
    */
+  void ForceSetDoubleArray(std::initializer_list<double> value);
+
+  /**
+   * Sets the entry's value.  If the value is of different type, the type is
+   * changed to match the new value.
+   *
+   * @param value the value to set
+   */
   void ForceSetStringArray(ArrayRef<std::string> value);
 
   /**
+   * Sets the entry's value.  If the value is of different type, the type is
+   * changed to match the new value.
+   *
+   * @param value the value to set
+   */
+  void ForceSetStringArray(std::initializer_list<std::string> value);
+
+  /**
    * Sets flags.
    *
    * @param flags the flags to set (bitmask)
diff --git a/ntcore/src/main/native/include/networktables/NetworkTableEntry.inl b/ntcore/src/main/native/include/networktables/NetworkTableEntry.inl
index f95b1a8..4a46b96 100644
--- a/ntcore/src/main/native/include/networktables/NetworkTableEntry.inl
+++ b/ntcore/src/main/native/include/networktables/NetworkTableEntry.inl
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) FIRST 2017. All Rights Reserved.                             */
+/* Copyright (c) FIRST 2017-2019. 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.                                                               */
@@ -76,6 +76,12 @@
   return value->GetBooleanArray();
 }
 
+inline std::vector<int> NetworkTableEntry::GetBooleanArray(
+    std::initializer_list<int> defaultValue) const {
+  return GetBooleanArray(
+      wpi::makeArrayRef(defaultValue.begin(), defaultValue.end()));
+}
+
 inline std::vector<double> NetworkTableEntry::GetDoubleArray(
     ArrayRef<double> defaultValue) const {
   auto value = GetEntryValue(m_handle);
@@ -83,6 +89,12 @@
   return value->GetDoubleArray();
 }
 
+inline std::vector<double> NetworkTableEntry::GetDoubleArray(
+    std::initializer_list<double> defaultValue) const {
+  return GetDoubleArray(
+      wpi::makeArrayRef(defaultValue.begin(), defaultValue.end()));
+}
+
 inline std::vector<std::string> NetworkTableEntry::GetStringArray(
     ArrayRef<std::string> defaultValue) const {
   auto value = GetEntryValue(m_handle);
@@ -90,6 +102,12 @@
   return value->GetStringArray();
 }
 
+inline std::vector<std::string> NetworkTableEntry::GetStringArray(
+    std::initializer_list<std::string> defaultValue) const {
+  return GetStringArray(
+      wpi::makeArrayRef(defaultValue.begin(), defaultValue.end()));
+}
+
 inline bool NetworkTableEntry::SetDefaultValue(std::shared_ptr<Value> value) {
   return SetDefaultEntryValue(m_handle, value);
 }
@@ -145,18 +163,42 @@
   return SetEntryValue(m_handle, Value::MakeRaw(value));
 }
 
+inline bool NetworkTableEntry::SetBooleanArray(ArrayRef<bool> value) {
+  return SetEntryValue(m_handle, Value::MakeBooleanArray(value));
+}
+
+inline bool NetworkTableEntry::SetBooleanArray(
+    std::initializer_list<bool> value) {
+  return SetEntryValue(m_handle, Value::MakeBooleanArray(value));
+}
+
 inline bool NetworkTableEntry::SetBooleanArray(ArrayRef<int> value) {
   return SetEntryValue(m_handle, Value::MakeBooleanArray(value));
 }
 
+inline bool NetworkTableEntry::SetBooleanArray(
+    std::initializer_list<int> value) {
+  return SetEntryValue(m_handle, Value::MakeBooleanArray(value));
+}
+
 inline bool NetworkTableEntry::SetDoubleArray(ArrayRef<double> value) {
   return SetEntryValue(m_handle, Value::MakeDoubleArray(value));
 }
 
+inline bool NetworkTableEntry::SetDoubleArray(
+    std::initializer_list<double> value) {
+  return SetEntryValue(m_handle, Value::MakeDoubleArray(value));
+}
+
 inline bool NetworkTableEntry::SetStringArray(ArrayRef<std::string> value) {
   return SetEntryValue(m_handle, Value::MakeStringArray(value));
 }
 
+inline bool NetworkTableEntry::SetStringArray(
+    std::initializer_list<std::string> value) {
+  return SetEntryValue(m_handle, Value::MakeStringArray(value));
+}
+
 inline void NetworkTableEntry::ForceSetValue(std::shared_ptr<Value> value) {
   SetEntryTypeValue(m_handle, value);
 }
@@ -177,19 +219,43 @@
   SetEntryTypeValue(m_handle, Value::MakeRaw(value));
 }
 
+inline void NetworkTableEntry::ForceSetBooleanArray(ArrayRef<bool> value) {
+  SetEntryTypeValue(m_handle, Value::MakeBooleanArray(value));
+}
+
+inline void NetworkTableEntry::ForceSetBooleanArray(
+    std::initializer_list<bool> value) {
+  SetEntryTypeValue(m_handle, Value::MakeBooleanArray(value));
+}
+
 inline void NetworkTableEntry::ForceSetBooleanArray(ArrayRef<int> value) {
   SetEntryTypeValue(m_handle, Value::MakeBooleanArray(value));
 }
 
+inline void NetworkTableEntry::ForceSetBooleanArray(
+    std::initializer_list<int> value) {
+  SetEntryTypeValue(m_handle, Value::MakeBooleanArray(value));
+}
+
 inline void NetworkTableEntry::ForceSetDoubleArray(ArrayRef<double> value) {
   SetEntryTypeValue(m_handle, Value::MakeDoubleArray(value));
 }
 
+inline void NetworkTableEntry::ForceSetDoubleArray(
+    std::initializer_list<double> value) {
+  SetEntryTypeValue(m_handle, Value::MakeDoubleArray(value));
+}
+
 inline void NetworkTableEntry::ForceSetStringArray(
     ArrayRef<std::string> value) {
   SetEntryTypeValue(m_handle, Value::MakeStringArray(value));
 }
 
+inline void NetworkTableEntry::ForceSetStringArray(
+    std::initializer_list<std::string> value) {
+  SetEntryTypeValue(m_handle, Value::MakeStringArray(value));
+}
+
 inline void NetworkTableEntry::SetFlags(unsigned int flags) {
   SetEntryFlags(m_handle, GetFlags() | flags);
 }
diff --git a/ntcore/src/main/native/include/networktables/NetworkTableValue.h b/ntcore/src/main/native/include/networktables/NetworkTableValue.h
index 3aa0c01..1b8aabe 100644
--- a/ntcore/src/main/native/include/networktables/NetworkTableValue.h
+++ b/ntcore/src/main/native/include/networktables/NetworkTableValue.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -11,6 +11,7 @@
 #include <stdint.h>
 
 #include <cassert>
+#include <initializer_list>
 #include <memory>
 #include <string>
 #include <type_traits>
@@ -278,21 +279,16 @@
     return val;
   }
 
-/**
- * Creates a string entry value.
- *
- * @param value the value
- * @param time if nonzero, the creation time to use (instead of the current
- *             time)
- * @return The entry value
- */
-#ifdef _MSC_VER
-  template <typename T,
-            typename = std::enable_if_t<std::is_same<T, std::string>>>
-#else
+  /**
+   * Creates a string entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
+   */
   template <typename T,
             typename std::enable_if<std::is_same<T, std::string>::value>::type>
-#endif
   static std::shared_ptr<Value> MakeString(T&& value, uint64_t time = 0) {
     auto val = std::make_shared<Value>(NT_STRING, time, private_init());
     val->m_string = std::move(value);
@@ -317,21 +313,16 @@
     return val;
   }
 
-/**
- * Creates a raw entry value.
- *
- * @param value the value
- * @param time if nonzero, the creation time to use (instead of the current
- *             time)
- * @return The entry value
- */
-#ifdef _MSC_VER
-  template <typename T,
-            typename = std::enable_if_t<std::is_same<T, std::string>>>
-#else
+  /**
+   * Creates a raw entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
+   */
   template <typename T,
             typename std::enable_if<std::is_same<T, std::string>::value>::type>
-#endif
   static std::shared_ptr<Value> MakeRaw(T&& value, uint64_t time = 0) {
     auto val = std::make_shared<Value>(NT_RAW, time, private_init());
     val->m_string = std::move(value);
@@ -392,10 +383,38 @@
    *             time)
    * @return The entry value
    */
+  static std::shared_ptr<Value> MakeBooleanArray(
+      std::initializer_list<bool> value, uint64_t time = 0) {
+    return MakeBooleanArray(wpi::makeArrayRef(value.begin(), value.end()),
+                            time);
+  }
+
+  /**
+   * Creates a boolean array entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
+   */
   static std::shared_ptr<Value> MakeBooleanArray(ArrayRef<int> value,
                                                  uint64_t time = 0);
 
   /**
+   * Creates a boolean array entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
+   */
+  static std::shared_ptr<Value> MakeBooleanArray(
+      std::initializer_list<int> value, uint64_t time = 0) {
+    return MakeBooleanArray(wpi::makeArrayRef(value.begin(), value.end()),
+                            time);
+  }
+
+  /**
    * Creates a double array entry value.
    *
    * @param value the value
@@ -407,6 +426,19 @@
                                                 uint64_t time = 0);
 
   /**
+   * Creates a double array entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
+   */
+  static std::shared_ptr<Value> MakeDoubleArray(
+      std::initializer_list<double> value, uint64_t time = 0) {
+    return MakeDoubleArray(wpi::makeArrayRef(value.begin(), value.end()), time);
+  }
+
+  /**
    * Creates a string array entry value.
    *
    * @param value the value
@@ -424,6 +456,19 @@
    * @param time if nonzero, the creation time to use (instead of the current
    *             time)
    * @return The entry value
+   */
+  static std::shared_ptr<Value> MakeStringArray(
+      std::initializer_list<std::string> value, uint64_t time = 0) {
+    return MakeStringArray(wpi::makeArrayRef(value.begin(), value.end()), time);
+  }
+
+  /**
+   * Creates a string array entry value.
+   *
+   * @param value the value
+   * @param time if nonzero, the creation time to use (instead of the current
+   *             time)
+   * @return The entry value
    *
    * @note This function moves the values out of the vector.
    */
diff --git a/ntcore/src/main/native/include/networktables/RpcCall.h b/ntcore/src/main/native/include/networktables/RpcCall.h
index 7d83140..fc2e0bf 100644
--- a/ntcore/src/main/native/include/networktables/RpcCall.h
+++ b/ntcore/src/main/native/include/networktables/RpcCall.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -36,7 +36,7 @@
    */
   RpcCall(NT_Entry entry, NT_RpcCall call) : m_entry(entry), m_call(call) {}
 
-  RpcCall(RpcCall&& other);
+  RpcCall(RpcCall&& other) noexcept;
   RpcCall(const RpcCall&) = delete;
   RpcCall& operator=(const RpcCall&) = delete;
 
diff --git a/ntcore/src/main/native/include/networktables/RpcCall.inl b/ntcore/src/main/native/include/networktables/RpcCall.inl
index d7dacf5..0e9b522 100644
--- a/ntcore/src/main/native/include/networktables/RpcCall.inl
+++ b/ntcore/src/main/native/include/networktables/RpcCall.inl
@@ -12,7 +12,7 @@
 
 namespace nt {
 
-inline RpcCall::RpcCall(RpcCall&& other) : RpcCall() {
+inline RpcCall::RpcCall(RpcCall&& other) noexcept : RpcCall() {
   swap(*this, other);
 }
 
diff --git a/ntcore/src/main/native/include/ntcore_cpp.h b/ntcore/src/main/native/include/ntcore_cpp.h
index 56cb5af..d7e91ad 100644
--- a/ntcore/src/main/native/include/ntcore_cpp.h
+++ b/ntcore/src/main/native/include/ntcore_cpp.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -79,19 +79,19 @@
   std::string remote_ip;
 
   /** The port number of the remote node. */
-  unsigned int remote_port;
+  unsigned int remote_port{0};
 
   /**
    * The last time any update was received from the remote node (same scale as
    * returned by nt::Now()).
    */
-  uint64_t last_update;
+  uint64_t last_update{0};
 
   /**
    * The protocol version being used for this connection.  This in protocol
    * layer format, so 0x0200 = 2.0, 0x0300 = 3.0).
    */
-  unsigned int protocol_version;
+  unsigned int protocol_version{0};
 
   friend void swap(ConnectionInfo& first, ConnectionInfo& second) {
     using std::swap;
@@ -179,7 +179,7 @@
 /** NetworkTables Entry Notification */
 class EntryNotification {
  public:
-  EntryNotification() : listener(0), entry(0) {}
+  EntryNotification() : listener(0), entry(0), flags(0) {}
   EntryNotification(NT_EntryListener listener_, NT_Entry entry_,
                     StringRef name_, std::shared_ptr<Value> value_,
                     unsigned int flags_)
diff --git a/ntcore/src/main/native/include/tables/ITableListener.h b/ntcore/src/main/native/include/tables/ITableListener.h
index e836b51..dae6f85 100644
--- a/ntcore/src/main/native/include/tables/ITableListener.h
+++ b/ntcore/src/main/native/include/tables/ITableListener.h
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -18,6 +18,9 @@
 #ifdef __GNUC__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif _WIN32
+#pragma warning(push)
+#pragma warning(disable : 4996)
 #endif
 
 class ITable;
@@ -58,6 +61,8 @@
 
 #ifdef __GNUC__
 #pragma GCC diagnostic pop
+#elif _WIN32
+#pragma warning(pop)
 #endif
 
 #endif  // NTCORE_TABLES_ITABLELISTENER_H_
diff --git a/ntcore/src/test/java/edu/wpi/first/networktables/NetworkTableTest.java b/ntcore/src/test/java/edu/wpi/first/networktables/NetworkTableTest.java
index e45f197..71ce0ae 100644
--- a/ntcore/src/test/java/edu/wpi/first/networktables/NetworkTableTest.java
+++ b/ntcore/src/test/java/edu/wpi/first/networktables/NetworkTableTest.java
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -8,6 +8,7 @@
 package edu.wpi.first.networktables;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.stream.Stream;
 
@@ -65,8 +66,8 @@
 
   private static Stream<Arguments> getHierarchyArguments() {
     return Stream.of(
-        Arguments.of(Arrays.asList("/"), ""),
-        Arguments.of(Arrays.asList("/"), "/"),
+        Arguments.of(Collections.singletonList("/"), ""),
+        Arguments.of(Collections.singletonList("/"), "/"),
         Arguments.of(Arrays.asList("/", "/foo", "/foo/bar", "/foo/bar/baz"), "/foo/bar/baz"),
         Arguments.of(Arrays.asList("/", "/foo", "/foo/bar", "/foo/bar/"), "/foo/bar/")
     );
diff --git a/ntcore/src/test/native/cpp/EntryNotifierTest.cpp b/ntcore/src/test/native/cpp/EntryNotifierTest.cpp
index 4f1df77..604db3d 100644
--- a/ntcore/src/test/native/cpp/EntryNotifierTest.cpp
+++ b/ntcore/src/test/native/cpp/EntryNotifierTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-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.                                                               */
@@ -12,10 +12,10 @@
 #include "ValueMatcher.h"
 #include "gtest/gtest.h"
 
+using ::testing::_;
 using ::testing::AnyNumber;
 using ::testing::IsNull;
 using ::testing::Return;
-using ::testing::_;
 
 namespace nt {
 
diff --git a/ntcore/src/test/native/cpp/StorageTest.cpp b/ntcore/src/test/native/cpp/StorageTest.cpp
index 47c1096..f271123 100644
--- a/ntcore/src/test/native/cpp/StorageTest.cpp
+++ b/ntcore/src/test/native/cpp/StorageTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
@@ -18,10 +18,10 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
+using ::testing::_;
 using ::testing::AnyNumber;
 using ::testing::IsNull;
 using ::testing::Return;
-using ::testing::_;
 
 namespace nt {
 
@@ -981,13 +981,13 @@
   EXPECT_TRUE(storage.GetEntries("", 0).empty());
 }
 
-INSTANTIATE_TEST_CASE_P(StorageTestsEmpty, StorageTestEmpty,
-                        ::testing::Bool(), );
-INSTANTIATE_TEST_CASE_P(StorageTestsPopulateOne, StorageTestPopulateOne,
-                        ::testing::Bool(), );
-INSTANTIATE_TEST_CASE_P(StorageTestsPopulated, StorageTestPopulated,
-                        ::testing::Bool(), );
-INSTANTIATE_TEST_CASE_P(StorageTestsPersistent, StorageTestPersistent,
-                        ::testing::Bool(), );
+INSTANTIATE_TEST_SUITE_P(StorageTestsEmpty, StorageTestEmpty,
+                         ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(StorageTestsPopulateOne, StorageTestPopulateOne,
+                         ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(StorageTestsPopulated, StorageTestPopulated,
+                         ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(StorageTestsPersistent, StorageTestPersistent,
+                         ::testing::Bool());
 
 }  // namespace nt
diff --git a/ntcore/src/test/native/cpp/WireDecoderTest.cpp b/ntcore/src/test/native/cpp/WireDecoderTest.cpp
index a13fa7a..e32f909 100644
--- a/ntcore/src/test/native/cpp/WireDecoderTest.cpp
+++ b/ntcore/src/test/native/cpp/WireDecoderTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */
diff --git a/ntcore/src/test/native/cpp/WireEncoderTest.cpp b/ntcore/src/test/native/cpp/WireEncoderTest.cpp
index 664344f..fab5a22 100644
--- a/ntcore/src/test/native/cpp/WireEncoderTest.cpp
+++ b/ntcore/src/test/native/cpp/WireEncoderTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-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.                                                               */