Boost C++ Libraries

PrevUpHomeNext

Why scoped attributes don't override existing attributes?

Initially scoped attributes were able to override other attributes with the same name if they were already registered by the time when a scoped attribute encountered. This allowed some interesting use cases like this:

BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)

void foo()
{
    // This scoped attribute would temporarily replace the existing tag
    BOOST_LOG_SCOPED_THREAD_TAG("Section", std::string, "In foo");

    // This log record will have a "Section" attribute with value "In foo"
    BOOST_LOG(get_my_logger()) << "We're in foo section";
}

int main(int, char*[])
{
    BOOST_LOG_SCOPED_THREAD_TAG("Section", std::string, "In main");

    // This log record will have a "Section" attribute with value "In main"
    BOOST_LOG(get_my_logger()) << "We're in main section";

    foo();

    // This log record will have a "Section" attribute with value "In main" again
    BOOST_LOG(get_my_logger()) << "We're in main section again";

    return 0;
}

However, this feature introduced a number of safety problems, including thread safety issues, that could be difficult to track down. For example, it was no longer safe to use logger-wide scoped attributes on the same logger from different threads, because the resulting attribute would be undefined:

BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)

void thread1()
{
    BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", std::string, "thread1");
    BOOST_LOG(get_my_logger()) << "We're in thread1";
}

void thread2()
{
    BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", int, 10);
    BOOST_LOG(get_my_logger()) << "We're in thread2";
}

int main(int, char*[])
{
    BOOST_LOG_SCOPED_LOGGER_TAG(get_my_logger(), "Tag", double, -2.2);

    BOOST_LOG(get_my_logger()) << "We're in main";

    boost::thread t1(&thread1);
    boost::thread t2(&thread2);

    t1.join();
    t2.join();

    // Which "Tag" is registered here?
    BOOST_LOG(get_my_logger()) << "We're in main again";

    return 0;
}

There were other issues, like having an attribute set iterator that points to one attribute object, then suddenly without seemingly modifying it it becomes pointing to a different attribute object (of, possibly, a different type). Such behavior could lead to tricky failures that would be difficult to investigate. Therefore this feature was eventually dropped, which simplified the scoped attributes implementation significantly.


PrevUpHomeNext