All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.z3.Z3ReferenceQueue Maven / Gradle / Ivy

The newest version!
/**
Copyright (c) 2012-2014 Microsoft Corporation
   
Module Name:

    IDecRefQueue.java

Abstract:

Author:

    @author Christoph Wintersteiger (cwinter) 2012-03-15

Notes:
    
**/

package com.microsoft.z3;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

/**
 * A queue to handle management of native memory.
 *
 * 

Mechanics: When an object is created, a so-called {@link PhantomReference} * is constructed that is associated with the created object and the reference queue {@code referenceQueue}. * Once the object becomes strongly unreachable, the phantom reference gets * added by JVM to the {@code referenceQueue}. * After each object creation, we iterate through the available objects in * {@code referenceQueue} and decrement references for them. *

* In order for this to work, we need to (i) associate to each phantom reference the underlying * native object (and its type) that it references and (ii) keep the phantom references themselves alive, so they are not * garbage collected before the object they reference. * We use a doubly-linked list of custom phantom references, subclasses of {@link Reference}, to achieve this. * */ class Z3ReferenceQueue { private final Context ctx; private final ReferenceQueue referenceQueue = new ReferenceQueue<>(); private final Reference referenceList = emptyList(); Z3ReferenceQueue(Context ctx) { this.ctx = ctx; } /** * Create and store a new phantom reference. */ void storeReference(T z3Object, ReferenceConstructor refConstructor) { referenceList.insert(refConstructor.construct(z3Object, referenceQueue)); clear(); } /** * Clean all references currently in {@code referenceQueue}. */ private void clear() { Reference ref; while ((ref = (Reference)referenceQueue.poll()) != null) { ref.cleanup(ctx); } } /** * Clean all references stored in {@code referenceList}, * regardless of whether they are in {@code referenceQueue} or not. */ @SuppressWarnings("StatementWithEmptyBody") public void forceClear() { // Decrement all reference counters Reference cur = referenceList.next; while (cur.next != null) { cur.decRef(ctx, cur.nativePtr); cur = cur.next; } // Bulk-delete the reference list's entries referenceList.next = cur; cur.prev = referenceList; // Empty the reference queue so that there are no living phantom references anymore. // This makes sure that all stored phantom references can be GC'd now. while (referenceQueue.poll() != null) {} } private static Reference emptyList() { Reference head = new DummyReference(); Reference tail = new DummyReference(); head.next = tail; tail.prev = head; return head; } // ================================================================================================================ @FunctionalInterface interface ReferenceConstructor { Reference construct(T reference, ReferenceQueue queue); } abstract static class Reference extends PhantomReference { private Reference prev; private Reference next; private final long nativePtr; Reference(T referent, ReferenceQueue q) { super(referent, q); this.nativePtr = referent != null ? referent.getNativeObject() : 0; } private void cleanup(Context ctx) { decRef(ctx, nativePtr); assert (prev != null && next != null); prev.next = next; next.prev = prev; } private void insert(Reference ref) { assert next != null; ref.prev = this; ref.next = this.next; ref.next.prev = ref; next = ref; } abstract void decRef(Context ctx, long z3Obj); } private static class DummyReference extends Reference { public DummyReference() { super(null, null); } @Override void decRef(Context ctx, long z3Obj) { // Should never be called. assert false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy