com.astamuse.asta4d.data.ContextBindData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asta4d-core Show documentation
Show all versions of asta4d-core Show documentation
core functionalities of asta4d framework, including template and snippt implemention
/*
* Copyright 2012 astamuse company,Ltd.
*
* 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.
*
*/
package com.astamuse.asta4d.data;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.astamuse.asta4d.Context;
/**
* a ContextBindData is supposed to be cache in the current thread Context and
* should only be initialized once
*
* @author e-ryu
*
* @param
*/
public abstract class ContextBindData {
private final static String MapKey = "##MapKey##" + ContextBindData.class.getName();
private static class DataWithLock {
volatile Object data = null;
volatile boolean valid = false;
// final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
}
private String bindKey = this.getClass().getName() + "##bind-key##23@23@@23";
private boolean contextSynchronizable;
/**
* The default constructor is for convenience of lazy load data
*/
public ContextBindData() {
this(false);
}
/**
* If contextSynchronizable is set to false, no synchronization operations
* will be performed and it is just a convenience for lazy load data.
*
* Otherwise, if contextSynchronizable is set to true, a Context based lock
* will be performed and the data will be load only once in the current
* context environment.
*
* @param doSynchronize
*/
public ContextBindData(boolean contextSynchronizable) {
this.contextSynchronizable = contextSynchronizable;
if (contextSynchronizable) {
Context context = Context.getCurrentThreadContext();
ConcurrentMap map = context.getData(MapKey);
Object obj = map.get(bindKey);
if (obj == null) {
obj = new DataWithLock();
obj = map.putIfAbsent(bindKey, obj);
}
}
}
public final static void initConext(Context context) {
ConcurrentMap map = new ConcurrentHashMap<>();
context.setData(MapKey, map);
}
public T get() {
if (contextSynchronizable) {
return getDataSynchronously();
} else {
Context context = Context.getCurrentThreadContext();
T data = context.getData(bindKey);
if (data == null) {
data = buildData();
context.setData(bindKey, data);
}
return data;
}
}
@SuppressWarnings("unchecked")
private T getDataSynchronously() {
Context context = Context.getCurrentThreadContext();
ConcurrentMap map = context.getData(MapKey);
// map will not be null since we have initialized it in constructor
DataWithLock dl = (DataWithLock) map.get(bindKey);
if (!dl.valid) {
Object data;
// TODO I want to read jvm code...
synchronized (dl) {
if (!dl.valid) {
data = dl.data;
if (data == null) {
data = buildData();
dl.data = data;
}
dl.valid = true;
}
}
}
return (T) dl.data;
}
protected abstract T buildData();
}