Finally in ATL?



  • Sowas gibt es in ISO-C++ nicht. Eigentlich ist es auch nicht notwendig und wichtig. Platziere den Code hinter den catch-Block, dann wird es auch immer ausgeführt oder, wie oben gesagt, pack den Code in einen Destruktor, der dank Stack-Unwinding aufgerufen wird. Wenn du nur für Windows programmierst, ist der VS-spezifische __try/__finally-Block für dich evtl. interessant.

    http://msdn.microsoft.com/en-us/library/yb3kz605(VS.80).aspx



  • Du könntest Microsofts C/C++-Extensions __try, __except und __finally nutzen, aber diese Fehlerbehandlung kannst du nicht mit try/catch mischen (zumindest nicht innerhalb einer Funktion). Außerdem kriege ich nur wieder einen auf den Deckel, wenn ich hier mit Sachen komme, die nicht hundertprozentig C++ sind... 😃



  • Ad aCTa schrieb:

    Eigentlich ist es auch nicht notwendig und wichtig. Platziere den Code hinter den catch-Block, dann wird es auch immer ausgeführt

    Das sehe ich nicht so. Natürlich geht es auch irgendwie anders, aber Exceptions sind ja gerade dazu da, daß man den Code zur Fehlerbehandlung klar strukturiert und übersichtlich schreiben kann.
    Dein Vorschlag mit "hinter den catch-Block" macht nicht wirklich das selbe, z.B. wenn der catch-Block returned oder selbst wieder eine Exception wirft. Und genau um solche Fälle geht es ja bei finally.

    Statements zum Umgang mit Exceptions kann man gar nicht genug haben, ich persönlich bin ja ein großer Fan von Python's try/except/else/finally 🙂



  • wie drakon bereits gesagt hat, kann man Destruktoren benutzen, um so etwas wie finally hinzubekommen. Im Grunde ist finally eh nur ein Workaround für fehlendes RAII, oder andersrum gesagt: wo du andernorts finally benutzen musst, kannst/solltest du in C++ RAII nutzen.



  • ok dann mal konkreter:

    So mach ich es bisher:

    try
    {
    ::EnterCriticalSection(&m_csControllerMessgage);
    //Codeblock
    }
    catch(...)
    {
    //bla bla
    }
    ::LeaveCriticalSection(&m_csControllerMessgage);

    In C# bin ich es eben gewohnt, solch ein Konstrukt mit finally abzuschließen.
    Das obige Beispiel sieht irgendwie unschön aus.

    Wie macht man sowas dann in C++?
    Gruß
    camelord



  • wie würdest du das denn mit finally machen, bzw. welchen Teil würdest du in den finally-Block verschieben? UND: welcher Teil kann eine Exception werfen, der Codeblock oder ::EnterCriticalSection()?
    Dein Konstrukt sieht nicht wegen dem fehlenden finally unschön aus, sondern wegen dem vorhandenen try/catch, das offenbar nicht auf den kleinstmöglichen Bereich reduziert wurde.



  • Mal am Beispiel von MFC-Klassen beschrieben (ich benutze die hauptsächlich):
    In diesem Falle kann man z.B. CSingleLock benutzen, dem Ctor das Sync-Object (m_csControllerMessage) übergeben und InitalLock auf TRUE setzen.

    CCriticalSection m_csControllerMessage;
    ...
    void CClass::MyFunc()
    {
        CSingleLock lock(&m_csControllerMessage, TRUE);
        // tu was...
    }// hier "automatisch" unlock
    

    Das ware ein Beispiel für RAII.

    EDIT: Da war jemand schneller... 🙂



  • So fänd ichs prima:

    try {
    ::EnterCriticalSection(&m_csResultStateMessgage);
    try {
    //Code
    }
    finally {
    ::LeaveCriticalSection(&m_csResultStateMessgage);
    }
    }
    catch(...){
    //bla blubb
    }

    get aber net..



  • camelord@gmx.de schrieb:

    So fänd ichs prima:

    try {		
         ::EnterCriticalSection(&m_csResultStateMessgage);
         try {
               //Code
    	 }
         finally {
    	        ::LeaveCriticalSection(&m_csResultStateMessgage);
    	     }
        }
    catch(...){
                //bla blubb
              }
    

    get aber net..

    Mal abgesehn von der grausamen Klammersetzung die du durch die fehlenden cpp-Tags versteckt hast:

    class CriticalSectionWrapper
    {
      CCriticalSection& cs; //evtl. const, wenn möglich, Typ auch entsprechend Anpassen
    public:
      CriticalSectionWrapper(CCriticalSection& cs_) //hier auch  
      : cs(cs_)
      {
        ::EnterCriticalSection(&cs);
      }
      ~CriticalSectionWrapper()
      {
        ::LeaveCriticalSection(&cs);
      } 
    };
    
    //.....
    
    try 
    {		
      CriticalSectionWrapper(m_csResultStateMessgage);
      //Code
    }
    catch(...)
    {
      //bla blubb
    }
    

    Wenn //Code eine exception wirft wird der CriticalSectionWrapper beim Verlassendes try-Blocks zerstört und damit per DTor die Critical section wieder verlassen. Ganz klassischer Fall von RAII. Wenn du wie von R3dNeXX vorausgesetzt tatsächlich die MFC verwendest schau dir mal das von ihm genannte CSingleLock an.



  • Vielen dank..
    Ich habe nach dem Hinweis von R3dNeXX sowas für ATL gefunden.
    Kann ich das auch so schreiben:

    CComAutoCriticalSection m_csResultStateMessage;
    ...
    void CClass::MyFunc()
    {
         try
         {       
              CComCritSecLock<CComAutoCriticalSection> lock(myCriticalSectionObject, true);
              //Code
         }
         catch(...)
         {
              //bla blubb
         }        
    }
    


  • camelord@gmx.de schrieb:

    Kann ich das auch so schreiben:

    Klar, zumindest wenn die Lock-Klasse nicht irgendeinen unerwarteten Nebeneffekt hat. Ansonsten ist das doch das Selbe wie in meinem Beispiel (mal abgesehn dass die Lock-Klasse ne andere ist)



  • Na dann nimm ich lieber dein Beispiel. C++ trau ich noch nicht so ganz 😉

    Vielen dank für die flotte Hilfe!

    Schönen Tag noch..


Anmelden zum Antworten