Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Refactor Context classes #81

Merged
merged 9 commits into from
Apr 19, 2024
436 changes: 12 additions & 424 deletions src/main/java/com/team766/framework/Context.java

Large diffs are not rendered by default.

480 changes: 480 additions & 0 deletions src/main/java/com/team766/framework/ContextImpl.java

Large diffs are not rendered by default.

45 changes: 3 additions & 42 deletions src/main/java/com/team766/framework/ContextWithValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,14 @@
* A {@link Context} that also allows the ProcedureWithValues running on it to yield values when
* running asynchronously.
*/
public class ContextWithValue<T> extends Context implements LaunchedContextWithValue<T> {

private T m_lastYieldedValue;

@SuppressWarnings("unchecked")
ContextWithValue(final RunnableWithContextWithValue<T> func, final Context parentContext) {
super((context) -> func.run((ContextWithValue<T>) context), parentContext);
}

@SuppressWarnings("unchecked")
ContextWithValue(final RunnableWithContextWithValue<T> func) {
super((context) -> func.run((ContextWithValue<T>) context));
}

/**
* Return the most recent value passed to yield(T).
*
* Implements LaunchedContextWithValue<T>
*/
@Override
public T lastYieldedValue() {
return m_lastYieldedValue;
}

/**
* Return the most recent value passed to yield(T), and clear the recorded last yielded value
* such that subsequent calls to lastYieldedValue() will return null.
*
* Implements LaunchedContextWithValue<T>
*/
@Override
public T getAndClearLastYieldedValue() {
final var result = m_lastYieldedValue;
m_lastYieldedValue = null;
return result;
}

public interface ContextWithValue<T> extends Context {
/**
* Momentarily pause execution of this Context to allow other Contexts to execute. Execution of
* this Context will resume as soon as possible after the other Contexts have been given a
* chance to run.
*
* The most recent value passed to this yield(T) method will be returned by subsequent calls to
* lastYieldedValue().
* LaunchedContextWithValue.lastYieldedValue().
*/
public void yield(final T valueToYield) {
m_lastYieldedValue = valueToYield;
this.yield();
}
void yield(final T valueToYield);
}
16 changes: 10 additions & 6 deletions src/main/java/com/team766/framework/LaunchedContextWithValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
public interface LaunchedContextWithValue<T> extends LaunchedContext {
/**
* Return the most recent value that the Procedure passed to Context.yield(T).
*
* Implements LaunchedContextWithValue<T>
* Return null if a value has never been yielded, or a value has not been yielded since the last
* call to getAndClearLastYieldedValue.
*/
T lastYieldedValue();

/**
* Return true if a has been yielded by the Procedure since since the last call to
* getAndClearLastYieldedValue. Return false otherwise.
*/
boolean hasYieldedValue();

/**
* Return the most recent value that the Procedure passed to Context.yield(T), and clear the
* recorded last yielded value such that subsequent calls to lastYieldedValue() will return
* null.
*
* Implements LaunchedContextWithValue<T>
* recorded last yielded value such that subsequent calls to hasYieldedValue() will return
* false.
*/
T getAndClearLastYieldedValue();
}
12 changes: 7 additions & 5 deletions src/main/java/com/team766/framework/Mechanism.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.team766.logging.Severity;

public abstract class Mechanism extends LoggingBase {
private Context m_owningContext = null;
private ContextImpl<?> m_owningContext = null;
private Thread m_runningPeriodic = null;

public Mechanism() {
Expand Down Expand Up @@ -44,9 +44,11 @@ public String getName() {
}

protected void checkContextOwnership() {
if (Context.currentContext() != m_owningContext && m_runningPeriodic == null) {
if (ContextImpl.currentContext() != m_owningContext && m_runningPeriodic == null) {
String message =
getName() + " tried to be used by " + Context.currentContext().getContextName();
getName()
+ " tried to be used by "
+ ContextImpl.currentContext().getContextName();
if (m_owningContext != null) {
message += " while owned by " + m_owningContext.getContextName();
} else {
Expand All @@ -57,7 +59,7 @@ protected void checkContextOwnership() {
}
}

void takeOwnership(final Context context, final Context parentContext) {
void takeOwnership(final ContextImpl<?> context, final ContextImpl<?> parentContext) {
if (m_owningContext != null && m_owningContext == parentContext) {
Logger.get(Category.FRAMEWORK)
.logRaw(
Expand Down Expand Up @@ -102,7 +104,7 @@ void takeOwnership(final Context context, final Context parentContext) {
m_owningContext = context;
}

void releaseOwnership(final Context context) {
void releaseOwnership(final ContextImpl<?> context) {
if (m_owningContext != context) {
LoggerExceptionUtils.logException(
new Exception(
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/team766/framework/Scheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ public void reset() {
}

public LaunchedContext startAsync(final RunnableWithContext func) {
return new Context(func);
return new ContextImpl<>(func::run);
}

public <T> LaunchedContext startAsync(final RunnableWithContextWithValue<T> func) {
return new ContextWithValue<T>(func);
public <T> LaunchedContextWithValue<T> startAsync(final RunnableWithContextWithValue<T> func) {
return new ContextImpl<T>(func);
}

public LaunchedContext startAsync(final Runnable func) {
return new Context(func);
return new ContextImpl<>(func);
}

public void run() {
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/com/team766/framework/TimedPredicateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class TimedPredicateTest {
@Test
public void testTimedPredicateTimedOut() {
MockClock testClock = new MockClock(1710411240.0);
Context.TimedPredicate predicate =
new Context.TimedPredicate(testClock, () -> false, 1.766);
ContextImpl.TimedPredicate predicate =
new ContextImpl.TimedPredicate(testClock, () -> false, 1.766);
assertFalse(predicate.getAsBoolean());
testClock.tick(1.0);
assertFalse(predicate.getAsBoolean());
Expand All @@ -24,8 +24,8 @@ public void testTimedPredicateTimedOut() {
@Test
public void testTimedPredicateCondition() {
MockClock testClock = new MockClock(1710411240.0);
Context.TimedPredicate predicate =
new Context.TimedPredicate(
ContextImpl.TimedPredicate predicate =
new ContextImpl.TimedPredicate(
testClock,
new BooleanSupplier() {
private int counter = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/test/java/com/team766/framework/YieldWithValueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ private static class ValueConsumer extends Procedure {
@Override
public void run(Context context) {
var generator = context.startAsync(new ValueGenerator());

assertNull(
generator.lastYieldedValue(),
"lastYieldedValue should be null before the procedure yields a value");

while (generator.lastYieldedValue() == null || generator.lastYieldedValue() < 10) {
var value = generator.lastYieldedValue();
if (value != null) {
Expand Down
Loading