summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lesot <jplesot@google.com>2014-10-03 15:09:49 +0200
committerJean-Philippe Lesot <jplesot@google.com>2014-10-03 16:24:53 +0200
commit9de22d42db7b6a12f8f98d9d5490c27c57b58c2d (patch)
tree69d8c7c175501178a2b95d3e2e6e997e5fe01c98
parent2b4aafbc11d904ecf6a3926866bee09b768283c0 (diff)
downloadtoolchain_jack-9de22d42db7b6a12f8f98d9d5490c27c57b58c2d.zip
toolchain_jack-9de22d42db7b6a12f8f98d9d5490c27c57b58c2d.tar.gz
toolchain_jack-9de22d42db7b6a12f8f98d9d5490c27c57b58c2d.tar.bz2
Add dynamic @Synchronized support
Change-Id: I875b0902dc56a03699daa1eac95225655b3c658d
-rw-r--r--sched/src/com/android/sched/item/Synchronized.java5
-rw-r--r--sched/src/com/android/sched/marker/ManagedMarker.java4
-rw-r--r--sched/src/com/android/sched/scheduler/ManagedSchedulable.java66
-rw-r--r--sched/src/com/android/sched/scheduler/MultiWorkersScheduleInstance.java2
4 files changed, 70 insertions, 7 deletions
diff --git a/sched/src/com/android/sched/item/Synchronized.java b/sched/src/com/android/sched/item/Synchronized.java
index a504f3f..694c852 100644
--- a/sched/src/com/android/sched/item/Synchronized.java
+++ b/sched/src/com/android/sched/item/Synchronized.java
@@ -23,9 +23,10 @@ import java.lang.annotation.Target;
/**
* Annotates a {@code Schedulable} and specifies that it has to run synchronized with itself, that
- * one instance could run at most one at a time.
+ * one instance can run at most one at a time. A dynamic version can be declared by annotating a
+ * method with no parameter and that return true if that instance needs to be synchronized.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
+@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Synchronized {
}
diff --git a/sched/src/com/android/sched/marker/ManagedMarker.java b/sched/src/com/android/sched/marker/ManagedMarker.java
index 7b75f11..fe309c3 100644
--- a/sched/src/com/android/sched/marker/ManagedMarker.java
+++ b/sched/src/com/android/sched/marker/ManagedMarker.java
@@ -252,7 +252,7 @@ public class ManagedMarker implements HasDescription {
for (Class<? extends MarkerManager> marked : staticValidOn) {
if (marked.isAssignableFrom(method.getParameterTypes()[0])) {
- throw new MarkerNotConformException("Marker '" + name + "' cannot have both a static @'"
+ throw new MarkerNotConformException("Marker '" + name + "' cannot have both a static @"
+ ValidOn.class.getName() + " (on class '" + marker.getCanonicalName()
+ "') and a @" + DynamicValidOn.class.getName() + " (on method '" + method + "'");
}
@@ -262,7 +262,7 @@ public class ManagedMarker implements HasDescription {
if (dvo.validOn.isAssignableFrom(method.getParameterTypes()[0])
|| method.getParameterTypes()[0].isAssignableFrom(dvo.validOn)) {
throw new MarkerNotConformException("Marker '" + name
- + "' could not have two @'" + DynamicValidOn.class.getName() + " ('" + method
+ + "' cannot have two @" + DynamicValidOn.class.getName() + " ('" + method
+ "' and '" + dvo.method + "')");
}
}
diff --git a/sched/src/com/android/sched/scheduler/ManagedSchedulable.java b/sched/src/com/android/sched/scheduler/ManagedSchedulable.java
index 24dae82..f1edc8e 100644
--- a/sched/src/com/android/sched/scheduler/ManagedSchedulable.java
+++ b/sched/src/com/android/sched/scheduler/ManagedSchedulable.java
@@ -20,9 +20,17 @@ import com.android.sched.item.Component;
import com.android.sched.item.Description;
import com.android.sched.item.Items;
import com.android.sched.item.Synchronized;
+import com.android.sched.marker.MarkerNotConformException;
import com.android.sched.schedulable.Schedulable;
import com.android.sched.util.HasDescription;
+import com.android.sched.util.log.LoggerFactory;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
@@ -30,6 +38,8 @@ import javax.annotation.Nonnull;
*/
public abstract class ManagedSchedulable implements HasDescription {
@Nonnull
+ private static final Logger logger = LoggerFactory.getLogger();
+ @Nonnull
private final Class<? extends Schedulable> schedulable;
// @Name
@@ -42,6 +52,9 @@ public abstract class ManagedSchedulable implements HasDescription {
// @Synchronized
private boolean isSynchronized = false;
+ @CheckForNull
+ private Method dynamicIsSynchronized = null;
+
/**
* Creates a new instance of {@link ManagedSchedulable} from a {@link Schedulable}.
@@ -83,8 +96,27 @@ public abstract class ManagedSchedulable implements HasDescription {
/**
* @return if the schedulable is synchronized
*/
- public boolean isSynchronized() {
- return isSynchronized;
+ public boolean isSynchronized(@Nonnull Schedulable schedulable) {
+ if (isSynchronized) {
+ return true;
+ }
+
+ if (dynamicIsSynchronized != null) {
+ try {
+ return ((Boolean) dynamicIsSynchronized.invoke(schedulable)).booleanValue();
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError(e);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ } catch (InvocationTargetException e) {
+ logger.log(Level.WARNING, "Method '" + dynamicIsSynchronized + "' threw an exception",
+ e.getCause());
+
+ return false;
+ }
+ }
+
+ return false;
}
/**
@@ -109,5 +141,35 @@ public abstract class ManagedSchedulable implements HasDescription {
Synchronized sync = cls.getAnnotation(Synchronized.class);
isSynchronized = sync != null;
+
+ for (Method method : cls.getMethods()) {
+ Synchronized dynamicSynchronizedOnAnnotation = method.getAnnotation(Synchronized.class);
+
+ if (dynamicSynchronizedOnAnnotation != null) {
+ if (!method.getReturnType().equals(Boolean.TYPE)) {
+ throw new SchedulableNotConformException("Annotated method '" + method + "' with @"
+ + Synchronized.class.getSimpleName() + " must have a 'boolean' return type");
+ }
+
+ if (method.getParameterTypes().length != 0) {
+ throw new SchedulableNotConformException("Annotated method '" + method + "' with @"
+ + Synchronized.class.getSimpleName() + " must have no parameter");
+ }
+
+ if (isSynchronized) {
+ throw new SchedulableNotConformException("Schedulable '" + name
+ + "' cannot have both a static and a dynamic @" + Synchronized.class.getName()
+ + " (on class '" + cls.getCanonicalName() + "')");
+ }
+
+ if (dynamicIsSynchronized != null) {
+ throw new MarkerNotConformException("Schedulable '" + name + "' cannot have two @"
+ + Synchronized.class.getName() + " ('" + method + "' and '" + dynamicIsSynchronized
+ + "')");
+ }
+
+ dynamicIsSynchronized = method;
+ }
+ }
}
}
diff --git a/sched/src/com/android/sched/scheduler/MultiWorkersScheduleInstance.java b/sched/src/com/android/sched/scheduler/MultiWorkersScheduleInstance.java
index 9399c99..59105f3 100644
--- a/sched/src/com/android/sched/scheduler/MultiWorkersScheduleInstance.java
+++ b/sched/src/com/android/sched/scheduler/MultiWorkersScheduleInstance.java
@@ -89,7 +89,7 @@ public class MultiWorkersScheduleInstance<T extends Component>
if (isSynchronizedManaged) {
int idx = 0;
for (PlanStep step : plan) {
- if (step.getManagedSchedulable().isSynchronized()) {
+ if (step.getManagedSchedulable().isSynchronized(steps[idx].instance)) {
syncs[idx] = new Synchronized();
}
++idx;