/* * 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_CONCURRENT_COPYONWRITEARRAYSET_H_ #define _DECAF_UTIL_CONCURRENT_COPYONWRITEARRAYSET_H_ #include #include #include #include #include #include #include #include #include namespace decaf { namespace util { namespace concurrent { /** * Since the CopyOnWriteArraySet and the CopyOnWriteArrayList share much of the same * operational semantics this class uses the CopyOnWriteArrayList for all its underlying * operations. * * This collection is best used in applications where the Set size is usually small and * write operations are minimal as they result in a copy of the underlying array being * created. Reads are generally fast and the iterators provided by this collection * do not block as they operate on a snapshot of the data taken at the time of their * creation. * * @since 1.0 */ template< typename E > class CopyOnWriteArraySet : public AbstractSet { private: CopyOnWriteArrayList array; public: CopyOnWriteArraySet() : AbstractSet (), array() { } CopyOnWriteArraySet(const Collection& collection) : AbstractSet (), array() { this->copy(collection); } CopyOnWriteArraySet(const E* array, int size) : AbstractSet (), array() { for (int i = 0; i < size; ++i) { this->array.addIfAbsent(array[i]); } } virtual ~CopyOnWriteArraySet() { } public: virtual void copy(const Collection& collection) { this->array.copy(collection); } virtual decaf::util::Iterator* iterator() { return this->array.iterator(); } virtual decaf::util::Iterator* iterator() const { return this->array.iterator(); } virtual int size() const { return this->array.size(); } virtual bool isEmpty() const { return this->array.isEmpty(); } virtual bool add(const E& value) { return this->array.addIfAbsent(value); } virtual bool addAll(const Collection& collection) { return this->array.addAllAbsent(collection) > 0 ? true : false; } virtual void clear() { this->array.clear(); } virtual bool contains(const E& value) const { return this->array.contains(value); } virtual bool containsAll(const Collection& collection) const { return this->array.containsAll(collection); } virtual bool remove(const E& value) { return this->array.remove(value); } virtual bool removeAll(const Collection& collection) { return this->array.removeAll(collection); } virtual bool retainAll(const Collection& collection) { return this->array.retainAll(collection); } virtual std::vector toArray() const { return this->array.toArray(); } virtual bool equals(const Collection& collection) const { if ((void*) this == &collection) { return true; } const Set* asSet = dynamic_cast*> (&collection); if (asSet == NULL) { return false; } if (this->size() != asSet->size()) { return false; } std::auto_ptr > setIter(asSet->iterator()); // Use a single snapshot of underlying array CopyOnWriteArrayList array(this->array); int length = array.size(); decaf::lang::ArrayPointer matched(length, false); while (setIter->hasNext()) { E value = setIter->next(); int matchedAt = array.indexOf(value); if (matchedAt >= 0) { matched[matchedAt] = true; } } for (int i = 0; i < length; ++i) { if (matched[i] == false) { return false; } } return true; } }; }}} #endif /* _DECAF_UTIL_CONCURRENT_COPYONWRITEARRAYSET_H_ */