[zypp-devel] Be carefull when using class ProgressData!
Unlike Report/Callback pairs (or not yet used Signal/Slots), ProgressData reports are not guarded against a vanishing reciever. A ProgressData object should have a limited lifetime. It should go out of scope as the task is completed. Preferably it is a variable local to some function. Not a class data member. https://bugzilla.novell.com/show_bug.cgi?id=299680 shows what happens if some ProgressData _ticks is a class data member: Set up to report progress during RepoImpl creation, it is not reset as the task has completed. Far later, as the RepoImpl goes out of scope, the ProgressData object sends it's final 'end of lifetime' report to a receiver that no longer exists. void task( ... ) { ProgressData ticks; // limited lifetime! } If you need to trigger the same ProgressData object within multiple functions, pass it per reference to the functions, ... .. or at least take care ProgressData is reset at the end of the task: #include "zypp/base/DtorReset.h" class RepoImpl { public: void task( ... ) { DtorReset x( _ticks, ProgressData() ); DtorReset y( _taskRunning, false ); _taskRunning = true; // _ticks = ProgressData( 10 ); // Expect range 0 -> 10 _tics.name( "test ticks" ); // Some arbitrary name _tics.sendTo( _fnc ); // Send reports to _fnc _ticks.toMin(); // start sending min (0) longrun(); _ticks.toMax(); } private: void longrun() { while ( ! done ) { ... if ( eror ) throw; ... _ticks.tick(); } } ProgressData _ticks; bool _taskRunning; }; - task initializes _ticks to be a 'new' ProgressData. - longrun is able to access _ticks - DtorReset takes care _ticks is reset at the end of task, even if an exception occurred. DtorReset: - DtorReset takes care _taskRunning is set to 'false' at the end of task, to show that DtorReset is templated, thus not limited to certain types (as long as they are copyable and assignable). DtorReset assigns back some value: DtorReset x( _flag, _flag ); // save and restore later _flag = 0; See also: class AutoDispose. Similar but calls some user defined cleanup function: { AutoDispose<int> fd( 0 ); fd = open( "/tmp/foo" ); if ( fd == -1 ) return; // or error report else fd.setDispose( ::close ); // HERE: fd is guarded. // The file will be closed when fd goes out of scope. // More precise: when fd and all copies obtained from fd // went out of scope. .. // explicit close: fd.resetDispose(); ::close( fd ); fd = -1; } -- cu, Michael Andres +------------------------------------------------------------------+ Key fingerprint = 2DFA 5D73 18B1 E7EF A862 27AC 3FB8 9E3A 27C6 B0E4 +------------------------------------------------------------------+ Michael Andres YaST Development ma@novell.com SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nuernberg) Maxfeldstrasse 5, D-90409 Nuernberg, Germany, ++49 (0)911 - 740 53-0 +------------------------------------------------------------------+ -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
participants (1)
-
Michael Andres