1 package org.eclipse.aether.named.support;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.eclipse.aether.named.NamedLockFactory;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicInteger;
30
31
32
33
34 public abstract class NamedLockFactorySupport implements NamedLockFactory
35 {
36 protected final Logger logger = LoggerFactory.getLogger( getClass() );
37
38 private final ConcurrentMap<String, NamedLockHolder> locks;
39
40 public NamedLockFactorySupport()
41 {
42 this.locks = new ConcurrentHashMap<>();
43 }
44
45 @Override
46 public NamedLockSupport getLock( final String name )
47 {
48 return locks.compute( name, ( k, v ) ->
49 {
50 if ( v == null )
51 {
52 v = new NamedLockHolder( createLock( k ) );
53 }
54 v.incRef();
55 return v;
56 } ).namedLock;
57 }
58
59 @Override
60 public void shutdown()
61 {
62
63 }
64
65 public boolean closeLock( final NamedLockSupport lock )
66 {
67 AtomicBoolean destroyed = new AtomicBoolean( false );
68 locks.compute( lock.name(), ( k, v ) ->
69 {
70 if ( v != null && v.decRef() == 0 )
71 {
72 destroyLock( v.namedLock );
73 destroyed.set( true );
74 return null;
75 }
76 return v;
77 } );
78 return destroyed.get();
79 }
80
81
82 @Override
83 protected void finalize() throws Throwable
84 {
85 try
86 {
87 if ( !locks.isEmpty() )
88 {
89
90 logger.warn( "Lock leak, referenced locks still exist {}", locks );
91 }
92 }
93 finally
94 {
95 super.finalize();
96 }
97 }
98
99 protected abstract NamedLockSupport createLock( final String name );
100
101 protected void destroyLock( final NamedLockSupport lock )
102 {
103
104 }
105
106 private static final class NamedLockHolder
107 {
108 private final NamedLockSupport namedLock;
109
110 private final AtomicInteger referenceCount;
111
112 private NamedLockHolder( NamedLockSupport namedLock )
113 {
114 this.namedLock = namedLock;
115 this.referenceCount = new AtomicInteger( 0 );
116 }
117
118 private int incRef()
119 {
120 return referenceCount.incrementAndGet();
121 }
122
123 private int decRef()
124 {
125 return referenceCount.decrementAndGet();
126 }
127
128 @Override
129 public String toString()
130 {
131 return "[refCount=" + referenceCount.get() + ", lock=" + namedLock + "]";
132 }
133 }
134 }