001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo;
012:
013: import java.util.Iterator;
014: import java.util.ConcurrentModificationException;
015: import java.util.NoSuchElementException;
016:
017: /**
018: * This is a Link List implementation of {@link PMCacheEntry} instances that must
019: * be processed at the end of the transaction.
020: */
021: public class TransactionalList {
022: private final PMCacheEntry header = new PMCacheEntry();
023: private int modCount;
024:
025: public TransactionalList() {
026: header.processListNext = header.processListPrev = header;
027: }
028:
029: private PMCacheEntry addBefore(PMCacheEntry o, PMCacheEntry e) {
030: modCount++;
031: o.processListNext = e;
032: o.processListPrev = e.processListPrev;
033:
034: o.processListPrev.processListNext = o;
035: o.processListNext.processListPrev = o;
036: return o;
037: }
038:
039: public boolean contains(PMCacheEntry ce) {
040: if (header == ce)
041: return true;
042: return (ce.processListPrev != null || ce.processListNext != null);
043: }
044:
045: public void clear() {
046: modCount++;
047: PMCacheEntry ce = header.processListNext;
048: for (; ce != null && ce != header; ce = ce.processListNext) {
049: ce.processListPrev.processListNext = null;
050: ce.processListPrev = null;
051: }
052: header.processListPrev.processListNext = null;
053: header.processListNext = header.processListPrev = header;
054: }
055:
056: public void add(PCStateMan sm) {
057: if (!contains(sm.cacheEntry)) {
058: addBefore(sm.cacheEntry, header);
059: }
060: }
061:
062: public void remove(PCStateMan sm) {
063: if (contains(sm.cacheEntry)) {
064: removeImp(sm.cacheEntry);
065: }
066: }
067:
068: private void removeImp(PMCacheEntry ce) {
069: if (contains(ce)) {
070: modCount++;
071: ce.processListPrev.processListNext = ce.processListNext;
072: ce.processListNext.processListPrev = ce.processListPrev;
073: ce.processListPrev = null;
074: ce.processListNext = null;
075: }
076: }
077:
078: public Iterator iterator() {
079: return new Iter(header, modCount);
080: }
081:
082: class Iter implements Iterator {
083: PMCacheEntry current;
084: private int iterModCount;
085:
086: public Iter(PMCacheEntry current, int iterModCount) {
087: this .current = current;
088: this .iterModCount = iterModCount;
089: }
090:
091: public void remove() {
092: //To change body of implemented methods use File | Settings | File Templates.
093: }
094:
095: public boolean hasNext() {
096: checkConcurrent();
097: return current.processListNext != header;
098: }
099:
100: private void checkConcurrent() {
101: if (iterModCount != modCount) {
102: throw new ConcurrentModificationException();
103: }
104: }
105:
106: public Object next() {
107: if (hasNext()) {
108: current = current.processListNext;
109: } else {
110: throw new NoSuchElementException();
111: }
112: return current;
113: }
114: }
115: }
|