Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/utils/ExclusiveExec.java @ 1129:ccfa07b88476
merged geo-backend
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:01 +0200 |
parents | f953c9a559d8 |
children |
line wrap: on
line source
/* * Copyright (c) 2010 by Intevation GmbH * * This program is free software under the LGPL (>=v2.1) * Read the file LGPL.txt coming with the software for details * or visit http://www.gnu.org/licenses/ if it does not exist. */ package de.intevation.gnv.utils; import java.util.HashMap; /** * This class can be used to synchronize threads with a given key. To use this * synchronization, you first need to do call {@link #acquire(java.lang.Object)} * to retrieve a {@link UniqueKey}. After this, you can call the code being * synchronized. After this execution, you need to call * {@link #release(UniqueKey)} with your token you retrieved from {@link * #acquire(java.lang.Object)}. A thread needs to wait for another thread if their keys * are equal. Threads with different keys don't need to wait for each other. * * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public final class ExclusiveExec { /** * The only instance of this singleton. */ public static final ExclusiveExec INSTANCE = new ExclusiveExec(); private HashMap tokens; /** * This class represents a unique key with a reference counter. */ public static class UniqueKey { Object key; int [] refs; /** * Constructs a new UniqueKey. * * @param key The key of this unique key. */ public UniqueKey(Object key) { this.key = key; refs = new int[1]; } } /** * Private constructor. Use {@link #INSTANCE} instead. */ private ExclusiveExec() { tokens = new HashMap(); } /** * This method serves a {@link UniqueKey} and starts a synchronized code * block. * * @param key The key used to identify same threads. * @return UniqueKey. Use this object to call {@link #release(UniqueKey)} * at the end of your code being synchronized. */ public UniqueKey acquire(Object key) { try { UniqueKey internalKey = null; synchronized (tokens) { internalKey = (UniqueKey)tokens.get(key); if (internalKey == null) { tokens.put(key, internalKey = new UniqueKey(key)); } } synchronized (internalKey) { ++internalKey.refs[0]; while (internalKey.refs[0] > 1) { internalKey.wait(10000L); } } return internalKey; } catch (InterruptedException ie) { return null; } } /** * This method releases a lock. Call this method at the end of your code * being synchronized. * * @param internalKey Token retrieved by {@link #acquire(Object)}. */ public void release(UniqueKey internalKey) { if (internalKey != null) { synchronized (internalKey) { if (--internalKey.refs[0] < 1) { synchronized (tokens) { tokens.remove(internalKey.key); } } internalKey.notifyAll(); } } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :