Skip to content

Commit 40da3d7

Browse files
committed
add DisposableObject as base class.
1 parent 724809c commit 40da3d7

12 files changed

Lines changed: 153 additions & 121 deletions

File tree

src/TensorFlowNET.Core/Buffers/Buffer.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ limitations under the License.
1919

2020
namespace Tensorflow
2121
{
22-
public class Buffer : IDisposable
22+
public class Buffer : DisposableObject
2323
{
24-
private IntPtr _handle;
25-
2624
private TF_Buffer buffer => Marshal.PtrToStructure<TF_Buffer>(_handle);
2725

2826
public byte[] Data
@@ -54,6 +52,8 @@ public Buffer(byte[] data)
5452
Marshal.Copy(data, 0, dst, data.Length);
5553

5654
_handle = c_api.TF_NewBufferFromString(dst, (ulong)data.Length);
55+
56+
Marshal.FreeHGlobal(dst);
5757
}
5858

5959
public static implicit operator IntPtr(Buffer buffer)
@@ -66,9 +66,7 @@ public static implicit operator byte[](Buffer buffer)
6666
return buffer.Data;
6767
}
6868

69-
public void Dispose()
70-
{
71-
c_api.TF_DeleteBuffer(_handle);
72-
}
69+
protected override void DisposeUnManagedState()
70+
=> c_api.TF_DeleteBuffer(_handle);
7371
}
7472
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*****************************************************************************
2+
Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved.
3+
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
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
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+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Text;
20+
21+
namespace Tensorflow
22+
{
23+
/// <summary>
24+
/// Abstract class for disposable object allocated in unmanaged runtime.
25+
/// </summary>
26+
public abstract class DisposableObject : IDisposable
27+
{
28+
protected IntPtr _handle;
29+
30+
protected DisposableObject() { }
31+
32+
public DisposableObject(IntPtr handle)
33+
{
34+
_handle = handle;
35+
}
36+
37+
private bool disposedValue = false; // To detect redundant calls
38+
39+
protected virtual void DisposeManagedState()
40+
{
41+
}
42+
43+
protected abstract void DisposeUnManagedState();
44+
45+
protected virtual void Dispose(bool disposing)
46+
{
47+
if (!disposedValue)
48+
{
49+
if (disposing)
50+
{
51+
// dispose managed state (managed objects).
52+
DisposeManagedState();
53+
}
54+
55+
// free unmanaged resources (unmanaged objects) and override a finalizer below.
56+
/*IntPtr h = IntPtr.Zero;
57+
lock (this)
58+
{
59+
h = _handle;
60+
_handle = IntPtr.Zero;
61+
}*/
62+
if (_handle != IntPtr.Zero)
63+
DisposeUnManagedState();
64+
65+
// set large fields to null.
66+
_handle = IntPtr.Zero;
67+
68+
disposedValue = true;
69+
}
70+
}
71+
72+
// override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
73+
~DisposableObject()
74+
{
75+
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
76+
Dispose(false);
77+
}
78+
79+
// This code added to correctly implement the disposable pattern.
80+
public void Dispose()
81+
{
82+
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
83+
Dispose(true);
84+
// uncomment the following line if the finalizer is overridden above.
85+
GC.SuppressFinalize(this);
86+
}
87+
}
88+
}

src/TensorFlowNET.Core/Graphs/Graph.Export.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public Buffer ToGraphDef(Status s)
2222
{
2323
var buffer = new Buffer();
2424
c_api.TF_GraphToGraphDef(_handle, buffer, s);
25-
s.Check();
25+
s.Check(true);
2626
// var def = GraphDef.Parser.ParseFrom(buffer);
2727
// buffer.Dispose();
2828

@@ -33,7 +33,9 @@ private GraphDef _as_graph_def(bool add_shapes = false)
3333
{
3434
var status = new Status();
3535
var buffer = ToGraphDef(status);
36-
status.Check();
36+
status.Check(true);
37+
status.Dispose();
38+
3739
var def = GraphDef.Parser.ParseFrom(buffer);
3840
buffer.Dispose();
3941

src/TensorFlowNET.Core/Sessions/BaseSession.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ limitations under the License.
2424

2525
namespace Tensorflow
2626
{
27-
public class BaseSession
27+
public class BaseSession : DisposableObject
2828
{
2929
protected Graph _graph;
3030
protected bool _opened;
@@ -42,17 +42,13 @@ public BaseSession(string target = "", Graph g = null, SessionOptions opts = nul
4242

4343
SessionOptions newOpts = null;
4444
if (opts == null)
45-
newOpts = c_api.TF_NewSessionOptions();
45+
newOpts = new SessionOptions();
4646

47-
var Status = new Status();
48-
49-
_session = c_api.TF_NewSession(_graph, opts ?? newOpts, Status);
47+
var status = new Status();
5048

51-
// dispose newOpts
52-
if (opts == null)
53-
c_api.TF_DeleteSessionOptions(newOpts);
49+
_session = c_api.TF_NewSession(_graph, opts ?? newOpts, status);
5450

55-
Status.Check(true);
51+
status.Check(true);
5652
}
5753

5854
public virtual NDArray run(object fetches, params FeedItem[] feed_dict)
@@ -363,5 +359,19 @@ private void _extend_graph()
363359
{
364360

365361
}
362+
363+
public void close()
364+
{
365+
Dispose();
366+
}
367+
368+
protected override void DisposeUnManagedState()
369+
{
370+
using (var status = new Status())
371+
{
372+
c_api.TF_DeleteSession(_handle, status);
373+
status.Check(true);
374+
}
375+
}
366376
}
367377
}

src/TensorFlowNET.Core/Sessions/Session.cs

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static Session LoadFromSavedModel(string path)
5050
{
5151
var graph = c_api.TF_NewGraph();
5252
var status = new Status();
53-
var opt = c_api.TF_NewSessionOptions();
53+
var opt = new SessionOptions();
5454

5555
var tags = new string[] { "serve" };
5656
var buffer = new TF_Buffer();
@@ -68,42 +68,14 @@ public static Session LoadFromSavedModel(string path)
6868
// var data = new byte[buffer.length];
6969
// Marshal.Copy(buffer.data, data, 0, (int)buffer.length);
7070
// var meta_graph = MetaGraphDef.Parser.ParseFrom(data);*/
71-
status.Check();
71+
status.Check(true);
7272

7373
return new Session(sess, g: new Graph(graph).as_default());
7474
}
7575

7676
public static implicit operator IntPtr(Session session) => session._session;
7777
public static implicit operator Session(IntPtr handle) => new Session(handle);
7878

79-
public void close()
80-
{
81-
Dispose();
82-
}
83-
84-
public void Dispose()
85-
{
86-
IntPtr h = IntPtr.Zero;
87-
lock (this)
88-
{
89-
h = _session;
90-
_session = IntPtr.Zero;
91-
}
92-
if (h != IntPtr.Zero)
93-
{
94-
var status = new Status();
95-
c_api.TF_DeleteSession(h, status);
96-
status.Check(true);
97-
}
98-
99-
GC.SuppressFinalize(this);
100-
}
101-
102-
~Session()
103-
{
104-
Dispose();
105-
}
106-
10779
public void __enter__()
10880
{
10981

src/TensorFlowNET.Core/Sessions/SessionOptions.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,34 @@ limitations under the License.
2020

2121
namespace Tensorflow
2222
{
23-
public class SessionOptions : IDisposable
23+
public class SessionOptions : DisposableObject
2424
{
25-
private IntPtr _handle;
26-
private Status _status;
27-
28-
public unsafe SessionOptions()
25+
public SessionOptions()
2926
{
30-
var opts = c_api.TF_NewSessionOptions();
31-
_handle = opts;
32-
_status = new Status();
27+
_handle = c_api.TF_NewSessionOptions();
3328
}
3429

35-
public unsafe SessionOptions(IntPtr handle)
30+
public SessionOptions(IntPtr handle)
3631
{
3732
_handle = handle;
3833
}
3934

40-
public void Dispose()
41-
{
42-
c_api.TF_DeleteSessionOptions(_handle);
43-
_status.Dispose();
44-
}
35+
protected override void DisposeUnManagedState()
36+
=> c_api.TF_DeleteSessionOptions(_handle);
4537

46-
public Status SetConfig(ConfigProto config)
38+
public void SetConfig(ConfigProto config)
4739
{
4840
var bytes = config.ToByteArray();
4941
var proto = Marshal.AllocHGlobal(bytes.Length);
5042
Marshal.Copy(bytes, 0, proto, bytes.Length);
51-
c_api.TF_SetConfig(_handle, proto, (ulong)bytes.Length, _status);
52-
_status.Check(false);
53-
return _status;
43+
44+
using (var status = new Status())
45+
{
46+
c_api.TF_SetConfig(_handle, proto, (ulong)bytes.Length, status);
47+
status.Check(false);
48+
}
49+
50+
Marshal.FreeHGlobal(proto);
5451
}
5552

5653
public static implicit operator IntPtr(SessionOptions opts) => opts._handle;

src/TensorFlowNET.Core/Status/Status.cs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ namespace Tensorflow
2222
/// TF_Status holds error information. It either has an OK code, or
2323
/// else an error code with an associated error message.
2424
/// </summary>
25-
public class Status : IDisposable
25+
public class Status : DisposableObject
2626
{
27-
protected IntPtr _handle;
28-
2927
/// <summary>
3028
/// Error message
3129
/// </summary>
@@ -67,22 +65,7 @@ public static implicit operator IntPtr(Status status)
6765
return status._handle;
6866
}
6967

70-
public void Dispose()
71-
{
72-
IntPtr h = IntPtr.Zero;
73-
lock (this)
74-
{
75-
h = _handle;
76-
_handle = IntPtr.Zero;
77-
}
78-
if (h != IntPtr.Zero)
79-
c_api.TF_DeleteStatus(h);
80-
GC.SuppressFinalize(this);
81-
}
82-
83-
~Status()
84-
{
85-
Dispose();
86-
}
68+
protected override void DisposeUnManagedState()
69+
=> c_api.TF_DeleteStatus(_handle);
8770
}
8871
}

src/TensorFlowNET.Core/Tensors/Tensor.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ namespace Tensorflow
2929
/// A tensor is a generalization of vectors and matrices to potentially higher dimensions.
3030
/// Internally, TensorFlow represents tensors as n-dimensional arrays of base datatypes.
3131
/// </summary>
32-
public partial class Tensor : IDisposable, ITensorOrOperation, _TensorLike
32+
public partial class Tensor : DisposableObject, ITensorOrOperation, _TensorLike
3333
{
34-
private IntPtr _handle;
35-
3634
private int _id;
3735
private Operation _op;
3836

@@ -394,26 +392,8 @@ public override string ToString()
394392
return $"tf.Tensor '{name}' shape=({string.Join(",", shape)}) dtype={dtype}";
395393
}
396394

397-
public void Dispose()
398-
{
399-
IntPtr h = IntPtr.Zero;
400-
lock (this)
401-
{
402-
h = _handle;
403-
_handle = IntPtr.Zero;
404-
}
405-
if (h != IntPtr.Zero)
406-
c_api.TF_DeleteTensor(h);
407-
GC.SuppressFinalize(this);
408-
}
409-
410-
/// <summary>
411-
/// Dispose the tensor when it gets garbage collected
412-
/// </summary>
413-
~Tensor()
414-
{
415-
Dispose();
416-
}
395+
protected override void DisposeUnManagedState()
396+
=> c_api.TF_DeleteTensor(_handle);
417397

418398
public bool IsDisposed
419399
{

0 commit comments

Comments
 (0)