OPENJPA-2099: Introduce flexible ThreadLocal

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1235624 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2012-01-25 04:00:11 +00:00
parent ade97ac4d4
commit f31e4ba507
2 changed files with 73 additions and 23 deletions

View File

@ -18,10 +18,8 @@
*/
package org.apache.openjpa.jdbc.sql;
import java.util.HashMap;
import java.util.Map;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.lib.util.FlexibleThreadLocal;
/**
@ -54,7 +52,7 @@ public class BindParameter {
private final Column _column;
// key of this parameter
private final Object _key;
private Map<Thread, Object> _value = new HashMap<Thread, Object>();
private FlexibleThreadLocal<Object> _values = new FlexibleThreadLocal<Object>();
/**
* Constructs a parameter with given key, column and user flag.
@ -70,7 +68,7 @@ public class BindParameter {
_key = key;
_user = user;
_column = column;
_value.put(Thread.currentThread(), value);
_values.set(value);
}
/**
@ -80,26 +78,14 @@ public class BindParameter {
* to this parameter.
*/
public Object getValue() {
Thread current = Thread.currentThread();
if (!_value.containsKey(current)) {
// calling thread may be a child of the thread that inserted the value.
// This is for SliceThread
for (Map.Entry<Thread, Object> e : _value.entrySet()) {
if (isEquivalent(e.getKey(), current))
return e.getValue();
}
throw new IllegalStateException("No value for " + current
+ ". Known threads " + _value.keySet());
}
return _value.get(current);
return _values.get();
}
/**
* Binds the given value to this parameter. Can be null.
*/
public void setValue(Object value) {
_value.put(Thread.currentThread(),value);
_values.set(value);
}
/**
@ -124,8 +110,4 @@ public class BindParameter {
return _key;
}
boolean isEquivalent(Thread a, Thread b) {
if (a == b) return true;
return a.equals(b) || b.equals(a);
}
}

View File

@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.openjpa.lib.util;
import java.util.HashMap;
import java.util.Map;
/**
* A thread-specific storage similar to {@link ThreadLocal}.
*
* @author Pinaki Poddar
*
*/
public class FlexibleThreadLocal<T> {
private final Map<Thread, T> _values = new HashMap<Thread, T>();
/**
* Gets the value associated with the calling thread or its equivalent.
*
* @see #isEquivalent(Thread, Thread)
*/
public T get() {
Thread current = Thread.currentThread();
if (_values.containsKey(current)) {
return _values.get(current);
} else {
for (Map.Entry<Thread, T> e : _values.entrySet()) {
if (isEquivalent(e.getKey(), current))
return e.getValue();
}
}
return null;
}
/**
* Associates the value to the current thread.
*/
public T set(T t) {
return _values.put(Thread.currentThread(), t);
}
/**
* Affirms if the two given thread are equivalent.
* Equivalence takes asymmetric equality in account.
*/
protected boolean isEquivalent(Thread a, Thread b) {
if (a == b) return true;
if (a == null || b== null) return false;
return a.equals(b) || b.equals(a);
}
}