C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

RAII fuer Ausdruecke

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Michael Trocken
Guest





PostPosted: Wed Nov 26, 2003 7:43 am    Post subject: RAII fuer Ausdruecke Reply with quote



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





PostPosted: Wed Nov 26, 2003 4:36 pm    Post subject: Re: RAII fuer Ausdruecke Reply with quote



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





PostPosted: Wed Nov 26, 2003 5:41 pm    Post subject: Re: RAII fuer Ausdruecke Reply with quote



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





PostPosted: Wed Nov 26, 2003 9:15 pm    Post subject: Re: RAII fuer Ausdruecke Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.