Skip to content

Commit e7d9c04

Browse files
author
James Hagborg
committed
Thread-safety improvements
- You should now be able to safely add an event to the PeriodicScheduler from within a scheduled event - You should be able to share Preference and PreferencesSet objects across multiple threads. Note that onPreferencesUpdated still always runs in the main thread, but you may call get() from any thread.
1 parent d7f6b2a commit e7d9c04

File tree

7 files changed

+27
-18
lines changed

7 files changed

+27
-18
lines changed

src/main/java/org/usfirst/frc/team69/util/PeriodicScheduler.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public class PeriodicScheduler {
1919
private static PeriodicScheduler theInstance;
2020

2121
/**
22-
* Return the single instance of {@link PeriodicScheduler}
22+
* Return the single instance of {@link PeriodicScheduler}. It is safe to
23+
* call this method from any thread.
2324
*
2425
* @return The sinlge instance of {@link PeriodicScheduler}
2526
*/
@@ -40,6 +41,9 @@ private PeriodicScheduler() {
4041
* time {@link #run()} is called. If using {@link HYPERRobot}, this
4142
* happens once every autonomousPeriodic, teleopPeriodic, and disabledPeriodic.
4243
*
44+
* As of hyperLib 0.3.1, it is safe to call this from within an event,
45+
* and to call it from any thread.
46+
*
4347
* @param event A {@link Runnable} object representing the task to run
4448
*/
4549
public synchronized void addEvent(Runnable event) {
@@ -51,8 +55,10 @@ public synchronized void addEvent(Runnable event) {
5155
* are using {@link HYPERRobot}, you do not need to call this manually.
5256
*/
5357
public synchronized void run() {
54-
for (Runnable event : events) {
55-
event.run();
58+
/* If we use an iterator, then callind addEvent from an event itself
59+
* will cause a ConcurrentModificationException */
60+
for (int i = 0; i < events.size(); i++) {
61+
events.get(i).run();
5662
}
5763
}
5864
}

src/main/java/org/usfirst/frc/team69/util/pref/BooleanPreference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
public class BooleanPreference extends Preference {
1212
private boolean m_lastValue;
13-
private boolean m_default;
13+
private final boolean m_default;
1414

1515
/**
1616
* Create a {@link BooleanPreference} object tracking the preference with
@@ -30,7 +30,7 @@ public BooleanPreference(String name, boolean value) {
3030
* {@inheritDoc}
3131
*/
3232
@Override
33-
public boolean hasChanged() {
33+
public synchronized boolean hasChanged() {
3434
boolean newValue = get();
3535
boolean changed = newValue != m_lastValue;
3636
m_lastValue = newValue;

src/main/java/org/usfirst/frc/team69/util/pref/DoublePreference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
public class DoublePreference extends Preference {
1212
private double m_lastValue;
13-
private double m_default;
13+
private final double m_default;
1414

1515
/**
1616
* Create a {@link DoublePreference} object tracking the preference with
@@ -30,7 +30,7 @@ public DoublePreference(String name, double value) {
3030
* {@inheritDoc}
3131
*/
3232
@Override
33-
public boolean hasChanged() {
33+
public synchronized boolean hasChanged() {
3434
double newValue = get();
3535
boolean changed = newValue != m_lastValue;
3636
m_lastValue = newValue;

src/main/java/org/usfirst/frc/team69/util/pref/IntPreference.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import edu.wpi.first.wpilibj.Preferences;
44

55
/**
6-
* A class which represents an ineger-valued preference
6+
* A class which represents an integer-valued preference
77
*
88
* @author James Hagborg
99
*
1010
*/
1111
public class IntPreference extends Preference {
1212
private int m_lastValue;
13-
private int m_default;
13+
private final int m_default;
1414

1515
/**
1616
* Create a {@link IntPreference} object tracking the preference with
@@ -30,7 +30,7 @@ public IntPreference(String name, int value) {
3030
* {@inheritDoc}
3131
*/
3232
@Override
33-
public boolean hasChanged() {
33+
public synchronized boolean hasChanged() {
3434
int newValue = get();
3535
boolean changed = newValue != m_lastValue;
3636
m_lastValue = newValue;

src/main/java/org/usfirst/frc/team69/util/pref/Preference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ public String getName() {
4545

4646
/**
4747
* Check if a preference with the same name as this one already exists
48-
* in the preferences fil. If not, then create the preference using
48+
* in the preferences file. If not, then create the preference using
4949
* the default value.
5050
*/
51-
public void putDefaultIfEmpty() {
51+
public synchronized void putDefaultIfEmpty() {
5252
if (!Preferences.getInstance().containsKey(m_name)) {
5353
putDefaultValue();
5454
}

src/main/java/org/usfirst/frc/team69/util/pref/PreferencesSet.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
* Example use-cases are subsystems, PID controllers, and specific tasks like
1414
* vision and driving, which may have many related preferences.
1515
*
16+
* It is safe to share this object, as well as the Preference objects it
17+
* creates, among multiple threads.
18+
*
1619
* @author James Hagborg
1720
*
1821
*/
@@ -22,10 +25,10 @@ public class PreferencesSet {
2225
private final String m_name;
2326
private final PreferencesListener m_listener;
2427

25-
private ArrayList<Preference> m_preferences = new ArrayList<Preference>();
26-
private HashSet<String> m_prefNames = new HashSet<String>();
28+
private final ArrayList<Preference> m_preferences = new ArrayList<Preference>();
29+
private final HashSet<String> m_prefNames = new HashSet<String>();
2730

28-
private static HashSet<String> setNames = new HashSet<String>();
31+
private static final HashSet<String> setNames = new HashSet<String>();
2932

3033
/**
3134
* Check the set name does not exist and add it if it does. This needs to
@@ -82,7 +85,7 @@ public String getName() {
8285
return m_name;
8386
}
8487

85-
private void checkForUpdates() {
88+
private synchronized void checkForUpdates() {
8689
boolean hasChanged = false;
8790

8891
for (Preference pref : m_preferences) {

src/main/java/org/usfirst/frc/team69/util/pref/StringPreference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
public class StringPreference extends Preference {
1212
private String m_lastValue;
13-
private String m_default;
13+
private final String m_default;
1414

1515
/**
1616
* Create a {@link StringPreference} object tracking the preference with
@@ -35,7 +35,7 @@ public StringPreference(String name, String value) {
3535
* {@inheritDoc}
3636
*/
3737
@Override
38-
public boolean hasChanged() {
38+
public synchronized boolean hasChanged() {
3939
String newValue = get();
4040
boolean changed = !newValue.equals(m_lastValue);
4141
m_lastValue = newValue;

0 commit comments

Comments
 (0)