Skip to content

Commit 709f570

Browse files
authored
Don't dealloc strings if the TensorBuffer is shared (#357) (#358)
1 parent 3f8272f commit 709f570

File tree

1 file changed

+89
-71
lines changed

1 file changed

+89
-71
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
/*
2-
Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2+
Copyright 2019 The TensorFlow Authors. All Rights Reserved.
33
4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
10-
Unless required by applicable law or agreed to in writing, software
11-
distributed under the License is distributed on an "AS IS" BASIS,
12-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
See the License for the specific language governing permissions and
14-
limitations under the License.
15-
=======================================================================
16-
*/
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
=======================================================================
16+
*/
1717

1818
package org.tensorflow.internal.c_api;
1919

@@ -25,83 +25,101 @@
2525
import static org.tensorflow.internal.c_api.global.tensorflow.TF_TString_Init;
2626
import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorData;
2727
import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorElementCount;
28+
import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorMaybeMove;
2829
import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorType;
2930

3031
import org.bytedeco.javacpp.Pointer;
3132
import org.bytedeco.javacpp.annotation.Properties;
3233

3334
@Properties(inherit = org.tensorflow.internal.c_api.presets.tensorflow.class)
3435
public abstract class AbstractTF_Tensor extends Pointer {
35-
protected static class DeleteDeallocator extends TF_Tensor implements Pointer.Deallocator {
36-
DeleteDeallocator(TF_Tensor s) { super(s); }
37-
@Override public void deallocate() {
38-
if (!isNull()) {
39-
if (TF_TensorType(this) == TF_STRING) {
40-
// we need to deallocate the strings themselves before deallocating the tensor memory
41-
long n = TF_TensorElementCount(this);
42-
TF_TString data = new TF_TString(TF_TensorData(this));
43-
for (int i = 0; i < n; i++) {
44-
TF_TString_Dealloc(data.position(i));
45-
}
46-
}
47-
TF_DeleteTensor(this);
36+
protected static class DeleteDeallocator extends TF_Tensor implements Pointer.Deallocator {
37+
DeleteDeallocator(TF_Tensor s) {
38+
super(s);
39+
}
40+
41+
@Override
42+
public void deallocate() {
43+
if (!isNull()) {
44+
if (TF_TensorType(this) == TF_STRING) {
45+
TF_Tensor moved = TF_TensorMaybeMove(this);
46+
if (moved != null) {
47+
// we need to deallocate the strings themselves before deallocating the tensor memory
48+
long n = TF_TensorElementCount(moved);
49+
TF_TString data = new TF_TString(TF_TensorData(moved));
50+
for (int i = 0; i < n; i++) {
51+
TF_TString_Dealloc(data.position(i));
4852
}
49-
setNull();
53+
TF_DeleteTensor(moved);
54+
} else {
55+
// TensorBuffer is shared, leave contained strings alone.
56+
TF_DeleteTensor(this);
57+
}
58+
} else {
59+
TF_DeleteTensor(this);
5060
}
61+
}
62+
setNull();
5163
}
64+
}
5265

53-
/** TensorFlow crashes if we don't pass it a deallocator, so... */
54-
protected static Deallocator_Pointer_long_Pointer dummyDeallocator = new Deallocator_Pointer_long_Pointer() {
55-
@Override public void call(Pointer data, long len, Pointer arg) { }
56-
}.retainReference();
66+
/** TensorFlow crashes if we don't pass it a deallocator, so... */
67+
protected static Deallocator_Pointer_long_Pointer dummyDeallocator =
68+
new Deallocator_Pointer_long_Pointer() {
69+
@Override
70+
public void call(Pointer data, long len, Pointer arg) {}
71+
}.retainReference();
5772

58-
/** A reference to prevent deallocation. */
59-
protected Pointer pointer;
73+
/** A reference to prevent deallocation. */
74+
protected Pointer pointer;
6075

61-
public AbstractTF_Tensor(Pointer p) { super(p); }
76+
public AbstractTF_Tensor(Pointer p) {
77+
super(p);
78+
}
6279

63-
/**
64-
* Calls TF_NewTensor(), and registers a deallocator.
65-
* @return TF_Tensor created. Do not call TF_DeleteTensor() on it.
66-
*/
67-
public static TF_Tensor newTensor(int dtype, long[] dims, Pointer data) {
68-
TF_Tensor t = TF_NewTensor(dtype, dims, dims.length, data, data.limit(), dummyDeallocator, null);
69-
if (t != null) {
70-
t.pointer = data;
71-
t.deallocator(new DeleteDeallocator(t));
72-
}
73-
return t;
80+
/**
81+
* Calls TF_NewTensor(), and registers a deallocator.
82+
*
83+
* @return TF_Tensor created. Do not call TF_DeleteTensor() on it.
84+
*/
85+
public static TF_Tensor newTensor(int dtype, long[] dims, Pointer data) {
86+
TF_Tensor t =
87+
TF_NewTensor(dtype, dims, dims.length, data, data.limit(), dummyDeallocator, null);
88+
if (t != null) {
89+
t.pointer = data;
90+
t.deallocator(new DeleteDeallocator(t));
7491
}
92+
return t;
93+
}
7594

76-
/**
77-
* Calls TF_AllocateTensor(), and registers a deallocator.
78-
* @return TF_Tensor created. Do not call TF_DeleteTensor() on it.
79-
*/
80-
public static TF_Tensor allocateTensor(int dtype, long[] dims, long length) {
81-
TF_Tensor t = TF_AllocateTensor(dtype, dims, dims.length, length);
82-
if (t != null) {
83-
if (TF_TensorType(t) == TF_STRING) {
84-
// we need to initialize the strings themselves after allocating the tensor memory
85-
long n = TF_TensorElementCount(t);
86-
TF_TString data = new TF_TString(TF_TensorData(t));
87-
for (int i = 0; i < n; i++) {
88-
TF_TString_Init(data.position(i));
89-
}
90-
}
91-
t.deallocator(new DeleteDeallocator(t));
95+
/**
96+
* Calls TF_AllocateTensor(), and registers a deallocator.
97+
*
98+
* @return TF_Tensor created. Do not call TF_DeleteTensor() on it.
99+
*/
100+
public static TF_Tensor allocateTensor(int dtype, long[] dims, long length) {
101+
TF_Tensor t = TF_AllocateTensor(dtype, dims, dims.length, length);
102+
if (t != null) {
103+
if (TF_TensorType(t) == TF_STRING) {
104+
// we need to initialize the strings themselves after allocating the tensor memory
105+
long n = TF_TensorElementCount(t);
106+
TF_TString data = new TF_TString(TF_TensorData(t));
107+
for (int i = 0; i < n; i++) {
108+
TF_TString_Init(data.position(i));
92109
}
93-
return t;
110+
}
111+
t.deallocator(new DeleteDeallocator(t));
94112
}
113+
return t;
114+
}
95115

96-
/** Registers a deallocator and returns this. */
97-
public TF_Tensor withDeallocator() {
98-
return (TF_Tensor)this.deallocator(new DeleteDeallocator((TF_Tensor)this));
99-
}
116+
/** Registers a deallocator and returns this. */
117+
public TF_Tensor withDeallocator() {
118+
return (TF_Tensor) this.deallocator(new DeleteDeallocator((TF_Tensor) this));
119+
}
100120

101-
/**
102-
* Calls the deallocator, if registered, otherwise has no effect.
103-
*/
104-
public void delete() {
105-
deallocate();
106-
}
121+
/** Calls the deallocator, if registered, otherwise has no effect. */
122+
public void delete() {
123+
deallocate();
124+
}
107125
}

0 commit comments

Comments
 (0)