C++ 宏定义打印日志

初始实现:

#define LOG_INFO(...) {\

fprintf(stderr, "%s :Line %d :\t", __FILE__, __LINE__);\

fprintf(stderr, __VA_ARGS__);\

fprintf(stderr, "\n");\

}

...

#define TEST_ON

#define TEST_LOG(...) {\
#ifdef TEST_ON\
std::this_thread::sleep_for(std::chrono::milliseconds(100)); \
LOG_INFO("Mytest", __VA_ARGS__); \
#endif \
}

在宏定义中直接使用 `std::this_thread::sleep_for` 是不好的做法,这会让整个线程暂停执行。

改成使用定时器或线程睡眠方式来控制延迟。

可以改成以下代码:

```c++
#include
#include

...

#define TEST_ON
#define TEST_LOG(...) {\
    if (TEST_ON) { \
        std::thread([](auto&&... args) { \
            std::this_thread::sleep_for(std::chrono::milliseconds(100)); \
            LOG_INFO("MyTest", std::forward(args)...); \
        }, __VA_ARGS__).detach(); \
    } \
}
#endif
```

这里使用了 `std::thread` 创建了一个新线程来进行延迟,并使用 `detach` 分离该线程,让其自行运行于后台,这样可以不阻塞当前线程。

注意:需要在使用 `__VA_ARGS__` 时加上宏定义中的 `std::forward(args)...` 语句,将可变参数转发给函数模板(`CAMX_LOG_INFO`)进行参数推导。

使用线程来延迟日志输出的做法可以避免当前线程暂停,但也会带来线程频繁创建与销毁的问题。这样的开销可能会对性能产生负面影响。

为了解决这个问题,可以考虑使用线程池来重用线程,减少创建和销毁线程的开销。线程池可以通过预先创建一定数量的线程,并维护一个任务队列来实现。当需要执行任务时,先将任务加入队列,然后由线程池内的线程来执行。

因此,可以将线程池的实现封装成一个类,然后在宏定义中使用该类来控制日志输出。这样可以避免线程创建与销毁的开销。

以下是使用线程池来实现的例子:

```c++
#include
#include
#include
#include
#include
#include

class ThreadPool {
public:
    explicit ThreadPool(size_t size) {
        for (size_t i = 0; i < size; ++i) {
            threads_.emplace_back([this] {
                while (true) {
                    std::unique_lock lock(mutex_);
                    cond_.wait(lock, [this]{ return !tasks_.empty() || stop_; });
                    if (stop_ && tasks_.empty()) {
                        return;
                    }
                    auto task = std::move(tasks_.front());
                    tasks_.pop();
                    lock.unlock();
                    task();
                }
            });
        }
    }

    ~ThreadPool() {
        {
            std::unique_lock lock(mutex_);
            stop_ = true;
        }
        cond_.notify_all();
        for (auto& thread : threads_) {
            thread.join();
        }
    }

    template
    void addTask(F&& task) {
        {
            std::unique_lock lock(mutex_);
            tasks_.emplace(std::forward(task));
        }
        cond_.notify_one();
    }

private:
    std::vector threads_;
    std::queue> tasks_;
    std::mutex mutex_;
    std::condition_variable cond_;
    bool stop_ = false;
};

static ThreadPool threadPool{4};

...

#define TEST_ON
#define TEST_LOG(...) {\
    if (TEST_ON) { \
        threadPool.addTask([=]{ \
            std::this_thread::sleep_for(std::chrono::milliseconds(100)); \
            LOG_INFO("MyTest", __VA_ARGS__); \
        }); \
    } \
}
```

这里使用了 `ThreadPool` 类来实现线程池的功能。该类在构造时会创建 `size` 个线程,并在析构时释放所有线程。该类提供了 `addTask` 方法以添加任务队列,并使用条件变量 `cond_` 唤醒空闲线程来执行任务。在宏定义中,使用线程池的 `ThreadPoo::addTask` 方法来将任务加入任务队列中。

以上编译报错,修改方案:

#define OPLUS_AON_TEST 1

if (OPLUS_AON_TEST == 1) { \

你可能感兴趣的:(c++,开发语言)