UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » C++
  • » handling resources pattern?

#1 2009-02-03 09:56 AM

thinking
Member
Registered: 2005-09-15
Posts: 103

Re: handling resources pattern?

hi all

my current project is getting bigger and thus the dependencies within the source code rises.
for example: a client connection has a message queue, related remote peers, metainformation like connection state or timestamps or related to recurring jobs in my app like creating statistics or maintaining queues

the problem i have: if, for example, one of the above "tasks" fail, like inserting in a std::map failed because ENOMEM, i need to cleanly remove everything related to the current action
this means cleanly close the connections, clean up queues, remove jobs and timout's ....

im using the boost library for doing all the stuff but as you can see the relations between the actions rises and every step could fail in different code locations

so the question i have is:
how do other projects handle such things? anyone has expirience on this? is there a pattern for this?

i thought about a class where every component/resource register's to and if something fails related callbacks for destruction are called, but im not sure how to handle the order of destruction or how to create the relations between the components which need to be destroyed and if this is a good idea generally - any opinions/suggestions?

thx all

Offline

#2 2009-02-03 01:46 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: handling resources pattern?

What I'd go for is one "get rid of this peer and do all cleanup" function which can be called from any context. The actual cleanup should probably be done from one, knows context, so asynchronous instead of immediately (depending on the structure of the rest of the code etc.), especially if part of it can fail, to avoid surprises (like sending a message to other hosts that this one is gone, which could cause unexpected recursion).

But as you're using C++, the more general approach is probably to have destructors that do all the cleanup, and throw an exception when something goes wrong which is caught somewhere early in the call chain.

Offline

#3 2009-02-03 03:58 PM

thinking
Member
Registered: 2005-09-15
Posts: 103

Re: handling resources pattern?

handling this asyncronously would also fit in my usage of boost::asio

for the destructors - well it sounds good, but throwing an exception in a destructor is something no one should do (at least in c++) http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.3
i will think about it, but
maybe i will combine ure suggestion like creating a "get rid function" called from the destructor not throwing an exception

Offline

#4 2009-02-03 04:12 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: handling resources pattern?

I'm not sure if this would solve 100% of your problem, but in my projects I find that reference-counting pointers go a long way toward making cleanup automatic.  By holding all my dynamic resources in objects and using boost::shared_ptr (or equivalent) to keep references to those objects, it is guaranteed that resources are freed up when the objects holding them are freed up, and so on.

For example, instead of keeping plain old int's around as my socket handles, I made a SocketHolder class that holds the int, and the SocketHolder destructor calls close() on the int.  Then I create a SocketHolder object for each socket I create, and all my code passes around not the int itself but shared_ptr's to the SocketHolder object... with the upshot being that I no longer have to worry about when to close the socket, because it's guaranteed that the socket will be closed when the SocketHolder is destroyed, and it's guaranteed that the SocketHolder will be destroyed when the last shared_ptr to it is destroyed.  That makes cleanup a no-brainer for me.

I hope that made sense!

-Jeremy

Offline

#5 2009-02-04 01:25 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: handling resources pattern?

thinking;25934 wrote:

handling this asyncronously would also fit in my usage of boost::asio

for the destructors - well it sounds good, but throwing an exception in a destructor is something no one should do (at least in c++) http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.3
i will think about it, but
maybe i will combine ure suggestion like creating a "get rid function" called from the destructor not throwing an exception

What I had in mind was more like throwing an exception, and at the exception handling do all the cleanup, so the destructors would be called after the exception is caught, not generate the exception themselves.

The one "get rid function" is probably the C way of doing it.

You might want to create a new "action" object for each action that is done, and deleting that object does all the cleanup (wich is needed regardless if anything failed or not).

If resource handling becomes too tricky to keep track off, you either made things more complicated than needed, or you probably should move to something like Jeremy said.

Offline

#6 2009-02-05 08:05 AM

Nope
Administrator
From: Germany
Registered: 2004-01-24
Posts: 385
Website

Re: handling resources pattern?

Well, in case I have a server handling client requests, I have all related data in a class ClientConnectionData. When a new Client connects I create an instance of that object. If there is an exception within the connection handling that can't be resolved internally, the class itself throws one, so the calling code just deletes the instance. So I do all my initialising in the constructor and all cleanup in the destructor.

I don't like any kind of automatic garbage collection. But I guess that I am just a bit old fashioned. Btw, code generated by modern C++ compilers will not call the destructor asap, but push the class in a queue for cleanup, waiting till the current program flow would give back control to the system before starting work. You'd need a compiler switch to force the clean up right away. I've learned that because once I had an exception thrown in one of my destructors...

Offline

#7 2009-02-05 04:06 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: handling resources pattern?

Nope;25959 wrote:

Btw, code generated by modern C++ compilers will not call the destructor asap, but push the class in a queue for cleanup, waiting till the current program flow would give back control to the system before starting work.

Really?  I'd have thought that would violate the C++ spec, which is quite explicit about when destructors ought to be called.  But may be I'm wrong.  (or maybe you're referring to Microsoft's bastardized version of C++ that runs on top of C#, or something)

You'd need a compiler switch to force the clean up right away. I've learned that because once I had an exception thrown in one of my destructors...

I'd always considered throwing from a destructor to be a no-no...

Offline

#8 2009-02-06 10:24 AM

Nope
Administrator
From: Germany
Registered: 2004-01-24
Posts: 385
Website

Re: handling resources pattern?

It was a segfault caused by a string buffer overflow changing the contents of a pointer on the stack.

The segfault happened at varying places completely unrelated to the code causing it. It was several years ago and it might have been related to the thread/exception problems of the gnu compiler back then. So my conclusion might be wrong.
I haven't found anything about the way the gnu c++ does handle the delete call. Perhaps I find the time to take a closer look at the libraries.

Offline

#9 2009-02-06 04:01 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: handling resources pattern?

The segfault happened at varying places completely unrelated to the code causing it.

I've found that's pretty much standard procedure with most memory-trashing bugs...
You trash some memory one place, but it's not until somewhere else down the line
that the trashing causes enough problems to cause a seg-fault...  It's especially true
with dynamic heap trashing: you trash things enough to fuck up malloc() a bit, but it
doesn't cause any real problems until the next time you try to malloc()/free() something
completely unrelated...

So, I wouldn't consider that necessarily evidence of that code being delayed until the
point you really got hit with the seg-fault...  It may have done the trashing of memory
when you thought it should have, but just not been bad enough to cause the seg-fault
until some later random time...

Offline

#10 2009-02-07 05:40 PM

Nope
Administrator
From: Germany
Registered: 2004-01-24
Posts: 385
Website

Re: handling resources pattern?

There was no new/delete/free/malloc around. I could cause the segfault at any specific place by adding a sleep(1) or yield. Then the segfault would appear to happen there.
But as said, it was a longer time ago and it was in a threaded app. The error was in the same thread though (only one active at that time). I am not sure which gcc version I used back then. If I had more time, I'd test the thing by recreating the bug.

Offline

#11 2009-02-17 08:31 AM

thinking
Member
Registered: 2005-09-15
Posts: 103

Re: handling resources pattern?

after working a few days on it, it seems working well

by accident i found boost::graph
this library is very generic and helps creating graphs e.g. used for routing problems
one thing to mention here: im using shared_ptr's too and will use them in future

i created a simple class for handling the graph library
you can add/remove nodes and create relations - nothing special here - everything is supported by the library
the relations also have a direction - thus i can create a hierarchy
now if a node should be removed e.g. because some operation failed or an operation has finished everything related to this node is removed and its callback function is executed

the advantage i have with this approach is that every class is very loosely coupled to other components
im using shared_ptr to avoid memory leaks, all my classes can now concentrate on the functionality and the relations are handled by my graph
thus i have separated managing the resources and using them

any opinions on this? (although its already implemented) ^^

Offline

  • Index
  • » C++
  • » handling resources pattern?

Board footer

Powered by FluxBB