/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class RacyLoader extends DefiningLoader {
static {
// For JVM, register as parallel capable.
// Android treats all class loaders as parallel capable and makes this a no-op.
registerAsParallelCapable();
}
private Object lock = new Object();
private int index = 0;
private int count;
private DefiningLoader[] defining_loaders;
public RacyLoader(ClassLoader parent, int count) {
super(parent);
this.count = count;
defining_loaders = new DefiningLoader[2];
for (int i = 0; i != defining_loaders.length; ++i) {
defining_loaders[i] = new DefiningLoader(parent);
}
}
protected Class<?> findClass(String name) throws ClassNotFoundException
{
if (name.equals("Test") || name.equals("Test3")) {
throw new Error("Unexpected RacyLoader.findClass(\"" + name + "\")");
}
return super.findClass(name);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
if (name.equals("Test") || name.equals("Test3")) {
int my_index = syncWithOtherInstances(count);
Class<?> result = defining_loaders[my_index & 1].loadClass(name, resolve);
syncWithOtherInstances(2 * count);
return result;
}
return super.loadClass(name, resolve);
}
private int syncWithOtherInstances(int limit) {
int my_index;
synchronized (lock) {
my_index = index;
++index;
if (index != limit) {
do {
try {
lock.wait();
} catch (InterruptedException ie) {
throw new Error(ie);
}
} while (index < limit);
} else {
lock.notifyAll();
}
}
return my_index;
}
}