|
1 | | ---- |
2 | | -name: marslib-threading |
3 | | -description: Dictates the elite standard for writing custom java Thread instances in MARSLib, strictly enforcing time-unit sleeping and interrupt safeties to prevent loop lockups. |
4 | | ---- |
5 | | - |
6 | | -# MARSLib Threading Standards |
7 | | - |
8 | | -Any time you are tasked with creating a background loop (e.g., `PhoenixOdometryThread`, a Custom Coprocessor Listener, or I2C buffer queues) it must be perfectly thread-safe and adhere to MARSLib's `ProjectDoctor` linting standards. |
9 | | - |
10 | | -## 1. No Infinite Loops |
11 | | -NEVER write `while (true)` inside a `run()` loop. The JVM handles thread interruption automatically during RoboRIO code restarts or autonomous transitions. |
12 | | -**Always use:** |
13 | | -```java |
14 | | -@Override |
15 | | -public void run() { |
16 | | - while (!Thread.currentThread().isInterrupted()) { |
17 | | - // ... Logic ... |
18 | | - } |
19 | | -} |
20 | | -``` |
21 | | - |
22 | | -## 2. No Raw Thread Sleeps |
23 | | -ProjectDoctor explicitly flags `Thread.sleep(...)` as a dangerous blocking call because it's ambiguous what unit of time is being requested, often leading to 20ms delays becoming 20 second loop lockups. |
24 | | - |
25 | | -**Always use `java.util.concurrent.TimeUnit`:** |
26 | | -```java |
27 | | -try { |
28 | | - TimeUnit.MILLISECONDS.sleep(20); |
29 | | -} catch (InterruptedException e) { |
30 | | - Thread.currentThread().interrupt(); // Restore interrupt status |
31 | | - break; // Safely exit the loop |
32 | | -} |
33 | | -``` |
34 | | -Never swallow the `InterruptedException`. You must properly re-assert the interrupt state to gracefully shut down the thread pool. |
| 1 | +--- |
| 2 | +name: marslib-threading |
| 3 | +description: Dictates the elite standard for writing custom java Thread instances in MARSLib, strictly enforcing time-unit sleeping and interrupt safeties to prevent loop lockups. |
| 4 | +--- |
| 5 | + |
| 6 | +# MARSLib Threading Standards |
| 7 | + |
| 8 | +Any time you are tasked with creating a background loop (e.g., `PhoenixOdometryThread`, a Custom Coprocessor Listener, or I2C buffer queues) it must be perfectly thread-safe and adhere to MARSLib's `ProjectDoctor` linting standards. |
| 9 | + |
| 10 | +## 1. No Infinite Loops |
| 11 | +NEVER write `while (true)` inside a `run()` loop. The JVM handles thread interruption automatically during RoboRIO code restarts or autonomous transitions. |
| 12 | +**Always use:** |
| 13 | +```java |
| 14 | +@Override |
| 15 | +public void run() { |
| 16 | + while (!Thread.currentThread().isInterrupted()) { |
| 17 | + // ... Logic ... |
| 18 | + } |
| 19 | +} |
| 20 | +``` |
| 21 | + |
| 22 | +## 2. No Raw Thread Sleeps |
| 23 | +ProjectDoctor explicitly flags `Thread.sleep(...)` as a dangerous blocking call because it's ambiguous what unit of time is being requested, often leading to 20ms delays becoming 20 second loop lockups. |
| 24 | + |
| 25 | +**Always use `java.util.concurrent.TimeUnit`:** |
| 26 | +```java |
| 27 | +try { |
| 28 | + TimeUnit.MILLISECONDS.sleep(20); |
| 29 | +} catch (InterruptedException e) { |
| 30 | + Thread.currentThread().interrupt(); // Restore interrupt status |
| 31 | + break; // Safely exit the loop |
| 32 | +} |
| 33 | +``` |
| 34 | +Never swallow the `InterruptedException`. You must properly re-assert the interrupt state to gracefully shut down the thread pool. |
| 35 | + |
| 36 | +## 3. Cache References in Constructor (No Hot Path Synchronization) |
| 37 | +Under zero circumstances should a 50Hz periodic loop (`updateInputs()`, `periodic()`, `execute()`) interact with a `synchronized` method or invoke `.getInstance()` of a continuous thread or Singleton. Doing so forces the fast periodic loop to compete for CPU lock availability with the thread's background loop, resulting in Lock Contention jitter. |
| 38 | + |
| 39 | +**Always cache the Thread's exact memory address in the constructor:** |
| 40 | +```java |
| 41 | +public class MySwerveModule { |
| 42 | + // Hold a persistent hard reference to the memory location |
| 43 | + private final PhoenixOdometryThread odometryThread; |
| 44 | + |
| 45 | + public MySwerveModule() { |
| 46 | + // Cross the synchronized bridge EXACTLY ONCE on boot |
| 47 | + this.odometryThread = PhoenixOdometryThread.getInstance(); |
| 48 | + } |
| 49 | + |
| 50 | + public void updateInputs() { |
| 51 | + // Direct, instantaneous memory poll with zero lock contention |
| 52 | + var data = this.odometryThread.getLatestData(); |
| 53 | + } |
| 54 | +} |
| 55 | +``` |
0 commit comments