diff --git a/include/ts/DbgCtl.h b/include/ts/DbgCtl.h index 1bd08988e9f..1aac8644614 100644 --- a/include/ts/DbgCtl.h +++ b/include/ts/DbgCtl.h @@ -38,7 +38,31 @@ class DbgCtl // DbgCtl(char const *tag) : _ptr{_new_reference(tag)} {} - ~DbgCtl() { _rm_reference(); } + // As instance with no tag will always be off. + // + DbgCtl() : _ptr{&_No_tag_dummy} {} + + ~DbgCtl() + { + if (_ptr != &_No_tag_dummy) { + _rm_reference(); + } + } + + // No copying. Only moving from a tagged to a tagless instance allowed. + // + DbgCtl(DbgCtl const &) = delete; + DbgCtl &operator=(DbgCtl const &) = delete; + DbgCtl(DbgCtl &&); + DbgCtl &operator=(DbgCtl &&); + + // A shorthand. + // + void + set(char const *tag) + { + *this = DbgCtl{tag}; + } bool tag_on() const @@ -90,14 +114,12 @@ class DbgCtl static void print(char const *tag, char const *file, char const *function, int line, char const *fmt_str, ...) TS_PRINTFLIKE(5, 6); - // No copying/moving. - DbgCtl(DbgCtl const &) = delete; - DbgCtl &operator=(DbgCtl const &) = delete; - private: using _TagData = std::pair; - _TagData const *const _ptr; + _TagData const *_ptr; + + static const _TagData _No_tag_dummy; static const _TagData *_new_reference(char const *tag); diff --git a/src/tscore/DbgCtl.cc b/src/tscore/DbgCtl.cc index 8ae652eb20b..0c5cad85fd6 100644 --- a/src/tscore/DbgCtl.cc +++ b/src/tscore/DbgCtl.cc @@ -30,6 +30,24 @@ #include #include +DbgCtl::DbgCtl(DbgCtl &&src) +{ + ink_release_assert(src._ptr != &_No_tag_dummy); + + _ptr = src._ptr; + src._ptr = &_No_tag_dummy; +} + +DbgCtl & +DbgCtl::operator=(DbgCtl &&src) +{ + ink_release_assert(&_No_tag_dummy == _ptr); + + new (this) DbgCtl{std::move(src)}; + + return *this; +} + // The resistry of fast debug controllers has a ugly implementation to handle the whole-program initialization // and destruction order problem with C++. // @@ -205,3 +223,5 @@ DbgCtl::_override_global_on() { return diags()->get_override(); } + +DbgCtl::_TagData const DbgCtl::_No_tag_dummy{nullptr, false};