activemq-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "David Fahlander" <David.Fahlan...@portwise.com>
Subject RE: Regarding feedback on OpenWire C++ client
Date Tue, 28 Mar 2006 09:01:47 GMT
Hi Nathan,

> > 1) Use of smart pointers.
> >
> > Though the user interface would be cleaner without smart pointers
they 
> > serves a purpose even when the passed in object is not owned by the
client.
> > As soon as an object is shared between two classes you have the 
> > problem when the object should be deleted - this problem is
eliminated 
> > when using SP's, the object is deleted when both object releases its
reference to it.
>
> I'm not sure I agree.  For user-generated objects, it should be up to
the user to
> add and remove references to them across the openwire library (such as
references
> to IMessageListeners).  When the user passes in a reference to one of
his objects,
> he's not expecting to give any amount of lifetime control to the
openwire code.
> In fact, the user object may not even have been created on the heap,
it may be a
> local variable that was added just for the scope of a function.  In
this case,
> when the openwire library decides to delete it, the application blows
up!  We
> have to make a separation of what is and what is not under our
library's control.
> We can't assume a structure of the client code, this forces the client
into a
> particular way of programming and causes our client to become a burden
to the
> developer and will turn them off to using ActiveMQ.

Regarding objects that the user provides, we still get benefits by using
smart pointers for them. It is not always the creator that is
responsible of deletion. Especially in a threaded application it can be
important to not end-up with ghost pointers. A thread in our client
library that holds a pointer to a listener, must be able to rely on that
the instance is still alive as long as it holds the SP to it. If the
user would provide an ordinary pointer, the user must never delete it as
long as there might be threads in our library using it. What about
"static" objects that should last forever in the client's lifetime then?
Still, we want to be able to take down the client in a controlled way.
Doing that without smart pointers, may create a lot of problems in our
experience.

The "burden" for the user would only lie in the classes that implement
our interfaces. If our API requires a p<IMessageListener>, the user must
hold his message listener using a p<MyMessageListener> allocated with
new MyMessageLister (...);. The user does not have to let this affect
his design. If the user wants, this instance can lie as a member within
another class that is neither derived from our interface nor maintained
as a smart pointer.

> > SP's and Strings: Semi-agreed :) The setters should all have "const
char*"
> > but we could change the getters to std:string (without SP), then it
is 
> > up to the user to either use it as a std:string or a "const char*".
>
> I think symmetry is a good thing.  We should pick one way or the other
...
> either both the getter and setter take const char* or they both take
strings.
> Also, when passing strings around, they should be passed as "const
std::string&" ...
> this way you don't have to copy the entire string, you just pass a
constant reference
> to it.  This will save a lot of processing when dealing with large
text messages, for
> example.

The options we have regarding passing and holding strings are the
following:

Class Xxx {
  p<string> name;
public:
  void setName (p<string> name) {
    this->name = name;
  }
  p<string> getName () {
    return this->name;
  }
  p<string> createName() {
    return new string ("name: " + *name);
  }
};

In the above example, strings are never copied, just the ptr value. The
downside is that the caller needs to pass their strings as p<string>.
This version adds the least overhead.

---

Class Xxx {
  string name;
  void setName (const string& name) {
    this->name = name;
  }
  const string& getName () {
    return this->name;
  }
  string createName() {
    return string ("name: " + name);
  }
};

In this example the string is always copied in the setters but not in
getters.

---

Class Xxx {
  const char* name;
  void setName (const char* name) {
    this->name = name;
  }
  const char* getName () {
    return this->name;
  }
  const char* () {
    const char* val = new char[256];
    strcpy (val, "name: ");
    strcat (val, name);
    return val;
  }
};

This example is unacceptable since ownership is undefined.

We are open to use any of the first two examples. 

Regards,
David & Mats

Mime
View raw message