blob: b55a62e5e57c96b11c65b1568db79245e9233f0f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.offheap;
import org.apache.geode.internal.cache.CachedDeserializableFactory;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Unretained;
/**
* Utility class that provides static method to do some common tasks for off-heap references.
*
* @since Geode 1.0
*/
public class OffHeapHelper {
private OffHeapHelper() {
// no instances allowed
}
/**
* If o is off-heap then return its heap form; otherwise return o since it is already on the heap.
*/
public static Object getHeapForm(Object o) {
if (o instanceof StoredObject) {
return ((StoredObject) o).getValueAsDeserializedHeapObject();
} else {
return o;
}
}
/**
* Just like {@link #copyIfNeeded(Object, InternalCache)} except that if off-heap is copied it is
* also released.
*
* @param v If this value is off-heap then the caller must have already retained it.
* @return the heap copy to use in place of v
*/
public static Object copyAndReleaseIfNeeded(@Released Object v, InternalCache cache) {
if (v instanceof StoredObject) {
@Unretained
StoredObject ohv = (StoredObject) v;
try {
if (ohv.isSerialized()) {
return CachedDeserializableFactory.create(ohv.getSerializedValue(), cache);
} else {
// it is a byte[]
return ohv.getDeserializedForReading();
}
} finally {
release(ohv);
}
} else {
return v;
}
}
/**
* If v is on heap then just return v; no copy needed. Else v is off-heap so copy it to heap and
* return a reference to the heap copy. Note that unlike {@link #getHeapForm(Object)} if v is a
* serialized off-heap object it will be copied to the heap as a CachedDeserializable. If you
* prefer to have the serialized object also deserialized and copied to the heap use
* {@link #getHeapForm(Object)}.
*
* @param v possible OFF_HEAP_REFERENCE
* @return v or a heap copy of v
*/
public static Object copyIfNeeded(@Unretained Object v, InternalCache cache) {
if (v instanceof StoredObject) {
@Unretained
StoredObject ohv = (StoredObject) v;
if (ohv.isSerialized()) {
v = CachedDeserializableFactory.create(ohv.getSerializedValue(), cache);
} else {
// it is a byte[]
v = ohv.getDeserializedForReading();
}
}
return v;
}
/**
* @return true if release was done
*/
public static boolean release(@Released Object o) {
if (o instanceof StoredObject) {
((StoredObject) o).release();
return true;
} else {
return false;
}
}
/**
* Just like {@link #release(Object)} but also disable debug tracking of the release.
*
* @return true if release was done
*/
public static boolean releaseWithNoTracking(@Released Object o) {
if (o instanceof StoredObject) {
StoredObject so = (StoredObject) o;
if (!so.hasRefCount()) {
so.release();
return true;
}
ReferenceCountHelper.skipRefCountTracking();
so.release();
ReferenceCountHelper.unskipRefCountTracking();
return true;
} else {
return false;
}
}
/**
* Just like {@link #release(Object)} but also set the owner for debug tracking of the release.
*
* @return true if release was done
*/
public static boolean releaseAndTrackOwner(@Released final Object o, final Object owner) {
if (o instanceof StoredObject) {
StoredObject so = (StoredObject) o;
if (!so.hasRefCount()) {
so.release();
return true;
}
ReferenceCountHelper.setReferenceCountOwner(owner);
so.release();
ReferenceCountHelper.setReferenceCountOwner(null);
return true;
} else {
return false;
}
}
}