[AGENT++] MT-safety of get_printable() -- yet another approach

Glenn Puchtel gpuchtel at gplicity.com
Mon Jan 17 02:20:58 CET 2005


Marek,

	Agreed, but it was not my intent to present the complete method
(such as error checking as you pointed out), rather, I was speaking to
the input and output pertaining to thread safety alone.  

	There is a simple way to return an error; throw and exception.
In doing so there is no need for a return code or flag.  This is
typically what I do for my constructors for example where there is no
simple way to indicate failure other than throwing and exception.

Regards,
Glenn

-----Original Message-----
From: agentpp-bounces at agentpp.org [mailto:agentpp-bounces at agentpp.org]
On Behalf Of maom_onet at poczta.onet.pl
Sent: Sunday, January 16, 2005 5:49 PM
To: Glenn Puchtel; agentpp at agentpp.org
Subject: Re: [AGENT++] MT-safety of get_printable() -- yet another
approach

U�ytkownik Glenn Puchtel <gpuchtel at gplicity.com> napisa�:
>Thread safety can be accomplished by using local (stack) variables and
>returning an "object"; in this case a "std::string" object.
>
>Now, before you cringe at this thought understand that goal is thread
>safety (integrity) rather than performance.  However, the cost to
>performance might not be as much as you think.  By returning an object
>you afford the compiler the opportunity to implement what is known as
>"Return Value Optimization", which eliminates the over head of one copy
>constructor.
>
>The following two methods should be thread safe (to the extent of
>calling them and using the returned value):
>
>
>const std::string OctetStr::get_printable() const
>{
>std::string result;
>
>[code to copy current value into "result" goes here]
>
>return result;  // No, this is not returning a local variable
>}

Of course, 1. MT-safety depends on what is inside the [] block; and 2.
'const' at front of the declaration is not really needed.

>, or for copy... 
>
>
>
>const std::string SafeGetPrintable(Oid oid) const
>{
>std::string result = oid.get_printable();
>
>return result;  // No, this is not returning a local variable
>}

This is almost exactly what I have proposed before; the only difference
is that you skip error checks. Both copy constructor and buffer creation
could fail (usually, due to lack of memory). Thus, I would opt for a
completely reliable implementation. Perhaps, with optimization enabled,
your version is indeed slightly more efficient (equivalent to
std::string s(oid.get_printable()) but there is no simple way to return
an error. Returning a flag through a second parameter, well, I think
would not be a good design. Returning an empty string on error (with no
notification) is not reliable, too.

Best regards,

Marek

>
>Passing Oid by value (in SafeGetPrintable) you pay the cost of a
>constructor but its now on the stack (which ensures its content will
not
>change for your thread). 
>
>More than likely your compiler performs "Return Value Optimization"
>(also known as RVO) so you avoid the cost of a constructor when
>returning the std:string object.  Also, since you return a class
object,
>it gets destroyed when it goes out of scope so you avoid memory leaks
as
>an additional benefit to this approach.
>
>All-in-all this approach is (arguably) a bit more expensive in regards
>to performance, but since integrity is the goal and you are just going
>to have to pay the cost (somewhere).
>
>Regards,
>Glenn
>
>
>
>-----Original Message-----
>Wrom: VRESKPNKMBIPBARHDMNNSKVFVWRKJVZCMHVIBGDADRZFSQHYUCDDJBLVLMHAALPT
>On Behalf Of maom_onet at poczta.onet.pl
>Sent: Saturday, January 15, 2005 2:29 PM
>To: Don Radick
>Cc: agentpp at agentpp.org
>Subject: Re: Re: Re: [AGENT++] MT-safety of get_printable() (was:
>SNMP++advocacy)
>
>U�ytkownik Don Radick <dradick at mindspring.com> napisa�:
>>On Fri, 2005-01-14 at 10:42 +0100, maom_onet at poczta.onet.pl wrote:
>>> U�ytkownik Don Radick <dradick at mindspring.com> napisa�:
>>> >On Wed, 2005-01-12 at 23:35 +0100, maom_onet at poczta.onet.pl wrote:
>>> >> A possible approach would be:
>>> >> 
>>> >> if (addr_changed)
>>> >> {
>>> >>    char buf[LARGE_ENOUGH];
>>> >>    format_output(buf);
>>> >>    strcpy(output_buffer, buf);
>>> >>    addr_changed = false;
>>> >> }
>>> >> return output_buffer;
>>> >> 
>>> >> There is some overhead but this guarantees "strong MT-safety".
>>You are correct.  I was continuing to think in MT terms. and your
>>solution will simply require the other thread to wait on the buffer
>>copy.
>
>Another MT-safe approach uses a temporary copy of an object, e.g.:
>
>bool SafeGetPrintable(const Oid& oid, std::string& s) {
>
>    Oid oidCopy(oid);
>    if (!oidCopy.valid())
>        return false;
>    const char* ptr = oidCopy.get_printable();
>    if (!ptr)
>        return false;
>    s = ptr;
>    return s == ptr;    // be paranoid
>}
>
>Looks a bit paranoid, especially error checks, but the idea is to use a
>copy. Theoretically looks like a big overhead, and this is true to some
>degree; however, get_printable() in Oid class allocates dynamically a
>buffer (OctetStr seems to do the same), so when we use a temporary
>object, this buffer is not created nor held for our object.
>
>But in fact, I think a final solution would be to provide
>get_printable(buf, buflen) functions.
>
>Marek
>_______________________________________________
>AGENTPP mailing list
>AGENTPP at agentpp.org
>http://agentpp.org/mailman/listinfo/agentpp
>
>
>_______________________________________________
>AGENTPP mailing list
>AGENTPP at agentpp.org
>http://agentpp.org/mailman/listinfo/agentpp
>
_______________________________________________
AGENTPP mailing list
AGENTPP at agentpp.org
http://agentpp.org/mailman/listinfo/agentpp





More information about the AGENTPP mailing list