Z3
 
Loading...
Searching...
No Matches
Z3ReferenceQueue.java
Go to the documentation of this file.
1
18package com.microsoft.z3;
19
20import java.lang.ref.PhantomReference;
21import java.lang.ref.ReferenceQueue;
22
39class Z3ReferenceQueue {
40 private final Context ctx;
41 private final ReferenceQueue<Z3Object> referenceQueue = new ReferenceQueue<>();
42 private final Reference<?> referenceList = emptyList();
43
44 Z3ReferenceQueue(Context ctx) {
45 this.ctx = ctx;
46 }
47
51 <T extends Z3Object> void storeReference(T z3Object, ReferenceConstructor<T> refConstructor) {
52 referenceList.insert(refConstructor.construct(z3Object, referenceQueue));
53 clear();
54 }
55
59 private void clear() {
60 Reference<?> ref;
61 while ((ref = (Reference<?>)referenceQueue.poll()) != null) {
62 ref.cleanup(ctx);
63 }
64 }
65
70 @SuppressWarnings("StatementWithEmptyBody")
71 public void forceClear() {
72 // Decrement all reference counters
73 Reference<?> cur = referenceList.next;
74 while (cur.next != null) {
75 cur.decRef(ctx, cur.nativePtr);
76 cur = cur.next;
77 }
78
79 // Bulk-delete the reference list's entries
80 referenceList.next = cur;
81 cur.prev = referenceList;
82
83 // Empty the reference queue so that there are no living phantom references anymore.
84 // This makes sure that all stored phantom references can be GC'd now.
85 while (referenceQueue.poll() != null) {}
86 }
87
88 private static Reference<?> emptyList() {
89 Reference<?> head = new DummyReference();
90 Reference<?> tail = new DummyReference();
91 head.next = tail;
92 tail.prev = head;
93 return head;
94 }
95
96 // ================================================================================================================
97
98 @FunctionalInterface
99 interface ReferenceConstructor<T extends Z3Object> {
100 Reference<T> construct(T reference, ReferenceQueue<Z3Object> queue);
101 }
102
103 abstract static class Reference<T extends Z3Object> extends PhantomReference<T> {
104
105 private Reference<?> prev;
106 private Reference<?> next;
107 private final long nativePtr;
108
109 Reference(T referent, ReferenceQueue<Z3Object> q) {
110 super(referent, q);
111 this.nativePtr = referent != null ? referent.getNativeObject() : 0;
112 }
113
114 private void cleanup(Context ctx) {
115 decRef(ctx, nativePtr);
116 assert (prev != null && next != null);
117 prev.next = next;
118 next.prev = prev;
119 }
120
121 private void insert(Reference<?> ref) {
122 assert next != null;
123 ref.prev = this;
124 ref.next = this.next;
125 ref.next.prev = ref;
126 next = ref;
127 }
128
129 abstract void decRef(Context ctx, long z3Obj);
130 }
131
132 private static class DummyReference extends Reference<Z3Object> {
133
134 public DummyReference() {
135 super(null, null);
136 }
137
138 @Override
139 void decRef(Context ctx, long z3Obj) {
140 // Should never be called.
141 assert false;
142 }
143 }
144}