初始实现:
#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
}, __VA_ARGS__).detach(); \
} \
}
#endif
```
这里使用了 `std::thread` 创建了一个新线程来进行延迟,并使用 `detach` 分离该线程,让其自行运行于后台,这样可以不阻塞当前线程。
注意:需要在使用 `__VA_ARGS__` 时加上宏定义中的 `std::forward
使用线程来延迟日志输出的做法可以避免当前线程暂停,但也会带来线程频繁创建与销毁的问题。这样的开销可能会对性能产生负面影响。
为了解决这个问题,可以考虑使用线程池来重用线程,减少创建和销毁线程的开销。线程池可以通过预先创建一定数量的线程,并维护一个任务队列来实现。当需要执行任务时,先将任务加入队列,然后由线程池内的线程来执行。
因此,可以将线程池的实现封装成一个类,然后在宏定义中使用该类来控制日志输出。这样可以避免线程创建与销毁的开销。
以下是使用线程池来实现的例子:
```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
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
stop_ = true;
}
cond_.notify_all();
for (auto& thread : threads_) {
thread.join();
}
}
template
void addTask(F&& task) {
{
std::unique_lock
tasks_.emplace(std::forward
}
cond_.notify_one();
}
private:
std::vector
std::queue
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) { \