[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: unwind_protect improved
From: |
John W. Eaton |
Subject: |
FYI: unwind_protect improved |
Date: |
Tue, 23 Jun 2009 09:26:43 -0400 |
On 23-Jun-2009, Jaroslav Hajek wrote:
| There's a generic unwind_protect::protect_var method able to handle a
| variable of any assignable & copyable class.
| unwind_protect::protect_mem is also provided though it will probably
| be very seldom used (given that you can protect a NDArray or whatever
| with protect_var).
|
| using string tags for unwind_protect frames is now deprecated:
|
| unwind_protect::begin_frame ("tree_evaluator::visit_simple_for_command");
| ...
| unwind_protect::run_frame ("tree_evaluator::visit_simple_for_command");
|
| In particular, if you misspelled the string in run_frame, it would
| silently run all frames down the stack (!).
|
| The proper usage is now:
|
| unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
| ...
| unwind_protect::run_frame (uwp_frame);
|
| which allocates the frame info as a local variable (in fact, it's
| simply the stacksize at the moment of query). This is also somewhat
| more efficient, as there's no string manipulation when processing the
| stack, neither is there need to store them in the stack.
|
| The old tags mechanism is still supported, but the methods are marked
| as deprecated. They should be removed at some point.
|
| It is also possible to protect a single variable locally, if
| performance is of particular concern:
|
| {
| unwind_protect::restore_var<bool> flag_protect (flag); // will
| auto-restore flag at end of block
| flag = temporary value;
| ...
| }
|
| this is more efficient because the compiler can inline everything.
Thanks. This is a big improvement. The old design was copied from
bash early in Octave's history. Since bash is written in C, it
can't take advantage of these kinds of constructor/destructor
features, and I wasn't smart enough to see a better way. Oh, and
templates weren't part of C++ yet...
I think the names "saved_var" and "saved_mem" might be better than
"restore_var" and "restore_mem". It usually seems better to me to
name objects as things rather than actions.
You have
private:
// No copying!
void operator = (const restore_mem&);
in the restore_mem class (and a similar declaration in the restore_var
class) but I don't think this actually prevents copying. For example,
try this program:
class foo
{
public:
foo (void) { }
~foo (void) { }
private:
void operator = (const foo&);
};
int
main (void)
{
foo x;
foo y (x);
foo z = y;
return 0;
}
I think that using
private:
restore_mem (const restore_mem&);
is sufficient, but I usually write
private:
// No copying!
X (const X&);
X& operator = (const X&);
to prevent copying in a class X.
jwe