views:

136

answers:

7

Hello, I'm writing a piece of sotware that needs objects that exchange messages between each other. The messages have to have the following contents:

Peer *srcPeer;
const char* msgText;
void* payload;
int payLoadLen;

now, Peer has to be a pointer as I have another class that manages Peers. For the rest I'm doubtful... for example I may copy the message text and payload (by allocating two new buffers) as the message is created, then putting the deletes in the destructor of the message. This has the great advantage of avoiding to forget the deletes in the consumer functions (not the mention to make those functions simpler) but it will result in many allocations & copies and can make everything slow. So I may just assing pointers and still have the destructor delete eveything... or ... well this is a common situation that in other programming languages is not even a dilemma as there is a GC. What are your suggestions and what are the most popular practices?

Edit: I mean that I'd like to know what are the best practices to pass the contents... like having another object that keeps track of them, or maybe shared pointers... or what would you do...

+1  A: 

If all of the messages are similar, consider using a trash stack (http://library.gnome.org/devel/glib/stable/glib-Trash-Stacks.html) - this way, you can keep a stack of allocated-yet-uninitialized message structures that you can reuse without taking the constant malloc/free hit.

Paul Betts
my concern was not about allocating messages... but about the content passing. What are the best strategies... I'll modify my question.
gotch4
+2  A: 

You need clear ownership: when a message is passed between peers, is the ownership changed? If you switch ownership, just have the receiver do the clean-up.

If you just "lease" a message, make sure to have a "return to owner" procedure.

Is the message shared? Then you probably need some copying or have mutexes to protect access.

jldupont
@gotch4: does my answer satisfy you?
jldupont
A: 

Consider using shared_ptr<>, available from Boost and also part of the std::tr1 library, rather than raw pointers. It's not the best thing to use in all cases, but it looks like you want to keep things simple and it's very good at that. It's local reference-count garbage collection.

David Thornley
A: 

There are no rules or even best practices for this in C++, except insofar as you make a design decision about pointer ownership and stick to it.

You can try to enforce a particular policy through use of smart pointers, or you can simply document the designed behavior and hope everyone reads the manual.

Warren Young
A: 

In C++, you can have reference counting too, like here:

http://library.gnome.org/devel/glibmm/stable/classGlib%5F1%5F1RefPtr.html

In this case, you can pass Glib::RefPtr objects. When the last of these RefPtr-s are destroyed associated to a pointer, the object is deleted itself.

If you do not want to use glibmm, you can implement it too, it's not too difficult. Also, probably STL and boost have something like these too.

Just watch out for circular references.

terminus
A: 

The simplest thing to do is to use objects to manage the buffers. For instance, you might use std::string for both the msgText and payload members and you could do away with the payLoadLen as it would be taken care of by the payload.size() method.

If and only if you measure the performance of this solution and the act of copying the msgText and payload were causing an unacceptable performance hit, you might choose to using a shared pointer to structure that was shared by copies of the message.

In (almost) no situation would I rely on remembering to call delete in a destructor or manually writing safe copy-assignment operator and copy constructor.

Charles Bailey
A: 

The simplest policy to deal with is copying the entire message (deep copy) and send that copy to the recipient. It will require more allocation, but it frees you from many problems related to concurrent access to data. If performance gets critical, there is still room for some optimizations (like avoiding copies if the object only has one owner who is willing to give up ownership of it when sending it, etc).

Each owner is then responsible for cleaning up the message object.

Carl Seleborg
hmmm... sounds like a lazy approach to me.
jldupont
Yes, to the same extend as using java instead of assembler: move up one level of abstraction to get rid of loads of problems. Erlang uses this approach, with great success.
Carl Seleborg