From: Mikko Rasa Date: Tue, 27 Aug 2024 11:51:51 +0000 (+0300) Subject: Use unique_ptr to manage owned memory X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=f53d7424937130136a138cc00c43c1f73f6233a7;p=libs%2Fcore.git Use unique_ptr to manage owned memory Required C++ language version is now C++14. --- diff --git a/Build b/Build index a2a3040..3d97b2c 100644 --- a/Build +++ b/Build @@ -7,7 +7,7 @@ package "mspcore" build_info { threads true; - standard CXX "c++11"; + standard CXX "c++14"; }; if_arch "linux" { diff --git a/source/core/application.cpp b/source/core/application.cpp index c214a06..5b0fabd 100644 --- a/source/core/application.cpp +++ b/source/core/application.cpp @@ -16,7 +16,7 @@ using namespace std; namespace Msp { -Application *Application::_app = nullptr; +unique_ptr Application::_app; Application::Starter *Application::_starter = nullptr; const char *Application::_argv0 = nullptr; string Application::_name; @@ -59,9 +59,7 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback) created_callback(data); int result = _app->main(); - Application *a = _app; - _app = nullptr; - delete a; + unique_ptr a = move(_app); return result; } catch(const exception &e) @@ -85,7 +83,6 @@ int Application::run(int argc, char **argv, void *data, void (*created_callback) } } - delete _app; _app = nullptr; return 124; diff --git a/source/core/application.h b/source/core/application.h index d5a571a..d45a576 100644 --- a/source/core/application.h +++ b/source/core/application.h @@ -1,6 +1,7 @@ #ifndef MSP_CORE_APPLICATION_H_ #define MSP_CORE_APPLICATION_H_ +#include #include #include #include "mspcore_api.h" @@ -21,7 +22,7 @@ protected: public: virtual ~Starter() = default; - virtual Application *create_app(int, char **) = 0; + virtual std::unique_ptr create_app(int, char **) = 0; }; bool done = false; @@ -29,7 +30,7 @@ protected: private: static Starter *_starter; - static Application *_app; + static std::unique_ptr _app; static const char *_argv0; static std::string _name; static void *_data; @@ -92,7 +93,7 @@ private: class Starter: public Application::Starter { public: - Application *create_app(int argc, char **argv) { return new T(argc, argv); } + std::unique_ptr create_app(int argc, char **argv) { return std::make_unique(argc, argv); } }; static Starter _starter; diff --git a/source/core/getopt.cpp b/source/core/getopt.cpp index cbc0afb..31e5dc4 100644 --- a/source/core/getopt.cpp +++ b/source/core/getopt.cpp @@ -11,14 +11,6 @@ GetOpt::GetOpt() add_option("help", help, NO_ARG).set_help("Displays this help"); } -GetOpt::~GetOpt() -{ - for(OptionImpl *i: opts) - delete i; - for(ArgumentImpl *i: args) - delete i; -} - GetOpt::OptionImpl &GetOpt::add_option(char s, const string &l, const Store &t, ArgType a) { if(l.empty()) @@ -29,15 +21,12 @@ GetOpt::OptionImpl &GetOpt::add_option(char s, const string &l, const Store &t, for(auto i=opts.begin(); i!=opts.end(); ) { if((s!=0 && (*i)->get_short()==s) || (*i)->get_long()==l) - { - delete *i; i = opts.erase(i); - } else ++i; } - opts.push_back(new OptionImpl(s, l, t, a)); + opts.push_back(make_unique(s, l, t, a)); return *opts.back(); } @@ -48,7 +37,7 @@ GetOpt::ArgumentImpl &GetOpt::add_argument(const string &n, const Store &t, ArgT bool have_list = false; bool have_optional = false; - for(const ArgumentImpl *a: args) + for(const unique_ptr &a: args) { if(a->is_list_store()) have_list = true; @@ -61,13 +50,13 @@ GetOpt::ArgumentImpl &GetOpt::add_argument(const string &n, const Store &t, ArgT if(have_list && (t.is_list() || y==OPTIONAL_ARG)) throw invalid_argument("GetOpt::add_argument"); - args.push_back(new ArgumentImpl(n, t, y)); + args.push_back(make_unique(n, t, y)); return *args.back(); } GetOpt::OptionImpl &GetOpt::get_option(char s) { - auto i = find_if(opts, [s](const OptionImpl *o){ return o->get_short()==s; }); + auto i = find_if(opts, [s](const unique_ptr &o){ return o->get_short()==s; }); if(i!=opts.end()) return **i; throw usage_error(string("Unknown option -")+s); @@ -75,7 +64,7 @@ GetOpt::OptionImpl &GetOpt::get_option(char s) GetOpt::OptionImpl &GetOpt::get_option(const string &l) { - auto i = find_if(opts, [&l](const OptionImpl *o){ return o->get_long()==l; }); + auto i = find_if(opts, [&l](const unique_ptr &o){ return o->get_long()==l; }); if(i!=opts.end()) return **i; throw usage_error(string("Unknown option --")+l); @@ -213,7 +202,7 @@ string GetOpt::generate_usage(const string &argv0, bool compact) const result += " [options]"; else { - for(const OptionImpl *o: opts) + for(const unique_ptr &o: opts) { result += " ["; if(o->get_short()) @@ -239,7 +228,7 @@ string GetOpt::generate_usage(const string &argv0, bool compact) const } } - for(const ArgumentImpl *a: args) + for(const unique_ptr &a: args) { result += ' '; if(a->get_type()==OPTIONAL_ARG) @@ -256,11 +245,11 @@ string GetOpt::generate_usage(const string &argv0, bool compact) const string GetOpt::generate_help() const { - bool any_short = any_of(opts.begin(), opts.end(), [](const OptionImpl *o){ return o->get_short(); }); + bool any_short = any_of(opts.begin(), opts.end(), [](const unique_ptr &o){ return o->get_short(); }); string::size_type maxw = 0; vector switches; - for(const OptionImpl *o: opts) + for(const unique_ptr &o: opts) { string swtch; if(o->get_short()) @@ -289,7 +278,7 @@ string GetOpt::generate_help() const } vector pargs; - for(const ArgumentImpl *a: args) + for(const unique_ptr &a: args) { string parg = format("<%s>", a->get_name()); pargs.push_back(parg); @@ -320,11 +309,6 @@ GetOpt::OptionImpl::OptionImpl(char s, const string &l, const Store &t, ArgType store(t.clone()) { } -GetOpt::OptionImpl::~OptionImpl() -{ - delete store; -} - GetOpt::OptionImpl &GetOpt::OptionImpl::set_help(const string &h) { help = h; @@ -389,11 +373,6 @@ GetOpt::ArgumentImpl::ArgumentImpl(const string &n, const Store &t, ArgType a): store(t.clone()) { } -GetOpt::ArgumentImpl::~ArgumentImpl() -{ - delete store; -} - GetOpt::ArgumentImpl &GetOpt::ArgumentImpl::set_help(const string &h) { help = h; diff --git a/source/core/getopt.h b/source/core/getopt.h index 59c810c..d8d5bb1 100644 --- a/source/core/getopt.h +++ b/source/core/getopt.h @@ -2,6 +2,7 @@ #define MSP_CORE_GETOPT_H_ #include +#include #include #include #include @@ -107,7 +108,7 @@ private: public: virtual ~Store() = default; - virtual Store *clone() const = 0; + virtual std::unique_ptr clone() const = 0; virtual bool is_list() const = 0; virtual void store() = 0; @@ -124,11 +125,10 @@ private: unsigned *ext_seen_count = nullptr; std::string help; std::string metavar = "ARG"; - Store *store = nullptr; + std::unique_ptr store; public: OptionImpl(char, const std::string &, const Store &, ArgType); - ~OptionImpl() override; OptionImpl &set_help(const std::string &) override; OptionImpl &set_help(const std::string &, const std::string &) override; @@ -149,11 +149,10 @@ private: std::string name; ArgType type = REQUIRED_ARG; std::string help; - Store *store = nullptr; + std::unique_ptr store; public: ArgumentImpl(const std::string &, const Store &, ArgType); - ~ArgumentImpl() override; ArgumentImpl &set_help(const std::string &) override; const std::string &get_name() const { return name; } @@ -172,8 +171,7 @@ private: public: SimpleStore(T &d): data(d) { } - SimpleStore *clone() const override - { return new SimpleStore(data); } + std::unique_ptr clone() const override { return std::make_unique(data); } bool is_list() const override { return false; } @@ -192,8 +190,7 @@ private: public: ListStore(T &d): data(d) { } - ListStore *clone() const override - { return new ListStore(data); } + std::unique_ptr clone() const override { return std::make_unique(data); } bool is_list() const override { return true; } @@ -204,13 +201,12 @@ private: }; bool help = false; - std::vector opts; - std::vector args; + std::vector> opts; + std::vector> args; std::vector args_raw; public: GetOpt(); - ~GetOpt(); /** Adds an option with both short and long forms. Processing depends on the type of the destination variable and whether an argument is taken or diff --git a/source/core/process.cpp b/source/core/process.cpp index 4c5ed46..95a5639 100644 --- a/source/core/process.cpp +++ b/source/core/process.cpp @@ -7,7 +7,7 @@ using namespace std; namespace Msp { -Process *Process::_self = nullptr; +unique_ptr Process::_self; Process::Process(const Private &p): priv(new Private(p)) @@ -23,7 +23,7 @@ Process &Process::self() { Private _priv; platform_get_self_info(_priv); - _self = new Process(_priv); + _self = unique_ptr(new Process(_priv)); } return *_self; } @@ -50,7 +50,7 @@ void Process::redirect_cerr(IO::Base &io) void Process::do_redirect(IO::Base *&ptr, IO::Base &io) { - if(this==_self) + if(this==_self.get()) { if(&ptr==&cin) IO::cin.redirect(io); diff --git a/source/core/process.h b/source/core/process.h index ed997f8..9913630 100644 --- a/source/core/process.h +++ b/source/core/process.h @@ -1,6 +1,7 @@ #ifndef MSP_CORE_PROCESS_H_ #define MSP_CORE_PROCESS_H_ +#include #include #include #include @@ -41,7 +42,7 @@ private: bool finished = false; unsigned exit_code = 0; - static Process *_self; + static std::unique_ptr _self; Process(const Private &); public: diff --git a/source/core/typeregistry.h b/source/core/typeregistry.h index 193fe07..84e8943 100644 --- a/source/core/typeregistry.h +++ b/source/core/typeregistry.h @@ -2,6 +2,7 @@ #define MSP_CORE_TYPEREGISTRY_H_ #include +#include #include #include "maputils.h" #include "noncopyable.h" @@ -43,11 +44,9 @@ private: void invoke(T arg) const override { action(this->keyword, arg); } }; - std::map types; + std::map> types; public: - ~TypeRegistry(); - /** Registers a type. */ template void register_type(const std::string &); @@ -60,13 +59,6 @@ public: void invoke_all(T) const; }; -template class A, typename T> -TypeRegistry::~TypeRegistry() -{ - for(auto &kvp: types) - delete kvp.second; -} - template class A, typename T> template void TypeRegistry::register_type(const std::string &kw) @@ -74,7 +66,7 @@ void TypeRegistry::register_type(const std::string &kw) if(types.count(kw)) throw key_error(kw); - types[kw] = new RegisteredType(kw); + types[kw] = std::make_unique>(kw); } template class A, typename T> diff --git a/source/core/unix/process.cpp b/source/core/unix/process.cpp index ee0a36d..78f64a3 100644 --- a/source/core/unix/process.cpp +++ b/source/core/unix/process.cpp @@ -25,7 +25,7 @@ void Process::platform_get_self_info(Private &priv) void Process::execute(const string &command, bool path_search, const Arguments &args) { pid_t pid = 0; - if(this!=_self) + if(this!=_self.get()) pid = fork(); if(pid==-1) diff --git a/source/core/windows/process.cpp b/source/core/windows/process.cpp index 0eae33b..ba6d0f9 100644 --- a/source/core/windows/process.cpp +++ b/source/core/windows/process.cpp @@ -94,7 +94,7 @@ void Process::execute(const string &command, bool path_search, const Arguments & running = true; - if(this==_self) + if(this==_self.get()) TerminateProcess(priv->info.hProcess, 0); } diff --git a/source/io/base.cpp b/source/io/base.cpp index bf23ea2..d94cfee 100644 --- a/source/io/base.cpp +++ b/source/io/base.cpp @@ -12,7 +12,6 @@ Base::Base() Base::~Base() { signal_deleted.emit(); - delete mutex; } void Base::check_access(Mode m) const @@ -68,7 +67,7 @@ Base::Synchronize::Synchronize(Base &i): io(i) { if(!io.mutex) - io.mutex = new Mutex; + io.mutex = make_unique(); io.mutex->lock(); } diff --git a/source/io/base.h b/source/io/base.h index 92c860d..18353a3 100644 --- a/source/io/base.h +++ b/source/io/base.h @@ -2,6 +2,7 @@ #define MSP_IO_BASE_H_ #include +#include #include #include #include @@ -45,7 +46,7 @@ public: protected: Mode mode = M_READ; bool eof_flag = false; - Mutex *mutex = nullptr; + std::unique_ptr mutex; Base(); public: diff --git a/source/io/generic/asset.cpp b/source/io/generic/asset.cpp index b5cad9a..a736d18 100644 --- a/source/io/generic/asset.cpp +++ b/source/io/generic/asset.cpp @@ -9,22 +9,21 @@ namespace IO { struct Asset::Private { - Seekable *file; + unique_ptr file; }; Asset::Asset(const string &name) { - Seekable *file = new BufferedFile((FS::get_sys_data_dir()/name).str()); + unique_ptr file = make_unique((FS::get_sys_data_dir()/name).str()); priv = new Private; - priv->file = file; + priv->file = move(file); priv->file->signal_flush_required.connect(signal_flush_required); } Asset::~Asset() { - delete priv->file; delete priv; } diff --git a/source/stringcodec/codec.cpp b/source/stringcodec/codec.cpp index ff2bd63..6513848 100644 --- a/source/stringcodec/codec.cpp +++ b/source/stringcodec/codec.cpp @@ -17,14 +17,12 @@ namespace StringCodec { bool Codec::detect(const string &str) const { - Decoder *dec = create_decoder(IGNORE_ERRORS); + unique_ptr dec = create_decoder(IGNORE_ERRORS); bool result = true; for(auto i=str.begin(); (result && i!=str.end()); ) result = (dec->decode_char(str, i)!=-1); - delete dec; - return result; } @@ -61,7 +59,7 @@ ustring Codec::Decoder::decode(const string &str) return buf; } -Codec *create_codec(const string &n) +unique_ptr create_codec(const string &n) { string name; string::const_iterator i; @@ -89,22 +87,22 @@ Codec *create_codec(const string &n) throw invalid_argument("StringCodec::create_codec"); } - if(name=="ascii") return new Ascii(em); - if(name=="iso2022jp") return new Iso2022Jp(em); - if(name=="iso646fi") return new Iso646Fi(em); - if(name=="iso88591" || name=="latin1") return new Iso88591(em); - if(name=="iso885915" || name=="latin9") return new Iso885915(em); - if(name=="jisx0201") return new JisX0201(em); - if(name=="jisx0208") return new JisX0208(em); - if(name=="utf8") return new Utf8(em); - if(name=="utf16") return new Utf16(em, Utf16::AUTO); - if(name=="utf16be") return new Utf16(em, Utf16::BIG); - if(name=="utf16le") return new Utf16(em, Utf16::LITTLE); - if(name=="windows1252" || name=="cp1252") return new Windows1252(em); + if(name=="ascii") return make_unique(em); + if(name=="iso2022jp") return make_unique(em); + if(name=="iso646fi") return make_unique(em); + if(name=="iso88591" || name=="latin1") return make_unique(em); + if(name=="iso885915" || name=="latin9") return make_unique(em); + if(name=="jisx0201") return make_unique(em); + if(name=="jisx0208") return make_unique(em); + if(name=="utf8") return make_unique(em); + if(name=="utf16") return make_unique(em, Utf16::AUTO); + if(name=="utf16be") return make_unique(em, Utf16::BIG); + if(name=="utf16le") return make_unique(em, Utf16::LITTLE); + if(name=="windows1252" || name=="cp1252") return make_unique(em); throw invalid_argument("StringCodec::create_codec"); } -Codec *detect_codec(const string &str) +unique_ptr detect_codec(const string &str) { bool is_utf8 = true; bool is_ascii = true; @@ -146,13 +144,13 @@ Codec *detect_codec(const string &str) } if(is_ascii) - return new Ascii; + return make_unique(); else if(is_utf8) - return new Utf8; + return make_unique(); else if(is_latin1) - return new Iso88591; + return make_unique(); else - return new Windows1252; + return make_unique(); } } // namespace StringCodec diff --git a/source/stringcodec/codec.h b/source/stringcodec/codec.h index f53bae5..ec46480 100644 --- a/source/stringcodec/codec.h +++ b/source/stringcodec/codec.h @@ -1,6 +1,7 @@ #ifndef MSP_STRINGCODEC_CODEC_H_ #define MSP_STRINGCODEC_CODEC_H_ +#include #include #include #include "except.h" @@ -140,10 +141,10 @@ public: virtual const char *get_name() const = 0; /** Creates an encoder for this codec. */ - virtual Encoder *create_encoder(ErrorMode err_mode = DEFAULT) const = 0; + virtual std::unique_ptr create_encoder(ErrorMode err_mode = DEFAULT) const = 0; /** Creates a decoder for this codec. */ - virtual Decoder *create_decoder(ErrorMode err_mode = DEFAULT) const = 0; + virtual std::unique_ptr create_decoder(ErrorMode err_mode = DEFAULT) const = 0; /** Determines whether the given string can be successfully decoded with this codec. Note that this function returning true does not guarantee that @@ -172,11 +173,11 @@ protected: { return (em==DEFAULT ? err_mode : em); } public: - Encoder *create_encoder(ErrorMode em = DEFAULT) const override - { return new typename C::Encoder(get_error_mode(em)); } + std::unique_ptr create_encoder(ErrorMode em = DEFAULT) const override + { return std::make_unique(get_error_mode(em)); } - Decoder *create_decoder(ErrorMode em = DEFAULT) const override - { return new typename C::Decoder(get_error_mode(em)); } + std::unique_ptr create_decoder(ErrorMode em = DEFAULT) const override + { return std::make_unique(get_error_mode(em)); } }; @@ -203,13 +204,11 @@ std::string transcode(const std::string &s) return encode(decode(s)); } -/** Creates a codec for an encoding by name. The caller is responsible for -deleting the codec when it's no longer needed. */ -MSPCORE_API Codec *create_codec(const std::string &); +/** Creates a codec for an encoding by name. */ +MSPCORE_API std::unique_ptr create_codec(const std::string &); -/** Automatically detects the encoding of a string and creates a codec for it. -The codec must be deleted when it's no longer needed. */ -MSPCORE_API Codec *detect_codec(const std::string &); +/** Automatically detects the encoding of a string and creates a codec for it. */ +MSPCORE_API std::unique_ptr detect_codec(const std::string &); } // namespace StringCodec } // namespace Msp diff --git a/source/stringcodec/iso2022jp.cpp b/source/stringcodec/iso2022jp.cpp index 93c50f4..f262c74 100644 --- a/source/stringcodec/iso2022jp.cpp +++ b/source/stringcodec/iso2022jp.cpp @@ -81,7 +81,7 @@ void Iso2022Jp::Encoder::transliterate(unichar, string &buf) Iso2022Jp::Decoder::Decoder(ErrorMode em): Codec::Decoder(em), - dec(new Ascii::Decoder) + dec(make_unique()) { } unichar Iso2022Jp::Decoder::decode_char(const string &str, string::const_iterator &i) @@ -134,21 +134,18 @@ unichar Iso2022Jp::Decoder::decode_char(const string &str, string::const_iterato void Iso2022Jp::Decoder::reset() { - delete dec; mode = ASCII; - dec = new Ascii::Decoder; + dec = make_unique(); } void Iso2022Jp::Decoder::switch_mode(Mode m) { - delete dec; - mode = m; switch(mode) { - case ASCII: dec = new Ascii::Decoder; break; - case JISX0201: dec = new JisX0201::Decoder; break; - case JISX0208: dec = new JisX0208::Decoder; break; + case ASCII: dec = make_unique(); break; + case JISX0201: dec = make_unique(); break; + case JISX0208: dec = make_unique(); break; } } diff --git a/source/stringcodec/iso2022jp.h b/source/stringcodec/iso2022jp.h index 0bb1ad3..488f2ee 100644 --- a/source/stringcodec/iso2022jp.h +++ b/source/stringcodec/iso2022jp.h @@ -37,7 +37,7 @@ public: { private: Mode mode = ASCII; - Codec::Decoder *dec = nullptr; + std::unique_ptr dec; public: Decoder(ErrorMode = DEFAULT); diff --git a/source/stringcodec/utf16.h b/source/stringcodec/utf16.h index a588b12..0ed52b2 100644 --- a/source/stringcodec/utf16.h +++ b/source/stringcodec/utf16.h @@ -61,11 +61,11 @@ public: const char *get_name() const override { return endian==BIG ? "UTF-16-BE" : endian==LITTLE ? "UTF-16-LE" : "UTF-16"; } - Encoder *create_encoder(ErrorMode em = DEFAULT) const override - { return new Encoder(get_error_mode(em), endian); } + std::unique_ptr create_encoder(ErrorMode em = DEFAULT) const override + { return std::make_unique(get_error_mode(em), endian); } - Decoder *create_decoder(ErrorMode em = DEFAULT) const override - { return new Decoder(get_error_mode(em), endian); } + std::unique_ptr create_decoder(ErrorMode em = DEFAULT) const override + { return std::make_unique(get_error_mode(em), endian); } }; diff --git a/source/time/timer.cpp b/source/time/timer.cpp index eda782e..d3b96d9 100644 --- a/source/time/timer.cpp +++ b/source/time/timer.cpp @@ -12,41 +12,36 @@ Timer::Timer(): sem(1) { } -Timer::~Timer() -{ - for(const SlotProxy &s: slots) - delete s.slot; -} - Timer::Slot &Timer::add(const TimeDelta &td) { - Slot *s = new Slot(td); + unique_ptr s = make_unique(td); + Slot &sref = *s; MutexLock l(mutex); - slots.push_back({ s }); + slots.push_back({ move(s) }); push_heap(slots.begin(), slots.end()); if(blocking) sem.signal(); - return *s; + return sref; } Timer::Slot &Timer::add(const TimeStamp &ts) { - Slot *s = new Slot(ts); + unique_ptr s = make_unique(ts); + Slot &sref = *s; MutexLock l(mutex); - slots.push_back({ s }); + slots.push_back({ move(s) }); push_heap(slots.begin(), slots.end()); if(blocking) sem.signal(); - return *s; + return sref; } void Timer::cancel(Slot &slot) { MutexLock l(mutex); - auto i = find_member(slots, &slot, &SlotProxy::slot); + auto i = find_if(slots, [&slot](const SlotProxy &p){ return p.slot.get()==&slot; }); if(i!=slots.end()) { - delete i->slot; slots.erase(i); make_heap(slots.begin(), slots.end()); } @@ -71,7 +66,7 @@ void Timer::do_tick(const TimeDelta &timeout) if(timeout>=zero) deadline = now()+timeout; - Slot *next = nullptr; + unique_ptr next; { MutexLock l(mutex); while(1) @@ -80,8 +75,7 @@ void Timer::do_tick(const TimeDelta &timeout) TimeStamp t = now(); if(!slots.empty()) { - next = slots.begin()->slot; - stamp = next->get_timeout(); + stamp = slots.front().slot->get_timeout(); if(stamp<=t) break; } @@ -104,25 +98,16 @@ void Timer::do_tick(const TimeDelta &timeout) return; } + next = move(slots.front().slot); pop_heap(slots.begin(), slots.end()); slots.pop_back(); } - try - { - if(next->signal_timeout.emit() && next->increment()) - { - MutexLock l(mutex); - slots.push_back({ next }); - push_heap(slots.begin(), slots.end()); - } - else - delete next; - } - catch(...) + if(next->signal_timeout.emit() && next->increment()) { - delete next; - throw; + MutexLock l(mutex); + slots.push_back({ move(next) }); + push_heap(slots.begin(), slots.end()); } } diff --git a/source/time/timer.h b/source/time/timer.h index 7cb5c76..79b01db 100644 --- a/source/time/timer.h +++ b/source/time/timer.h @@ -1,6 +1,7 @@ #ifndef MSP_TIME_TIMER_H_ #define MSP_TIME_TIMER_H_ +#include #include #include #include @@ -42,7 +43,7 @@ public: private: struct SlotProxy { - Slot *slot; + std::unique_ptr slot; bool operator<(const SlotProxy &) const; }; @@ -54,7 +55,6 @@ private: public: Timer(); - ~Timer(); /** Adds a timer that will be executed periodically as long as the timeout signal hander returns true. */