Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #12284 > unrolled thread
| Started by | ittium <ittium@gmail.com> |
|---|---|
| First post | 2011-12-10 13:58 +0530 |
| Last post | 2011-12-12 00:31 -0800 |
| Articles | 13 — 6 participants |
Back to article view | Back to comp.lang.c++
Exception propagation ittium <ittium@gmail.com> - 2011-12-10 13:58 +0530
Re: Exception propagation Ian Collins <ian-news@hotmail.com> - 2011-12-10 22:42 +1300
Re: Exception propagation Paavo Helde <myfirstname@osa.pri.ee> - 2011-12-10 04:03 -0600
Re: Exception propagation Paavo Helde <myfirstname@osa.pri.ee> - 2011-12-10 06:12 -0600
Re: Exception propagation Goran <goran.pusic@gmail.com> - 2011-12-10 10:29 -0800
Re: Exception propagation Christopher <cpisz@austin.rr.com> - 2011-12-11 11:56 -0800
Re: Exception propagation Ebenezer <woodbrian77@gmail.com> - 2011-12-11 21:44 -0800
Re: Exception propagation Paavo Helde <myfirstname@osa.pri.ee> - 2011-12-12 00:24 -0600
Re: Exception propagation Ebenezer <woodbrian77@gmail.com> - 2011-12-12 02:50 -0800
Re: Exception propagation Goran <goran.pusic@gmail.com> - 2011-12-12 04:06 -0800
Re: Exception propagation Ebenezer <woodbrian77@gmail.com> - 2011-12-12 09:37 -0800
Re: Exception propagation Paavo Helde <myfirstname@osa.pri.ee> - 2011-12-12 11:16 -0600
Re: Exception propagation Goran <goran.pusic@gmail.com> - 2011-12-12 00:31 -0800
| From | ittium <ittium@gmail.com> |
|---|---|
| Date | 2011-12-10 13:58 +0530 |
| Subject | Exception propagation |
| Message-ID | <jbv58a$raq$1@dont-email.me> |
Group, I have a situation where some of the class/non-class methodsmake many levels of function calls, some of the function in this call hierarchy may throw exception, what is a good idea #1 inner function rethrow (by empty throw), such that exception is propagated back to the top level function. #2inner function does not throw (by empty throw), this exception will be by **default** propagated back to the top level routine (assuming intermediate routines are not catching the exception). #3 When it is a good idea that function(inner) receiving the exception or some intermediate function catch it and from there error event is propagated back through some error code. thanks Ittium
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-12-10 22:42 +1300 |
| Message-ID | <9kgnrmFhipU1@mid.individual.net> |
| In reply to | #12284 |
On 12/10/11 09:28 PM, ittium wrote: > Group, > > I have a situation where some of the class/non-class methodsmake many > levels of function calls, some of the function in this call hierarchy > may throw exception, what is a good idea > > #1 inner function rethrow (by empty throw), such that exception is > propagated back to the top level function. > > #2inner function does not throw (by empty throw), this exception will be > by **default** propagated back to the top level routine (assuming > intermediate routines are not catching the exception). > > #3 When it is a good idea that function(inner) receiving the exception > or some intermediate function catch it and from there error event is > propagated back through some error code. The first place where it makes sense to catch the exception catches it and performs the appropriate recovery actions. if there isn't an appropriate place, catch it in main, report and exit. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-12-10 04:03 -0600 |
| Message-ID | <Xns9FB77ABD5B464myfirstnameosapriee@216.196.109.131> |
| In reply to | #12284 |
ittium <ittium@gmail.com> wrote in news:jbv58a$raq$1@dont-email.me: > Group, > > I have a situation where some of the class/non-class methodsmake many > levels of function calls, some of the function in this call hierarchy > may throw exception, what is a good idea > > #1 inner function rethrow (by empty throw), such that exception is > propagated back to the top level function. > > #2inner function does not throw (by empty throw), this exception will be > by **default** propagated back to the top level routine (assuming > intermediate routines are not catching the exception). > > #3 When it is a good idea that function(inner) receiving the exception > or some intermediate function catch it and from there error event is > propagated back through some error code. Most functions should use #2 and not care about exceptions (apart of not using non-exception-safe code). If a function catches an exception, then it ought to be able to handle it somehow, at least to some extent. If it can handle it fully, then it continues the execution normally. If it is not able to handle it fully, it might construct a new exception (with added or clarified information, for example) and throw that, or it may throw the initial exception. Such functions should be rare, however. Using #3 should be only needed in extern "C" functions. Such a function can be called from C or Pascal or whatever, which have no way to catch C++ exceptions so all exceptions must be catched and "converted" to an error code before returning the error back to the caller. #3 migh also be justified when interfacing some old legacy C++ code which is not thread-safe and expects error codes instead of exceptions. cheers Paavo
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-12-10 06:12 -0600 |
| Message-ID | <Xns9FB79073864F4myfirstnameosapriee@216.196.109.131> |
| In reply to | #12288 |
Paavo Helde <myfirstname@osa.pri.ee> wrote in news:Xns9FB77ABD5B464myfirstnameosapriee@216.196.109.131: > #3 migh also be justified when interfacing some old legacy C++ code > which is not thread-safe Oops, wanted to say *exception-safe* here.
[toc] | [prev] | [next] | [standalone]
| From | Goran <goran.pusic@gmail.com> |
|---|---|
| Date | 2011-12-10 10:29 -0800 |
| Message-ID | <c99becda-d99a-455e-bfa2-b3843d5fd0f0@e2g2000vbb.googlegroups.com> |
| In reply to | #12284 |
On Dec 10, 9:28 am, ittium <itt...@gmail.com> wrote: > Group, > > I have a situation where some of the class/non-class methodsmake many > levels of function calls, some of the function in this call hierarchy > may throw exception, what is a good idea > > #1 inner function rethrow (by empty throw), such that exception is > propagated back to the top level function. > > #2inner function does not throw (by empty throw), this exception will be > by **default** propagated back to the top level routine (assuming > intermediate routines are not catching the exception). > > #3 When it is a good idea that function(inner) receiving the exception > or some intermediate function catch it and from there error event is > propagated back through some error code. In C++ code, there's no good reason to ever STOP exception propagation AND replace it with return code, except e.g. in main. Or perhaps when you are writing a module that should be exposed to a language that can't receive C++ exceptions. Further, there are RARE reasons to stop exception propagation. Off the top of my head, some of those rare ones are: * main() - you seldom want want terminate() to kick in, which is what will happen if exception escapes main() * for similar reason, any top-level thread function * to re-throw existing exception, but with further info about the error (e.g. "bad_alloc happened when fryding the swoorf"). This is because lowest-level exceptions have no further info about the context in which they happened, and that is useful, and C++ has no call stack in exception objects ;-). * there's a loop whose whole body can fail, but next iteration still should happen, usually after reporting the error. Example: a server- kind-of-a-program, who has a client serving loop, and serving one client request failed. You seem to be trying to make a rule of thumb here, but without the context. That is seldom a good idea. It's better to ask "what should I do" from a given context. Goran.
[toc] | [prev] | [next] | [standalone]
| From | Christopher <cpisz@austin.rr.com> |
|---|---|
| Date | 2011-12-11 11:56 -0800 |
| Message-ID | <5d45df5d-e915-49e7-8e71-7e304631337d@h3g2000yqa.googlegroups.com> |
| In reply to | #12314 |
On Dec 10, 12:29 pm, Goran <goran.pu...@gmail.com> wrote: > On Dec 10, 9:28 am, ittium <itt...@gmail.com> wrote: > > > > > > > Group, > > > I have a situation where some of the class/non-class methodsmake many > > levels of function calls, some of the function in this call hierarchy > > may throw exception, what is a good idea > > > #1 inner function rethrow (by empty throw), such that exception is > > propagated back to the top level function. > > > #2inner function does not throw (by empty throw), this exception will be > > by **default** propagated back to the top level routine (assuming > > intermediate routines are not catching the exception). > > > #3 When it is a good idea that function(inner) receiving the exception > > or some intermediate function catch it and from there error event is > > propagated back through some error code. > > In C++ code, there's no good reason to ever STOP exception propagation > AND replace it with return code, except e.g. in main. Or perhaps when > you are writing a module that should be exposed to a language that > can't receive C++ exceptions. > > Further, there are RARE reasons to stop exception propagation. Off the > top of my head, some of those rare ones are: > > * main() - you seldom want want terminate() to kick in, which is what > will happen if exception escapes main() > * for similar reason, any top-level thread function > * to re-throw existing exception, but with further info about the > error (e.g. "bad_alloc happened when fryding the swoorf"). This is > because lowest-level exceptions have no further info about the context > in which they happened, and that is useful, and C++ has no call stack > in exception objects ;-). > * there's a loop whose whole body can fail, but next iteration still > should happen, usually after reporting the error. Example: a server- > kind-of-a-program, who has a client serving loop, and serving one > client request failed. > > You seem to be trying to make a rule of thumb here, but without the > context. That is seldom a good idea. It's better to ask "what should I > do" from a given context. > > Goran.- Hide quoted text - > > - Show quoted text - Catching an exception at the top level function of a thread is not so rare in my opinion and very often overlooked. I've actually made it a point to examine thread entry points now, and make sure everything is caught and handled in some way.
[toc] | [prev] | [next] | [standalone]
| From | Ebenezer <woodbrian77@gmail.com> |
|---|---|
| Date | 2011-12-11 21:44 -0800 |
| Message-ID | <3937da31-10c3-4eea-9105-bd2462ce9f25@v29g2000yqv.googlegroups.com> |
| In reply to | #12314 |
On Dec 10, 12:29 pm, Goran <goran.pu...@gmail.com> wrote:
>
> In C++ code, there's no good reason to ever STOP exception propagation
> AND replace it with return code, except e.g. in main. Or perhaps when
> you are writing a module that should be exposed to a language that
> can't receive C++ exceptions.
>
> Further, there are RARE reasons to stop exception propagation. Off the
> top of my head, some of those rare ones are:
>
> * main() - you seldom want want terminate() to kick in, which is what
> will happen if exception escapes main()
> * for similar reason, any top-level thread function
> * to re-throw existing exception, but with further info about the
> error (e.g. "bad_alloc happened when fryding the swoorf"). This is
> because lowest-level exceptions have no further info about the context
> in which they happened, and that is useful, and C++ has no call stack
> in exception objects ;-).
> * there's a loop whose whole body can fail, but next iteration still
> should happen, usually after reporting the error. Example: a server-
> kind-of-a-program, who has a client serving loop, and serving one
> client request failed.
>
Well that last one is hardly rare. Most programs today are
servers, I think.
I stop the propagation in the following for performance
reasons:
cmw_request
getRequest (uint8_t byteOrder
, sock_type sock)
{
static ReceiveBuffer<SameFormat> localbuf(4096);
#ifdef ENDIAN_BIG
static ReceiveBuffer<LeastSignificantFirst> otherlocalbuf(4096);
#else
static ReceiveBuffer<MostSignificantFirst> otherlocalbuf(4096);
#endif
uint8_t clientFormat;
Read(sock, &clientFormat, 1);
try {
if (clientFormat == byteOrder) {
localbuf.sock_ = sock;
while (!localbuf.GotPacket()) ;
return cmw_request(localbuf);
} else {
otherlocalbuf.sock_ = sock;
while (!otherlocalbuf.GotPacket()) ;
return cmw_request(otherlocalbuf);
}
} catch (::std::exception const& ex) {
clientFormat == byteOrder ? localbuf.Reset() :
otherlocalbuf.Reset();
throw;
}
}
The exception catching allows me to make some variables
static that would otherwise be allocating and releasing
memory from the heap each time the function is called.
It is kind of experimental, but so far so good.
The above function is from this file --
http://webEbenezer.net/misc/cmwAmbassador.cc.
Brian Wood
Ebenezer Enterprises
http://webEbenezer.net
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-12-12 00:24 -0600 |
| Message-ID | <Xns9FB9558B5DC5Fmyfirstnameosapriee@216.196.109.131> |
| In reply to | #12386 |
Ebenezer <woodbrian77@gmail.com> wrote in news:3937da31-10c3-4eea-9105-
bd2462ce9f25@v29g2000yqv.googlegroups.com:
>
> I stop the propagation in the following for performance
> reasons:
>
> cmw_request
> getRequest (uint8_t byteOrder
> , sock_type sock)
> {
> static ReceiveBuffer<SameFormat> localbuf(4096);
> #ifdef ENDIAN_BIG
> static ReceiveBuffer<LeastSignificantFirst> otherlocalbuf(4096);
> #else
> static ReceiveBuffer<MostSignificantFirst> otherlocalbuf(4096);
> #endif
>
> uint8_t clientFormat;
> Read(sock, &clientFormat, 1);
> try {
> if (clientFormat == byteOrder) {
> localbuf.sock_ = sock;
> while (!localbuf.GotPacket()) ;
> return cmw_request(localbuf);
> } else {
> otherlocalbuf.sock_ = sock;
> while (!otherlocalbuf.GotPacket()) ;
> return cmw_request(otherlocalbuf);
> }
> } catch (::std::exception const& ex) {
> clientFormat == byteOrder ? localbuf.Reset() :
> otherlocalbuf.Reset();
> throw;
> }
> }
>
> The exception catching allows me to make some variables
> static that would otherwise be allocating and releasing
> memory from the heap each time the function is called.
> It is kind of experimental, but so far so good.
This is just lack of RAII. Why don't you just put a Reset() call in the
destructor of ReceiveBuffer?
Cheers
Paavo
[toc] | [prev] | [next] | [standalone]
| From | Ebenezer <woodbrian77@gmail.com> |
|---|---|
| Date | 2011-12-12 02:50 -0800 |
| Message-ID | <def8847f-0022-4b1d-98b6-a5f2d9c20074@p14g2000yqp.googlegroups.com> |
| In reply to | #12387 |
On Dec 12, 12:24 am, Paavo Helde <myfirstn...@osa.pri.ee> wrote: > Ebenezer <woodbria...@gmail.com> wrote in news:3937da31-10c3-4eea-9105- > > > The exception catching allows me to make some variables > > static that would otherwise be allocating and releasing > > memory from the heap each time the function is called. > > It is kind of experimental, but so far so good. > > This is just lack of RAII. Why don't you just put a Reset() call in the > destructor of ReceiveBuffer? > I think you may have a point(s) in the other thread and I'll have to do some digging on that later. So it seems easier to reply here. I'm intentionally avoiding RAII here in order to reuse resources. I don't think calling Reset in the dtor would help. (I can't think of other places where I avoid RAII.)
[toc] | [prev] | [next] | [standalone]
| From | Goran <goran.pusic@gmail.com> |
|---|---|
| Date | 2011-12-12 04:06 -0800 |
| Message-ID | <6c0af265-ceb4-4dae-a78d-f377c82607bf@q11g2000vbq.googlegroups.com> |
| In reply to | #12399 |
On Dec 12, 11:50 am, Ebenezer <woodbria...@gmail.com> wrote: > On Dec 12, 12:24 am, Paavo Helde <myfirstn...@osa.pri.ee> wrote: > > > Ebenezer <woodbria...@gmail.com> wrote in news:3937da31-10c3-4eea-9105- > > > > The exception catching allows me to make some variables > > > static that would otherwise be allocating and releasing > > > memory from the heap each time the function is called. > > > It is kind of experimental, but so far so good. > > > This is just lack of RAII. Why don't you just put a Reset() call in the > > destructor of ReceiveBuffer? > > I think you may have a point(s) in the other thread and I'll > have to do some digging on that later. So it seems easier to > reply here. > I'm intentionally avoiding RAII here in order > to reuse resources. I don't think calling Reset in the dtor > would help. (I can't think of other places where I avoid > RAII.) Perhaps Paavo was a bit too quick with his suggestion... You don't __need__ to destroy ReceiveBuffer. You can merely have an object whose destruction calls Reset() on the buffer (Reset() should be a no-fail operation, which seems a good guess). So you have best of both world: resource reuse that you hold dear, and application of RAII for simpler code. That said, it looks like you could get your resource reuse by changing ReceiveBuffer to receive the buffer it operates on from the outside. (I am guessing that the expensive resource is said buffer that is on the heap, and that Reset is dirt-cheap otherwise.) Note: function you've shown isn't thread-safe due to the use of the static. I don't know if it matters, but if it does, you should look for thread-local storage on your platform. Goran.
[toc] | [prev] | [next] | [standalone]
| From | Ebenezer <woodbrian77@gmail.com> |
|---|---|
| Date | 2011-12-12 09:37 -0800 |
| Message-ID | <e1df3e7f-1d3f-478a-b7f5-5414533c82d8@l29g2000yqf.googlegroups.com> |
| In reply to | #12402 |
On Dec 12, 6:06 am, Goran <goran.pu...@gmail.com> wrote: > On Dec 12, 11:50 am, Ebenezer <woodbria...@gmail.com> wrote: > > > > > > > On Dec 12, 12:24 am, Paavo Helde <myfirstn...@osa.pri.ee> wrote: > > > > Ebenezer <woodbria...@gmail.com> wrote in news:3937da31-10c3-4eea-9105- > > > > > The exception catching allows me to make some variables > > > > static that would otherwise be allocating and releasing > > > > memory from the heap each time the function is called. > > > > It is kind of experimental, but so far so good. > > > > This is just lack of RAII. Why don't you just put a Reset() call in the > > > destructor of ReceiveBuffer? > > > I think you may have a point(s) in the other thread and I'll > > have to do some digging on that later. So it seems easier to > > reply here. > > I'm intentionally avoiding RAII here in order > > to reuse resources. I don't think calling Reset in the dtor > > would help. (I can't think of other places where I avoid > > RAII.) > > Perhaps Paavo was a bit too quick with his suggestion... You don't > __need__ to destroy ReceiveBuffer. You can merely have an object whose > destruction calls Reset() on the buffer (Reset() should be a no-fail > operation, which seems a good guess). So you have best of both world: > resource reuse that you hold dear, and application of RAII for simpler > code. > > That said, it looks like you could get your resource reuse by changing > ReceiveBuffer to receive the buffer it operates on from the outside. > (I am guessing that the expensive resource is said buffer that is on > the heap, and that Reset is dirt-cheap otherwise.) That's correct. Thanks for the reminder about scope guard. I have to think about that and your arguments here further. > > Note: function you've shown isn't thread-safe due to the use of the > static. I don't know if it matters, but if it does, you should look > for thread-local storage on your platform. > Yes, I'm aware of that. The program is currently single-threaded. I've thought about the possibility of makings it use two threads. (It is the middle tier of a 3-tier system.) One thread would handle requests from the front tier and the other thread would handle responses from the back tier. I don't think changing the program in that way would be a problem as far as the statics in this function.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-12-12 11:16 -0600 |
| Message-ID | <Xns9FB9C405F56E5myfirstnameosapriee@216.196.109.131> |
| In reply to | #12399 |
Ebenezer <woodbrian77@gmail.com> wrote in news:def8847f-0022-4b1d-98b6- a5f2d9c20074@p14g2000yqp.googlegroups.com: > On Dec 12, 12:24 am, Paavo Helde <myfirstn...@osa.pri.ee> wrote: >> Ebenezer <woodbria...@gmail.com> wrote in news:3937da31-10c3-4eea- 9105- >> >> > The exception catching allows me to make some variables >> > static that would otherwise be allocating and releasing >> > memory from the heap each time the function is called. >> > It is kind of experimental, but so far so good. >> >> This is just lack of RAII. Why don't you just put a Reset() call in the >> destructor of ReceiveBuffer? >> > > I think you may have a point(s) in the other thread and I'll > have to do some digging on that later. So it seems easier to > reply here. > I'm intentionally avoiding RAII here in order > to reuse resources. I don't think calling Reset in the dtor > would help. Right, I overlooked the 'static'. But Goran is right, you can make another local object whose destructor calls Reset(). Cheers Paavo
[toc] | [prev] | [next] | [standalone]
| From | Goran <goran.pusic@gmail.com> |
|---|---|
| Date | 2011-12-12 00:31 -0800 |
| Message-ID | <68609df5-a6f6-432d-ad54-1c75342e4615@f5g2000yqg.googlegroups.com> |
| In reply to | #12386 |
On Dec 12, 6:44 am, Ebenezer <woodbria...@gmail.com> wrote:
> On Dec 10, 12:29 pm, Goran <goran.pu...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
>
>
> > In C++ code, there's no good reason to ever STOP exception propagation
> > AND replace it with return code, except e.g. in main. Or perhaps when
> > you are writing a module that should be exposed to a language that
> > can't receive C++ exceptions.
>
> > Further, there are RARE reasons to stop exception propagation. Off the
> > top of my head, some of those rare ones are:
>
> > * main() - you seldom want want terminate() to kick in, which is what
> > will happen if exception escapes main()
> > * for similar reason, any top-level thread function
> > * to re-throw existing exception, but with further info about the
> > error (e.g. "bad_alloc happened when fryding the swoorf"). This is
> > because lowest-level exceptions have no further info about the context
> > in which they happened, and that is useful, and C++ has no call stack
> > in exception objects ;-).
> > * there's a loop whose whole body can fail, but next iteration still
> > should happen, usually after reporting the error. Example: a server-
> > kind-of-a-program, who has a client serving loop, and serving one
> > client request failed.
>
> Well that last one is hardly rare. Most programs today are
> servers, I think.
>
> I stop the propagation in the following for performance
> reasons:
>
> cmw_request
> getRequest (uint8_t byteOrder
> , sock_type sock)
> {
> static ReceiveBuffer<SameFormat> localbuf(4096);
> #ifdef ENDIAN_BIG
> static ReceiveBuffer<LeastSignificantFirst> otherlocalbuf(4096);
> #else
> static ReceiveBuffer<MostSignificantFirst> otherlocalbuf(4096);
> #endif
>
> uint8_t clientFormat;
> Read(sock, &clientFormat, 1);
> try {
> if (clientFormat == byteOrder) {
> localbuf.sock_ = sock;
> while (!localbuf.GotPacket()) ;
> return cmw_request(localbuf);
> } else {
> otherlocalbuf.sock_ = sock;
> while (!otherlocalbuf.GotPacket()) ;
> return cmw_request(otherlocalbuf);
> }
> } catch (::std::exception const& ex) {
> clientFormat == byteOrder ? localbuf.Reset() :
> otherlocalbuf.Reset();
> throw;
> }
>
> }
I don't think you should count this as "stopping propagation", as you-
re-throw.
You should further consider using Alexandrescu/Martinean's excellent
scope guard for such things. That would give you e.g.
cmw_request
getRequest (uint8_t byteOrder
, sock_type sock)
{
static ReceiveBuffer<SameFormatlocalbuf(4096);
#ifdef ENDIAN_BIG
static ReceiveBuffer<LeastSignificantFirstotherlocalbuf(4096);
#else
static ReceiveBuffer<MostSignificantFirstotherlocalbuf(4096);
#endif
uint8_t clientFormat;
Read(sock, &clientFormat, 1);
ON_BLOCK_EXIT_OBJ(byteOrder ? localbuf : otherlocalbuf,
&buffer_class::Reset());
if (clientFormat == byteOrder) {
localbuf.sock_ = sock;
while (!localbuf.GotPacket()) ;
return cmw_request(localbuf);
} else {
otherlocalbuf.sock_ = sock;
while (!otherlocalbuf.GotPacket()) ;
return cmw_request(otherlocalbuf);
}
+1 for Paavo's remark. Use RAII, that gets you more time for good
things in life ;-).
Goran.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web