Oleksandr Redchuk wrote:
2007/9/2, David Brown <[EMAIL PROTECTED]>:
Similarly, if you have multiple objects being constructed or
destructed, their ordering is *not* guaranteed by the compiler
AFAIR, this order guaranteed for objects in block of code and for
objects in file - in order of definitions, but not guaranteed for
objects in different files because of dependence form object files
linking order.
You are correct in thinking about the *logical* ordering - the compiler
must generate code that runs *as though* objects were constructed in
this order. But it is important to remember that as long as the
compiler knows (according to the rules of the language, and what you
have told it in the program) it is safe to do so, it can re-order any
calculations and statements if that lets it generate better (smaller and
faster) code. Ultimately, the compiler can generate any code in any
order, as long as the view through the program's external connections
(its volatiles, and its external library calls) is as specified by the
programmer.
In any case this is not a question of constructor/destructor order or
even it's presence:
class iii {
public:
iii(int _i) : i(_i) {}
~iii() {}
operator int() { return i; }
private:
int i;
};
int foo(int i) {
iii a(5);
return a + i;
}
a even not be created, and this is good optimizer behavior :-)
Exactly. Having the "crit_sect" volatile ensures that it is created and
destroyed, unlike "a" above, but there is nothing to say that other
non-volatile code cannot be moved back and forth over the volatile code.
are guaranteed is that the code will act as though they followed the
order given, based on what the compiler knows of the code.
I'm shure that compiler can change execution sequence of independent
lines of code and can't change that sequence for volatile objects
access.
But I'm not shure, that it can change order of non-volatile and
volatile objects access.
I believe it can (it certainly *does* do such moves here!). Obviously
it is only legal if such moves do not affect the volatile accesses
themselves. Perhaps someone here who has a better knowledge of the
standards could enlighten us, or we could pose the question on
comp.lang.c or comp.lang.c++, as I am by no means sure about this.
avr-gcc optimizer behavior looks reasonable, but is the C++ standard
grant this changing? I not found such grants in standard text...
inline uint32_t get_counter() {
crit_sect cs;
uint32_t x = counter;
asm volatile("" : : : "memory");
return x;
}
Thanks.
Yes, I think, that qualifying counter as volatile is the best solution
- it is really modifiable in interrupt :-)
Making "counter" volatile is certainly the traditional solution. But
volatile is an all-or-nothing approach - there are times when you want
finer-grained control to get optimised code while still having the data
accesses you need. Memory blocks like this can help there, and C++ can
let you hide things nicely within classes (for example, giving you
something that has volatile write semantics, but non-volatile read
semantics - or which has enforced atomic access like this). I'm still
playing around with C++ for this sort of thing - I haven't tried it in a
real project as yet.
mvh.,
David
But in real world get_counter() is part of "external" code wich I
don't want to change. However, crit_sect definition is a part of
"target-specific" include-file for the "external code" and I add asm
volatile("" : : : "memory"); to constructor and destructor of
crit_sect.
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list