Introduced concurrency fixes as done in https://github.com/openhab/openhab/pull/3016

Signed-off-by: Kai Kreuzer <kai@openhab.org>
pull/20/head
Kai Kreuzer 2016-02-17 09:46:30 +01:00
parent c7c6e2965f
commit 6f0a7acbf6
1 changed files with 107 additions and 88 deletions

View File

@ -13,7 +13,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@ -25,11 +24,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>This abstract class serves as a basis for implementations of binding providers that retrieve binding
* information from the items configuration file(s), i.e. they register as {@link BindingConfigReader}s.</p>
* <p>
* This abstract class serves as a basis for implementations of binding providers that retrieve binding
* information from the items configuration file(s), i.e. they register as {@link BindingConfigReader}s.
* </p>
*
* <p>This class takes care of tracking all changes in the binding config strings and makes sure that all
* listeners are correctly notified of any change.<p>
* <p>
* This class takes care of tracking all changes in the binding config strings and makes sure that all
* listeners are correctly notified of any change.
* <p>
*
* @author Kai Kreuzer
* @since 0.6.0
@ -42,7 +45,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
private Set<BindingChangeListener> listeners = new CopyOnWriteArraySet<BindingChangeListener>();
/** caches binding configurations. maps itemNames to {@link BindingConfig}s */
protected Map<String, BindingConfig> bindingConfigs = new ConcurrentHashMap<String, BindingConfig>(new WeakHashMap<String, BindingConfig>());
protected Map<String, BindingConfig> bindingConfigs = new ConcurrentHashMap<String, BindingConfig>();
/**
* stores information about the context of items. The map has this content
@ -50,7 +53,6 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
*/
protected Map<String, Set<Item>> contextMap = new ConcurrentHashMap<String, Set<Item>>();
public AbstractGenericBindingProvider() {
super();
}
@ -58,6 +60,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* {@inheritDoc}
*/
@Override
public void addBindingChangeListener(BindingChangeListener listener) {
listeners.add(listener);
}
@ -65,6 +68,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* {@inheritDoc}
*/
@Override
public void removeBindingChangeListener(BindingChangeListener listener) {
listeners.remove(listener);
}
@ -72,28 +76,40 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* {@inheritDoc}
*/
public void processBindingConfiguration(String context, Item item, String bindingConfig) throws BindingConfigParseException {
@Override
public void processBindingConfiguration(String context, Item item, String bindingConfig)
throws BindingConfigParseException {
if (context == null) {
throw new BindingConfigParseException("null context is not permitted for item " + item.getName());
}
synchronized (contextMap) {
Set<Item> items = contextMap.get(context);
if (items == null) {
items = new HashSet<Item>();
contextMap.put(context, items);
}
items.add(item);
}
}
/**
* {@inheritDoc}
*/
@Override
public void removeConfigurations(String context) {
Set<Item> items = contextMap.get(context);
Set<Item> items = null;
synchronized (contextMap) {
items = contextMap.get(context);
if (items != null) {
contextMap.remove(context);
}
}
if (items != null) {
for (Item item : items) {
// we remove all binding configurations for all items
bindingConfigs.remove(item.getName());
notifyListeners(item);
}
contextMap.remove(context);
}
}
@ -115,6 +131,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* @{inheritDoc}
*/
@Override
public boolean providesBindingFor(String itemName) {
return bindingConfigs.get(itemName) != null;
}
@ -122,6 +139,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* @{inheritDoc}
*/
@Override
public boolean providesBinding() {
return !bindingConfigs.isEmpty();
}
@ -129,6 +147,7 @@ public abstract class AbstractGenericBindingProvider implements BindingConfigRea
/**
* {@inheritDoc}
*/
@Override
public Collection<String> getItemNames() {
return new ArrayList<String>(bindingConfigs.keySet());
}