473,404 Members | 2,137 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,404 software developers and data experts.

A class destructor

Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I connect,
I can parse various properties of the system. However, when I am done, I
send it the "&EXIT." This tells the machine that I am disconnecting.

Now, I like ordered code just as much as the next person, so I try to create
my code with fault tolerances built into it. Therefore, if another
individual using my code forgets to call, Disconnect() which sends the
"&EXIT" message, I want to send that before the object is garbage collected.
This is synonymous to implementing a Dipose() method, and if the person
forgets to Dispose() the object, the destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function. However,
my stream has already been marked and called for garbage collection. What
should I do?

An abbreviated example of my code is as follows...

~MyClass()
{
if (this.m_stream != null)
{
this.Disconnect();
}
}

public void Disconnect()
{
if (this.m_stream != null)
{
this.Write("&EXIT");
this.m_stream.Close();
this.m_stream = null;
}
}

Again, if someone hasn't called Disconnect(), the destructor should call
Disconnect(), but by that time the stream has already been called for garbage
collection. Maybe I should do GC.SuppressFinalize()? Thank you, all.
Trecius

Oct 20 '08 #1
4 1438
On Oct 20, 7:42*pm, Trecius <Trec...@discussions.microsoft.comwrote:
Hello, Newsgroupians:

Here's my situation. *I have created a class that connects to another
device. *It reads and sends information using a stream. *The device it
connects to is proprietary and has its own set of commands. *When I connect,
I can parse various properties of the system. *However, when I am done,I
send it the "&EXIT." *This tells the machine that I am disconnecting.

Now, I like ordered code just as much as the next person, so I try to create
my code with fault tolerances built into it. *Therefore, if another
individual using my code forgets to call, Disconnect() which sends the
"&EXIT" message, I want to send that before the object is garbage collected. *
This is synonymous to implementing a Dipose() method, and if the person
forgets to Dispose() the object, the destructor will do it for you.

However, I am running into problems. *I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function. *However,
my stream has already been marked and called for garbage collection. *What
should I do?

An abbreviated example of my code is as follows...

~MyClass()
{
* if (this.m_stream != null)
* {
* * this.Disconnect();
* }

}

public void Disconnect()
{
* if (this.m_stream != null)
* {
* * this.Write("&EXIT");
* * this.m_stream.Close();
* * this.m_stream = null;
* }

}

Again, if someone hasn't called Disconnect(), the destructor should call
Disconnect(), but by that time the stream has already been called for garbage
collection. *Maybe I should do GC.SuppressFinalize()? *Thank you, all..

Trecius
Can you try implementing Dispose() pattern? As I see you are facing
issue with non deterministic nature of GC.

-Cnu
Oct 20 '08 #2
First I would implement IDisposable.

Next I would either

A: Create a stream class that writes &EXIT. It is the stream that owns the
unmanaged resource.
or
B: Throw an exception if you collect an instance that has not been closed.
FileStream for example will flush the contents if the handle is still
available, otherwise your file will just be missing some data. The idea is
that soon enough you will realise your data is missing and fix your bug.

I'd be more inclined to go for option B!


--
Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

Oct 20 '08 #3
Trecius wrote:
Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I
connect, I can parse various properties of the system. However, when
I am done, I send it the "&EXIT." This tells the machine that I am
disconnecting.

Now, I like ordered code just as much as the next person, so I try to
create my code with fault tolerances built into it. Therefore, if
another individual using my code forgets to call, Disconnect() which
sends the "&EXIT" message, I want to send that before the object is
garbage collected. This is synonymous to implementing a Dipose()
method, and if the person forgets to Dispose() the object, the
destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function.
However, my stream has already been marked and called for garbage
collection. What should I do?
Ahh, well C# classes (and .NET types in general) haven't got destructors,
they have finalizers instead. And finalizers run when the object is no
longer reachable from the root(s). Your problem is that the Stream is only
referenced from your object, so when your object is unreachable the Stream
is also unreachable, and .NET gives no guarantees as to which finalizers run
first. However, there is a way to force your finalizer to run before the
Stream is finalized: make the Stream reachable.

for example, add as follows:
class MyClass
{
private static readonly Dictionary<object, StreamConnectedStreams =
new Dictionary<MyClass, Stream>();
private readonly object self = new object(); // now guaranteed unique
for each this, but won't keep MyClass instance alive like using this would

public Stream UnderlyingStream
{
get { return m_stream; }
private set { m_stream = value; ConnectedStreams[self] = value; }
}
~MyClass()
{
if (this.m_stream != null)
{
this.Disconnect();
}
}
public void Disconnect()
{
if (UnderlyingStream != null)
{
this.Write("&EXIT");
this.m_stream.Close();
this.m_stream.Dispose();
UnderlyingStream = null;
}
}
}

>
Again, if someone hasn't called Disconnect(), the destructor should
call Disconnect(), but by that time the stream has already been
called for garbage collection. Maybe I should do
GC.SuppressFinalize()? Thank you, all.
Trecius

Oct 20 '08 #4
Trecius wrote:
Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I
connect, I can parse various properties of the system. However, when
I am done, I send it the "&EXIT." This tells the machine that I am
disconnecting.

Now, I like ordered code just as much as the next person, so I try to
create my code with fault tolerances built into it. Therefore, if
another individual using my code forgets to call, Disconnect() which
sends the "&EXIT" message, I want to send that before the object is
garbage collected. This is synonymous to implementing a Dipose()
method, and if the person forgets to Dispose() the object, the
destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function.
However, my stream has already been marked and called for garbage
collection. What should I do?
Note, in addition to my example using a static field, you could also use a
non-pinning GCHandle to keep the Stream alive.
>

Trecius

Oct 20 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: frs | last post by:
For memory economization, I need to get rid if the virtual destructor. Under this constraint I get caught up in a design, where I need to call a destructor of a derived class from a base class....
9
by: Daniel Kay | last post by:
Hello! I have written two template classes which implement the observerpattern in C++. I hope I manage to desribe the problem I have. template<class T> class Observer { /* ... */ }; ...
7
by: Hyoung Lee | last post by:
A simple method of simulating a class, such as C++ or UML class, in C would be using the struct construct. Similarly, we use C functions to simulate a methods; e.g., rv method_a (&struct,...
2
by: arun | last post by:
Hello Group, I have a class A, which has three other members and each member is of a different class type. If I don't create a destructor then the compiler will give me one and whenever...
2
by: arun | last post by:
Hello Group, The compiler generated destructor will invoke destructor of each member of the containing class let us say 'class A'. However, if I write my own destructor for class A like; ...
7
by: Thomas | last post by:
I am compiling with g++ the fol. class: template<typename E> class C_vector_ : public std::vector<E> { private:
15
by: Juha Nieminen | last post by:
I'm sure this is not a new idea, but I have never heard about it before. I'm wondering if this could work: Assume that you have a common base class and a bunch of classes derived from it, and...
7
by: Rahul | last post by:
Hi Everyone, I was trying to implement a final class and i start having the destructor of the final class as private, class A { ~A() { printf("destructor invoked\n");
1
by: Rune Allnor | last post by:
Hi all. I am sure this is an oldie, but I can't find a useful suggestion on how to solve it. I have a class hierarchy of classes derived from a base class. I would like to set up a vector of...
7
by: Tonni Tielens | last post by:
I'm trying to create a pure virtual class describing an interface. Normally, when I do this I make the destructor pure virtual so that, even if there are no members in the class, it cannot be...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.