 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Michael Trocken Guest
|
Posted: Wed Nov 26, 2003 7:43 am Post subject: RAII fuer Ausdruecke |
|
|
Gemäß 12.2p3 werden temporäre Objekte in Ausdrücken zerstört, sobald
der komplette Ausdruck "abgearbeitet" ist:
...
Temporary objects are destroyed as the last step in evaluating
the full-expression (1.9) that (lexically) contains the point
where they were created.
Unabhängig vom ursprünglichen Sinn dieser Festlegung (s.[1]) wären
aber auch andere Verwendungen denkbar.
Z.B. könnte man in einem Ausruck ein temporäres Objekt erzeugen und
den Destruktoraufruf nutzen, um dort Ressourcen freizugeben, die für
den Ausdruck verwendet wurden, also eine Art "RAII für Ausdrücke".
(RAII = resource acquisition is initialisation)
Damit ließen sich Synchronisationsprobleme zwischen verschiedenen
Threads lösen. Wenn es z.B. in einem Programm Ausgaben der folgenden
Art ...
cout << a << "bla" << b << "!n";
.... in mehreren Threads gibt, dann kommt es vor, dass mitten in der
Ausgabe zwischen den Threads umgeschaltet wird, und die aus
unterschiedlichen Threads ausgegebenen Zeilen werden munter
miteinander vermischt.
Folgendes soll das Problem lösen:
namespace sync {
struct cout_t {} cout;
using std::endl;
struct locker {
locker (const cout_t&) {
std::cout << "n" << "(LOCK)" << endl;
}
~locker() {
std::cout << "(UNLOCK)" << endl;
}
};
template
inline std::ostream& operator<<(const locker&, const T& rhs) {
return std::cout << rhs;
}
}
void bla() {
using namespace sync;
cout << "Ich denke, " << "also bin ich " << "am Denken.n";
cout << 1 << "was" << 2 << "du" << 3 << "nicht"
<< 4 << "sagst!" << endl;
}
Ausgabe:
(LOCK)
Ich denke, also bin ich am Denken.
(UNLOCK)
(LOCK)
1was2du3nicht4sagst!
(UNLOCK)
Dabei kann man sich LOCK bzw. UNLOCK durch Synchronisationsbefehle
(z.B. "critical section" unter W'dows) ersetzt denken.
Interessant ist 12.2p3 vor allem deshalb, weil der Punkt der
Zerstörung des temporären Objektes so genau definiert ist, und nicht,
wie ich praktisch seit meiner frühen Jugend dachte, bis z.B. zum Ende
des umschließenden Blocks hinausgezögert werden kann. Fatal wäre dies
u.U. für die Synchronisation, denn dann könnte das Programm
blockieren.
Ich habe die folgenden Fragen:
° Welche Probleme ergeben sich möglicherweise bei dem obigen Ansatz?
° Welche Lösungen, die Ausgabe zu synchronisieren, verwendet ihr?
Gruß,
Michael
[1]->http://groups.google.de/groups?dq=&hl=de&lr=&ie=UTF-8&oe=UTF-8&selm=1069321934.irz779%25sr21%40inf.tu-dresden.de
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Wed Nov 26, 2003 4:36 pm Post subject: Re: RAII fuer Ausdruecke |
|
|
Hallo,
Michael Trocken <s1234569 (AT) hotmail (DOT) com> wrote:
[...]
| Quote: | Interessant ist 12.2p3 vor allem deshalb, weil der Punkt der
Zerstörung des temporären Objektes so genau definiert ist, und nicht,
wie ich praktisch seit meiner frühen Jugend dachte, bis z.B. zum Ende
des umschließenden Blocks hinausgezögert werden kann. Fatal wäre dies
u.U. für die Synchronisation, denn dann könnte das Programm
blockieren.
Ich habe die folgenden Fragen:
° Welche Probleme ergeben sich möglicherweise bei dem obigen Ansatz?
|
Du solltest dennoch verschachtelte Locks handhaben können. Das
nennt man dann glaube ich 'Monitor' (blockiert, wenn jemand
anders das Lock hat, nicht jedoch, wenn ich das Lock selber
habe). Beispiel:
char* funktion() {
cout << "bla";
return "blub";
}
// anderswo
cout << funktion();
Wenn hier das untere 'cout' vor 'funktion()' bewertet wird und
ein Temporary erstellt, welches das Lock besitzt, blockiert
'funktion'.
| Quote: | ° Welche Lösungen, die Ausgabe zu synchronisieren, verwendet ihr?
|
Ähnliche :-)
Ich bevorzuge etwas expliziteres, also
class lock {
std::ostream& os;
public:
lock(std::ostream& os) : os(os) { lock(); }
~lock() { unlock(); }
template
std::ostream& operator<<(const T& rhs) { return os << rhs; }
};
Allerdings hatte ich das Problem noch nicht sehr häufig.
Stefan
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Wed Nov 26, 2003 5:41 pm Post subject: Re: RAII fuer Ausdruecke |
|
|
Michael Trocken wrote:
| Quote: | Ich habe die folgenden Fragen:
° Welche Probleme ergeben sich möglicherweise bei dem obigen Ansatz?
|
Ich würde nur ein Problem sehen, wenn man das in Funktionen verwendet,
die evtl. schon mit einem gehaltenem lock aufgerufen werden
(operator<<() z.b.), das könnte man aber mit rekursiven locks lösen.
| Quote: | ° Welche Lösungen, die Ausgabe zu synchronisieren, verwendet ihr?
|
Ich würde für verschiedene threads verschiedene streams verwenden. Wenn
der Output schlußendlich aber im gleichen output landen soll würde ich
jedem dieser streams einen eigenen streambuffer mitgeben, der jeden
output zwischenspeichert, bis der stream geflushed wird. Bei flushen des
streambuffers kann man dann einen lock nehmen, der ein Umkopieren in den
Ziel streambuffer synchronisiert.
mfg Torsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Martin v. Löwis Guest
|
Posted: Wed Nov 26, 2003 9:15 pm Post subject: Re: RAII fuer Ausdruecke |
|
|
Michael Trocken wrote:
| Quote: | ° Welche Probleme ergeben sich möglicherweise bei dem obigen Ansatz?
|
Ich halte das für zu magisch, und zu fehleranfällig. Beispielsweise
funktioniert Dein Code nicht in folgenden Fällen:
std::cout << "Hallo" << endl;
cerr << "Hallo" << endl;
foo() << "Hallo" << endl;
Frei nach Tim Peters: Explicit is better than implicit.
lock(), cout<<"Hallo", endl;
oder
lock(cout) << "Hallo" << endl;
Ciao,
Martin
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|