]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/impl/LockingTransactionContext.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / handler / impl / LockingTransactionContext.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.diagram.handler.impl;
13
14 import java.util.Collection;
15 import java.util.concurrent.locks.ReadWriteLock;
16 import java.util.concurrent.locks.ReentrantReadWriteLock;
17
18 import org.simantics.g2d.diagram.IDiagram;
19 import org.simantics.g2d.diagram.handler.LifeCycle;
20 import org.simantics.g2d.diagram.handler.TransactionContext;
21 import org.simantics.g2d.element.IElement;
22 import org.simantics.utils.datastructures.ListenerList;
23 import org.simantics.utils.datastructures.hints.IHintContext.Key;
24 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
25
26 /**
27  * @author Tuukka Lehtonen
28  */
29 public class LockingTransactionContext implements TransactionContext, LifeCycle {
30
31     public static final LockingTransactionContext INSTANCE = new LockingTransactionContext();
32
33     private static final Key TRANSACTION_LISTENERS = new KeyOf(ListenerList.class, "TRANSACTION LISTENERS");
34     private static final Key TRANSACTION_LOCK      = new KeyOf(ReadWriteLock.class, "TRANSACTION LOCK");
35
36     @Override
37     public void onDiagramCreated(IDiagram diagram) {
38         diagram.setHint(TRANSACTION_LISTENERS, new ListenerList<TransactionListener>(TransactionListener.class));
39         diagram.setHint(TRANSACTION_LOCK, new ReentrantReadWriteLock(true));
40     }
41
42     @Override
43     public void onDiagramLoaded(IDiagram diagram, Collection<IElement> initialElements) {
44     }
45
46     @Override
47     public void onDiagramDestroyed(IDiagram diagram) {
48     }
49
50     @Override
51     public void onDiagramDisposed(IDiagram diagram) {
52         diagram.removeHint(TRANSACTION_LISTENERS);
53         diagram.removeHint(TRANSACTION_LOCK);
54     }
55
56     @Override
57     public void addTransactionListener(IDiagram d, TransactionListener l) {
58         ListenerList<TransactionListener> ll;
59         synchronized (d) {
60             ll = d.getHint(TRANSACTION_LISTENERS);
61             if (ll == null) {
62                 ll = new ListenerList<TransactionListener>(TransactionListener.class);
63                 d.setHint(TRANSACTION_LISTENERS, ll);
64             }
65         }
66         ll.add(l);
67     }
68
69     @Override
70     public void removeTransactionListener(IDiagram d, TransactionListener l) {
71         synchronized (d) {
72             ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
73             if (ll == null)
74                 return;
75             ll.remove(l);
76         }
77     }
78
79     void lock(ReadWriteLock lock, TransactionType type) {
80         switch (type) {
81             case READ:
82                 lock.readLock().lock();
83                 return;
84             case WRITE:
85                 lock.writeLock().lock();
86                 return;
87         }
88     }
89
90     void unlock(ReadWriteLock lock, TransactionType type) {
91         switch (type) {
92             case READ:
93                 lock.readLock().unlock();
94                 return;
95             case WRITE:
96                 lock.writeLock().unlock();
97                 return;
98         }
99     }
100
101     @Override
102     public Transaction startTransaction(IDiagram d, TransactionType type) {
103         ReadWriteLock lock = d.getHint(TRANSACTION_LOCK);
104         assert lock != null;
105         lock(lock, type);
106         try {
107             Transaction t = new Transaction.Impl(type);
108             ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
109             if (ll != null)
110                 for (TransactionListener l : ll.getListeners())
111                     l.transactionStarted(d, t);
112             return t;
113         } catch (RuntimeException e) {
114             unlock(lock, type);
115             throw e;
116         }
117     }
118
119     @Override
120     public void finishTransaction(IDiagram d, Transaction t) {
121         ReadWriteLock lock = d.getHint(TRANSACTION_LOCK);
122         assert lock != null;
123         try {
124             ListenerList<TransactionListener> ll = d.getHint(TRANSACTION_LISTENERS);
125             if (ll != null)
126                 for (TransactionListener l : ll.getListeners())
127                     l.transactionFinished(d, t);
128         } finally {
129             unlock(lock, t.getType());
130         }
131     }
132
133 }