| /* |
| * 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. |
| */ |
| |
| #ifndef _DECAF_UTIL_CONCURRENTSTLMAP_H_ |
| #define _DECAF_UTIL_CONCURRENTSTLMAP_H_ |
| |
| #include <map> |
| #include <vector> |
| #include <decaf/util/NoSuchElementException.h> |
| #include <decaf/util/concurrent/Synchronizable.h> |
| #include <decaf/util/concurrent/ConcurrentMap.h> |
| #include <decaf/util/concurrent/Mutex.h> |
| #include <decaf/util/ConcurrentModificationException.h> |
| #include <decaf/util/Map.h> |
| #include <decaf/util/AbstractCollection.h> |
| #include <decaf/util/AbstractSet.h> |
| #include <decaf/util/Iterator.h> |
| #include <decaf/lang/Pointer.h> |
| |
| namespace decaf { |
| namespace util { |
| namespace concurrent { |
| |
| /** |
| * Map template that wraps around a std::map to provide a more user-friendly |
| * interface and to provide common functions that do not exist in std::map. |
| * |
| * This version of Map extends the ConcurrentMap inteface and implements all |
| * the methods defined in that interface. Unlike a Java ConcurrentHashMap this |
| * implementations synchronizes all methods such that any call to this class |
| * will block if another thread is already holding a lock, much like the |
| * Java HashTable. |
| * |
| * @since 1.0 |
| */ |
| template <typename K, typename V, typename COMPARATOR = std::less<K> > |
| class ConcurrentStlMap : public ConcurrentMap<K, V> { |
| private: |
| |
| std::map<K,V,COMPARATOR> valueMap; |
| mutable concurrent::Mutex mutex; |
| int modCount; |
| |
| private: |
| |
| class AbstractMapIterator { |
| protected: |
| |
| mutable int position; |
| int expectedModCount; |
| typename std::map<K,V,COMPARATOR>::iterator futureEntry; |
| typename std::map<K,V,COMPARATOR>::iterator currentEntry; |
| |
| ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| AbstractMapIterator(const AbstractMapIterator&); |
| AbstractMapIterator& operator= (const AbstractMapIterator&); |
| |
| public: |
| |
| AbstractMapIterator(ConcurrentStlMap* parent) : position(0), |
| expectedModCount(parent->modCount), |
| futureEntry(parent->valueMap.begin()), |
| currentEntry(parent->valueMap.end()), |
| associatedMap(parent) { |
| } |
| |
| virtual ~AbstractMapIterator() {} |
| |
| virtual bool checkHasNext() const { |
| synchronized(&this->associatedMap->mutex) { |
| if (futureEntry != this->associatedMap->valueMap.end()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void checkConcurrentMod() const { |
| if (expectedModCount != this->associatedMap->modCount) { |
| throw ConcurrentModificationException( |
| __FILE__, __LINE__, "StlMap modified outside this iterator"); |
| } |
| } |
| |
| void makeNext() { |
| synchronized(&this->associatedMap->mutex) { |
| checkConcurrentMod(); |
| |
| if (!checkHasNext()) { |
| throw NoSuchElementException(__FILE__, __LINE__, "No next element"); |
| } |
| |
| currentEntry = futureEntry; |
| futureEntry++; |
| } |
| } |
| |
| virtual void doRemove() { |
| synchronized(&this->associatedMap->mutex) { |
| checkConcurrentMod(); |
| |
| if (currentEntry == this->associatedMap->valueMap.end()) { |
| throw decaf::lang::exceptions::IllegalStateException( |
| __FILE__, __LINE__, "Remove called before call to next()"); |
| } |
| |
| this->associatedMap->valueMap.erase(currentEntry); |
| currentEntry = this->associatedMap->valueMap.end(); |
| |
| expectedModCount++; |
| associatedMap->modCount++; |
| } |
| } |
| }; |
| |
| class EntryIterator : public Iterator< MapEntry<K,V> >, public AbstractMapIterator { |
| private: |
| |
| EntryIterator(const EntryIterator&); |
| EntryIterator& operator= (const EntryIterator&); |
| |
| public: |
| |
| EntryIterator(ConcurrentStlMap* parent) : AbstractMapIterator(parent) { |
| } |
| |
| virtual ~EntryIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual MapEntry<K, V> next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return MapEntry<K, V>(this->currentEntry->first, this->currentEntry->second); |
| } |
| |
| return MapEntry<K, V>(); |
| } |
| |
| virtual void remove() { |
| this->doRemove(); |
| } |
| }; |
| |
| class KeyIterator : public Iterator<K>, public AbstractMapIterator { |
| private: |
| |
| KeyIterator(const KeyIterator&); |
| KeyIterator& operator= (const KeyIterator&); |
| |
| public: |
| |
| KeyIterator(ConcurrentStlMap* parent) : AbstractMapIterator(parent) { |
| } |
| |
| virtual ~KeyIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual K next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return this->currentEntry->first; |
| } |
| |
| return K(); |
| } |
| |
| virtual void remove() { |
| this->doRemove(); |
| } |
| }; |
| |
| class ValueIterator : public Iterator<V>, public AbstractMapIterator { |
| private: |
| |
| ValueIterator(const ValueIterator&); |
| ValueIterator& operator= (const ValueIterator&); |
| |
| public: |
| |
| ValueIterator(ConcurrentStlMap* parent) : AbstractMapIterator(parent) { |
| } |
| |
| virtual ~ValueIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual V next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return this->currentEntry->second; |
| } |
| |
| return V(); |
| } |
| |
| virtual void remove() { |
| this->doRemove(); |
| } |
| }; |
| |
| private: |
| |
| class ConstAbstractMapIterator { |
| protected: |
| |
| mutable int position; |
| int expectedModCount; |
| typename std::map<K,V,COMPARATOR>::const_iterator futureEntry; |
| typename std::map<K,V,COMPARATOR>::const_iterator currentEntry; |
| |
| const ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| ConstAbstractMapIterator(const ConstAbstractMapIterator&); |
| ConstAbstractMapIterator& operator= (const ConstAbstractMapIterator&); |
| |
| public: |
| |
| ConstAbstractMapIterator(const ConcurrentStlMap* parent) : position(0), |
| expectedModCount(parent->modCount), |
| futureEntry(parent->valueMap.begin()), |
| currentEntry(parent->valueMap.end()), |
| associatedMap(parent) { |
| } |
| |
| virtual ~ConstAbstractMapIterator() {} |
| |
| virtual bool checkHasNext() const { |
| synchronized(&this->associatedMap->mutex) { |
| if (futureEntry != this->associatedMap->valueMap.end()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void checkConcurrentMod() const { |
| synchronized(&this->associatedMap->mutex) { |
| if (expectedModCount != this->associatedMap->modCount) { |
| throw ConcurrentModificationException( |
| __FILE__, __LINE__, "StlMap modified outside this iterator"); |
| } |
| } |
| } |
| |
| void makeNext() { |
| synchronized(&this->associatedMap->mutex) { |
| checkConcurrentMod(); |
| |
| if (!checkHasNext()) { |
| throw NoSuchElementException(__FILE__, __LINE__, "No next element"); |
| } |
| |
| currentEntry = futureEntry; |
| futureEntry++; |
| } |
| } |
| }; |
| |
| class ConstEntryIterator : public Iterator< MapEntry<K,V> >, public ConstAbstractMapIterator { |
| private: |
| |
| ConstEntryIterator(const ConstEntryIterator&); |
| ConstEntryIterator& operator= (const ConstEntryIterator&); |
| |
| public: |
| |
| ConstEntryIterator(const ConcurrentStlMap* parent) : ConstAbstractMapIterator(parent) { |
| } |
| |
| virtual ~ConstEntryIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual MapEntry<K, V> next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return MapEntry<K, V>(this->currentEntry->first, this->currentEntry->second); |
| } |
| |
| return MapEntry<K, V>(); |
| } |
| |
| virtual void remove() { |
| throw lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Cannot write to a const Iterator." ); |
| } |
| }; |
| |
| class ConstKeyIterator : public Iterator<K>, public ConstAbstractMapIterator { |
| private: |
| |
| ConstKeyIterator(const ConstKeyIterator&); |
| ConstKeyIterator& operator= (const ConstKeyIterator&); |
| |
| public: |
| |
| ConstKeyIterator(const ConcurrentStlMap* parent) : ConstAbstractMapIterator(parent) { |
| } |
| |
| virtual ~ConstKeyIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual K next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return this->currentEntry->first; |
| } |
| |
| return K(); |
| } |
| |
| virtual void remove() { |
| throw lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Cannot write to a const Iterator." ); |
| } |
| }; |
| |
| class ConstValueIterator : public Iterator<V>, public ConstAbstractMapIterator { |
| private: |
| |
| ConstValueIterator(const ConstValueIterator&); |
| ConstValueIterator& operator= (const ConstValueIterator&); |
| |
| public: |
| |
| ConstValueIterator(const ConcurrentStlMap* parent) : ConstAbstractMapIterator(parent) { |
| } |
| |
| virtual ~ConstValueIterator() {} |
| |
| virtual bool hasNext() const { |
| return this->checkHasNext(); |
| } |
| |
| virtual V next() { |
| synchronized(&this->associatedMap->mutex) { |
| this->makeNext(); |
| return this->currentEntry->second; |
| } |
| |
| return V(); |
| } |
| |
| virtual void remove() { |
| throw lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Cannot write to a const Iterator." ); |
| } |
| }; |
| |
| private: |
| |
| // Special Set implementation that is backed by this HashMap |
| class StlMapEntrySet : public AbstractSet< MapEntry<K, V> > { |
| private: |
| |
| ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| StlMapEntrySet(const StlMapEntrySet&); |
| StlMapEntrySet& operator= (const StlMapEntrySet&); |
| |
| public: |
| |
| StlMapEntrySet(ConcurrentStlMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) { |
| } |
| |
| virtual ~StlMapEntrySet() {} |
| |
| virtual int size() const { |
| return associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| associatedMap->clear(); |
| } |
| |
| virtual bool remove(const MapEntry<K,V>& entry) { |
| synchronized(&this->associatedMap->mutex) { |
| if (this->associatedMap->containsKey(entry.getKey()) && |
| this->associatedMap->get(entry.getKey()) == entry.getValue()) { |
| associatedMap->remove(entry.getKey()); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| virtual bool contains(const MapEntry<K,V>& entry) const { |
| synchronized(&this->associatedMap->mutex) { |
| if (this->associatedMap->containsKey(entry.getKey()) && |
| this->associatedMap->get(entry.getKey()) == entry.getValue()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| virtual Iterator< MapEntry<K, V> >* iterator() { |
| return new EntryIterator(associatedMap); |
| } |
| |
| virtual Iterator< MapEntry<K, V> >* iterator() const { |
| return new ConstEntryIterator(associatedMap); |
| } |
| }; |
| |
| // Special Set implementation that is backed by this HashMap |
| class ConstStlMapEntrySet : public AbstractSet< MapEntry<K, V> > { |
| private: |
| |
| const ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| ConstStlMapEntrySet(const ConstStlMapEntrySet&); |
| ConstStlMapEntrySet& operator= (const ConstStlMapEntrySet&); |
| |
| public: |
| |
| ConstStlMapEntrySet(const ConcurrentStlMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) { |
| } |
| |
| virtual ~ConstStlMapEntrySet() {} |
| |
| virtual int size() const { |
| return associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't clear a const collection"); |
| } |
| |
| virtual bool remove(const MapEntry<K,V>& entry DECAF_UNUSED) { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't remove from const collection"); |
| } |
| |
| virtual bool contains(const MapEntry<K,V>& entry) const { |
| synchronized(&this->associatedMap->mutex) { |
| if (this->associatedMap->containsKey(entry.getKey()) && |
| this->associatedMap->get(entry.getKey()) == entry.getValue()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| virtual Iterator< MapEntry<K, V> >* iterator() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); |
| } |
| |
| virtual Iterator< MapEntry<K, V> >* iterator() const { |
| return new ConstEntryIterator(associatedMap); |
| } |
| }; |
| |
| private: |
| |
| class StlMapKeySet : public AbstractSet<K> { |
| private: |
| |
| ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| StlMapKeySet(const StlMapKeySet&); |
| StlMapKeySet& operator= (const StlMapKeySet&); |
| |
| public: |
| |
| StlMapKeySet(ConcurrentStlMap* parent) : AbstractSet<K>(), associatedMap(parent) { |
| } |
| |
| virtual ~StlMapKeySet() {} |
| |
| virtual bool contains(const K& key) const { |
| return this->associatedMap->containsKey(key); |
| } |
| |
| virtual int size() const { |
| return this->associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| this->associatedMap->clear(); |
| } |
| |
| virtual bool remove(const K& key) { |
| synchronized(&this->associatedMap->mutex) { |
| if (this->associatedMap->containsKey(key)) { |
| associatedMap->remove(key); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| virtual Iterator<K>* iterator() { |
| return new KeyIterator(this->associatedMap); |
| } |
| |
| virtual Iterator<K>* iterator() const { |
| return new ConstKeyIterator(this->associatedMap); |
| } |
| }; |
| |
| class ConstStlMapKeySet : public AbstractSet<K> { |
| private: |
| |
| const ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| ConstStlMapKeySet(const ConstStlMapKeySet&); |
| ConstStlMapKeySet& operator= (const ConstStlMapKeySet&); |
| |
| public: |
| |
| ConstStlMapKeySet(const ConcurrentStlMap* parent) : AbstractSet<K>(), associatedMap(parent) { |
| } |
| |
| virtual ~ConstStlMapKeySet() {} |
| |
| virtual bool contains(const K& key) const { |
| return this->associatedMap->containsKey(key); |
| } |
| |
| virtual int size() const { |
| return this->associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't modify a const collection"); |
| } |
| |
| virtual bool remove(const K& key DECAF_UNUSED) { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't modify a const collection"); |
| } |
| |
| virtual Iterator<K>* iterator() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); |
| } |
| |
| virtual Iterator<K>* iterator() const { |
| return new ConstKeyIterator(this->associatedMap); |
| } |
| }; |
| |
| private: |
| |
| class StlMapValueCollection : public AbstractCollection<V> { |
| private: |
| |
| ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| StlMapValueCollection(const StlMapValueCollection&); |
| StlMapValueCollection& operator= (const StlMapValueCollection&); |
| |
| public: |
| |
| StlMapValueCollection(ConcurrentStlMap* parent) : AbstractCollection<V>(), associatedMap(parent) { |
| } |
| |
| virtual ~StlMapValueCollection() {} |
| |
| virtual bool contains(const V& value) const { |
| return this->associatedMap->containsValue(value); |
| } |
| |
| virtual int size() const { |
| return this->associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| this->associatedMap->clear(); |
| } |
| |
| virtual Iterator<V>* iterator() { |
| return new ValueIterator(this->associatedMap); |
| } |
| |
| virtual Iterator<V>* iterator() const { |
| return new ConstValueIterator(this->associatedMap); |
| } |
| }; |
| |
| class ConstStlMapValueCollection : public AbstractCollection<V> { |
| private: |
| |
| const ConcurrentStlMap* associatedMap; |
| |
| private: |
| |
| ConstStlMapValueCollection(const ConstStlMapValueCollection&); |
| ConstStlMapValueCollection& operator= (const ConstStlMapValueCollection&); |
| |
| public: |
| |
| ConstStlMapValueCollection(const ConcurrentStlMap* parent) : AbstractCollection<V>(), associatedMap(parent) { |
| } |
| |
| virtual ~ConstStlMapValueCollection() {} |
| |
| virtual bool contains(const V& value) const { |
| return this->associatedMap->containsValue(value); |
| } |
| |
| virtual int size() const { |
| return this->associatedMap->size(); |
| } |
| |
| virtual void clear() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't modify a const collection"); |
| } |
| |
| virtual Iterator<V>* iterator() { |
| throw decaf::lang::exceptions::UnsupportedOperationException( |
| __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); |
| } |
| |
| virtual Iterator<V>* iterator() const { |
| return new ConstValueIterator(this->associatedMap); |
| } |
| }; |
| |
| private: |
| |
| // Cached values that are only initialized once a request for them is made. |
| decaf::lang::Pointer<StlMapEntrySet> cachedEntrySet; |
| decaf::lang::Pointer<StlMapKeySet> cachedKeySet; |
| decaf::lang::Pointer<StlMapValueCollection> cachedValueCollection; |
| |
| // Cached values that are only initialized once a request for them is made. |
| mutable decaf::lang::Pointer<ConstStlMapEntrySet> cachedConstEntrySet; |
| mutable decaf::lang::Pointer<ConstStlMapKeySet> cachedConstKeySet; |
| mutable decaf::lang::Pointer<ConstStlMapValueCollection> cachedConstValueCollection; |
| |
| public: |
| |
| /** |
| * Default constructor - does nothing. |
| */ |
| ConcurrentStlMap() : ConcurrentMap<K,V>(), valueMap(), mutex(), modCount(0), |
| cachedEntrySet(), cachedKeySet(), cachedValueCollection(), |
| cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { |
| |
| } |
| |
| /** |
| * Copy constructor - copies the content of the given map into this |
| * one. |
| * @param source The source map. |
| */ |
| ConcurrentStlMap(const ConcurrentStlMap& source) : ConcurrentMap<K, V>(), valueMap(), mutex(), modCount(0), |
| cachedEntrySet(), cachedKeySet(), cachedValueCollection(), |
| cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { |
| copy(source); |
| } |
| |
| /** |
| * Copy constructor - copies the content of the given map into this |
| * one. |
| * @param source The source map. |
| */ |
| ConcurrentStlMap(const Map<K, V>& source) : ConcurrentMap<K, V>(), valueMap(), mutex(), modCount(0), |
| cachedEntrySet(), cachedKeySet(), cachedValueCollection(), |
| cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { |
| copy(source); |
| } |
| |
| virtual ~ConcurrentStlMap() {} |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool equals(const ConcurrentStlMap& source) const { |
| synchronized(&mutex) { |
| return this->valueMap == source.valueMap; |
| } |
| |
| return false; |
| } |
| |
| virtual bool equals(const Map<K, V>& source) const { |
| synchronized(&mutex) { |
| typename std::auto_ptr< Iterator<K> > iterator(this->keySet().iterator()); |
| while (iterator->hasNext()) { |
| K key = iterator->next(); |
| if (!this->containsKey(key)) { |
| return false; |
| } |
| |
| if (!(this->get(key) == source.get(key))) { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual void copy(const ConcurrentStlMap& source) { |
| synchronized(&mutex) { |
| this->valueMap.clear(); |
| this->valueMap.insert(source.valueMap.begin(), source.valueMap.end()); |
| } |
| } |
| |
| virtual void copy(const Map<K, V>& source) { |
| synchronized( &mutex ) { |
| this->clear(); |
| this->putAll(source); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual void clear() { |
| synchronized(&mutex) { |
| valueMap.clear(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool containsKey(const K& key) const { |
| typename std::map<K, V, COMPARATOR>::const_iterator iter; |
| |
| synchronized(&mutex) { |
| if (!valueMap.empty()) { |
| iter = valueMap.find(key); |
| return iter != valueMap.end(); |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool containsValue(const V& value) const { |
| synchronized(&mutex) { |
| if (valueMap.empty()) { |
| return false; |
| } |
| |
| typename std::map<K, V, COMPARATOR>::const_iterator iter = valueMap.begin(); |
| for (; iter != valueMap.end(); ++iter) { |
| if ((*iter).second == value) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool isEmpty() const { |
| synchronized(&mutex) { |
| return valueMap.empty(); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual int size() const { |
| synchronized(&mutex) { |
| return (int)valueMap.size(); |
| } |
| |
| return 0; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual V& get(const K& key) { |
| typename std::map<K,V,COMPARATOR>::iterator iter; |
| synchronized(&mutex) { |
| if (!valueMap.empty()) { |
| iter = valueMap.find(key); |
| if (iter != valueMap.end()) { |
| return iter->second; |
| } |
| } |
| } |
| |
| throw NoSuchElementException( |
| __FILE__, __LINE__, "Key does not exist in map"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual const V& get(const K& key) const { |
| typename std::map<K,V,COMPARATOR>::const_iterator iter; |
| synchronized(&mutex) { |
| if (!valueMap.empty()) { |
| iter = valueMap.find(key); |
| if (iter != valueMap.end()) { |
| return iter->second; |
| } |
| } |
| } |
| |
| throw NoSuchElementException( |
| __FILE__, __LINE__, "Key does not exist in map"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool put(const K& key, const V& value) { |
| bool result = false; |
| synchronized(&mutex) { |
| if (this->containsKey(key)) { |
| result = true; |
| } |
| modCount++; |
| valueMap[key] = value; |
| } |
| return result; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual bool put(const K& key, const V& value, V& oldValue) { |
| bool result = false; |
| synchronized(&mutex) { |
| if (this->containsKey(key)) { |
| result = true; |
| oldValue = valueMap[key]; |
| } |
| modCount++; |
| valueMap[key] = value; |
| } |
| return result; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual void putAll(const ConcurrentStlMap<K, V, COMPARATOR>& other) { |
| synchronized(&mutex) { |
| this->valueMap.insert(other.valueMap.begin(), other.valueMap.end()); |
| this->modCount++; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual void putAll(const Map<K, V>& other) { |
| synchronized(&mutex) { |
| typename std::auto_ptr< Iterator<K> > iterator(other.keySet().iterator()); |
| while (iterator->hasNext()) { |
| K key = iterator->next(); |
| this->put(key, other.get(key)); |
| } |
| modCount++; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| virtual V remove(const K& key) { |
| V result = V(); |
| synchronized(&mutex) { |
| if (!valueMap.empty()) { |
| typename std::map<K, V, COMPARATOR>::iterator iter = valueMap.find(key); |
| if (iter == valueMap.end()) { |
| return result; |
| } |
| result = iter->second; |
| valueMap.erase(iter); |
| modCount++; |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * If the specified key is not already associated with a value, associate it with |
| * the given value. This is equivalent to |
| * <pre> |
| * if( !map.containsKey( key ) ) { |
| * map.put( key, value ); |
| * return true; |
| * } else { |
| * return false; |
| * } |
| * </pre> |
| * except that the action is performed atomically. |
| * |
| * @param key |
| * The key to map the value to. |
| * @param value |
| * The value to map to the given key. |
| * |
| * @return true if the put operation was performed otherwise return false |
| * which indicates there was a value previously mapped to the key. |
| * @throw UnsupportedOperationException |
| * if the put operation is not supported by this map |
| */ |
| bool putIfAbsent(const K& key, const V& value) { |
| synchronized(&mutex) { |
| if (!this->containsKey(key)) { |
| this->put(key, value); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Remove entry for key only if currently mapped to given value. |
| * Acts as |
| * <pre> |
| * if( map.containsKey( key ) && ( map.get( key ) == value ) ) { |
| * map.remove( key ); |
| * return true; |
| * } else { |
| * return false; |
| * } |
| * </pre> |
| * except that the action is performed atomically. |
| * |
| * @param key key with which the specified value is associated. |
| * @param value value associated with the specified key. |
| * |
| * @return true if the value was removed, false otherwise |
| */ |
| bool remove(const K& key, const V& value) { |
| synchronized(&mutex) { |
| if( this->containsKey( key ) && ( this->get( key ) == value ) ) { |
| this->remove(key); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Replace entry for key only if currently mapped to given value. |
| * Acts as |
| * <pre> |
| * if( map.containsKey( key ) && ( map.get( key ) == oldValue ) ) { |
| * map.put( key, newValue ); |
| * return true; |
| * } else { |
| * return false; |
| * } |
| * </pre> |
| * except that the action is performed atomically. |
| * |
| * @param key key with which the specified value is associated. |
| * @param oldValue value expected to be associated with the specified key. |
| * @param newValue value to be associated with the specified key. |
| * |
| * @return true if the value was replaced |
| */ |
| bool replace(const K& key, const V& oldValue, const V& newValue) { |
| synchronized(&mutex) { |
| if (this->containsKey(key) && (this->get(key) == oldValue)) { |
| this->put(key, newValue); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Replace entry for key only if currently mapped to some value. |
| * Acts as |
| * <pre> |
| * if( map.containsKey( key ) ) { |
| * return map.put( key, value ); |
| * } else { |
| * throw NoSuchElementException(...); |
| * }; |
| * </pre> |
| * except that the action is performed atomically. |
| * |
| * @param key key with which the specified value is associated. |
| * @param value value to be associated with the specified key. |
| * |
| * @return copy of the previous value associated with specified key, or |
| * throws an NoSuchElementException if there was no mapping for key. |
| * |
| * @throws NoSuchElementException if there was no previous mapping. |
| */ |
| V replace(const K& key, const V& value) { |
| synchronized(&mutex) { |
| if (this->containsKey(key)) { |
| V result = this->get(key); |
| this->put(key, value); |
| return result; |
| } |
| } |
| |
| throw NoSuchElementException( |
| __FILE__, __LINE__, "Value to Replace was not in the Map." ); |
| } |
| |
| virtual Set< MapEntry<K, V> >& entrySet() { |
| synchronized(&mutex) { |
| if (this->cachedEntrySet == NULL) { |
| this->cachedEntrySet.reset(new StlMapEntrySet(this)); |
| } |
| } |
| return *(this->cachedEntrySet); |
| } |
| virtual const Set< MapEntry<K, V> >& entrySet() const { |
| synchronized(&mutex) { |
| if (this->cachedConstEntrySet == NULL) { |
| this->cachedConstEntrySet.reset(new ConstStlMapEntrySet(this)); |
| } |
| } |
| return *(this->cachedConstEntrySet); |
| } |
| |
| virtual Set<K>& keySet() { |
| synchronized(&mutex) { |
| if (this->cachedKeySet == NULL) { |
| this->cachedKeySet.reset(new StlMapKeySet(this)); |
| } |
| } |
| return *(this->cachedKeySet); |
| } |
| |
| virtual const Set<K>& keySet() const { |
| synchronized(&mutex) { |
| if (this->cachedConstKeySet == NULL) { |
| this->cachedConstKeySet.reset(new ConstStlMapKeySet(this)); |
| } |
| } |
| return *(this->cachedConstKeySet); |
| } |
| |
| virtual Collection<V>& values() { |
| synchronized(&mutex) { |
| if (this->cachedValueCollection == NULL) { |
| this->cachedValueCollection.reset(new StlMapValueCollection(this)); |
| } |
| } |
| return *(this->cachedValueCollection); |
| } |
| |
| virtual const Collection<V>& values() const { |
| synchronized(&mutex) { |
| if (this->cachedConstValueCollection == NULL) { |
| this->cachedConstValueCollection.reset(new ConstStlMapValueCollection(this)); |
| } |
| } |
| return *(this->cachedConstValueCollection); |
| } |
| |
| public: |
| |
| virtual void lock() { |
| mutex.lock(); |
| } |
| |
| virtual bool tryLock() { |
| return mutex.tryLock(); |
| } |
| |
| virtual void unlock() { |
| mutex.unlock(); |
| } |
| |
| virtual void wait() { |
| mutex.wait(); |
| } |
| |
| virtual void wait( long long millisecs ) { |
| mutex.wait( millisecs ); |
| } |
| |
| virtual void wait( long long millisecs, int nanos ) { |
| mutex.wait( millisecs, nanos ); |
| } |
| |
| virtual void notify() { |
| mutex.notify(); |
| } |
| |
| virtual void notifyAll() { |
| mutex.notifyAll(); |
| } |
| |
| }; |
| |
| }}} |
| |
| #endif /*_DECAF_UTIL_CONCURRENTSTLMAP_H_*/ |