2121import java .io .IOException ;
2222import java .lang .foreign .Arena ;
2323import java .lang .foreign .MemorySegment ;
24+ import java .util .ArrayList ;
2425import java .util .LinkedHashMap ;
26+ import java .util .List ;
2527import java .util .Map ;
28+ import java .util .Map .Entry ;
2629import java .util .Objects ;
2730import java .util .WeakHashMap ;
2831
3235class SharedMemoryCleaner extends CleanableState {
3336 private final Map <MemorySegment , Integer > segments = new LinkedHashMap <>();
3437 private final Map <Futex , Futex > futexes = new WeakHashMap <>();
35- private final Arena arena = Arena .ofShared ();
36- private final MemorySegment arenaSegment = arena .allocate (0 );
38+ private Arena arena ;
39+ private final boolean closeArena ;
40+ private MemorySegment arenaSegment ;
3741 final FileDescriptor fd ;
38- Arena defaultArena ;
3942
40- protected SharedMemoryCleaner (Object observed , FileDescriptor fd ) {
43+ SharedMemoryCleaner (Arena arena , Object observed ) {
44+ this (arena , observed , null );
45+ }
46+
47+ SharedMemoryCleaner (Arena arena , Object observed , FileDescriptor fd ) {
4148 super (observed );
49+ if (arena == null ) {
50+ this .arena = null ;
51+ this .closeArena = true ;
52+ } else {
53+ this .arena = arena ;
54+ this .closeArena = false ;
55+ }
4256 this .fd = fd ;
4357 }
4458
@@ -50,14 +64,14 @@ void registerMemorySegment(MemorySegment ms, int duplicates) {
5064
5165 @ Override
5266 @ SuppressWarnings ("PMD.CognitiveComplexity" )
53- protected void doClean () throws IOException {
67+ protected synchronized void doClean () throws IOException {
5468 if (!SharedMemory .isUtilLoaded ()) {
5569 // Nothing to do
5670 return ;
5771 }
5872
5973 Map <FileDescriptor , Long > map = SharedMemory .FD_MEMORY ;
60- if (map != null ) {
74+ if (map != null && fd != null ) {
6175 synchronized (map ) {
6276 map .remove (fd );
6377 }
@@ -77,45 +91,46 @@ protected void doClean() throws IOException {
7791 }
7892 }
7993
80- if (defaultArena != null ) {
81- defaultArena .close ();
82- defaultArena = null ;
94+ if (closeArena && arena != null ) {
95+ arena .close ();
8396 }
8497
8598 MemoryImplUtilInternal util = SharedMemory .getUtil ();
8699
87100 IOException exc = null ;
88- if (fd .valid ()) {
101+ if (fd != null && fd .valid ()) {
89102 try {
90103 util .close (fd );
91104 } catch (IOException e ) {
92105 exc = e ;
93106 }
94107 }
95108
109+ List <Entry <MemorySegment , Integer >> list ;
96110 synchronized (segments ) {
97- for (Map .Entry <MemorySegment , Integer > en : segments .entrySet ()) {
98- MemorySegment ms = en .getKey ();
99- int duplicates = en .getValue ();
100-
101- long addr = ms .address ();
102- long length = ms .byteSize ();
103- if (ms .scope ().isAlive ()) {
104- util .madvise (addr , length , MemoryImplUtilInternal .MADV_FREE_NOW , true );
105- continue ;
106- }
111+ list = new ArrayList <>(segments .entrySet ()).reversed ();
112+ segments .clear ();
113+ }
114+ for (Map .Entry <MemorySegment , Integer > en : list ) {
115+ MemorySegment ms = en .getKey ();
116+ int duplicates = en .getValue ();
117+
118+ long addr = ms .address ();
119+ long length = ms .byteSize ();
120+ if (ms .scope ().isAlive ()) {
121+ util .madvise (addr , length , MemoryImplUtilInternal .MADV_FREE_NOW , true );
122+ continue ;
123+ }
107124
108- try {
109- util .unmap (addr , length , duplicates , false );
110- } catch (IOException e ) {
111- if (exc == null ) {
112- exc = e ;
113- } else {
114- exc .addSuppressed (e );
115- }
125+ try {
126+ util .unmap (addr , length , duplicates , false );
127+ } catch (IOException e ) {
128+ if (exc == null ) {
129+ exc = e ;
130+ } else {
131+ exc .addSuppressed (e );
116132 }
117133 }
118- segments .clear ();
119134 }
120135
121136 if (exc != null ) {
@@ -141,7 +156,10 @@ public boolean isCovered(MemorySegment segment) {
141156 return false ;
142157 }
143158
144- public MemorySegment getArenaSegment () {
159+ public synchronized MemorySegment getArenaSegment () {
160+ if (this .arenaSegment == null ) {
161+ this .arenaSegment = getArena ().allocate (0 );
162+ }
145163 return arenaSegment ;
146164 }
147165
@@ -156,4 +174,11 @@ public void checkCovered(MemorySegment addr) throws IOException {
156174 throw new IOException ("Not a MemorySegment of ours" );
157175 }
158176 }
177+
178+ public synchronized Arena getArena () {
179+ if (this .arena == null ) {
180+ this .arena = Arena .ofShared ();
181+ }
182+ return this .arena ;
183+ }
159184}
0 commit comments