Refactor and Optimize a Multithreaded Logging System in C++
Improve the readability, maintainability, and performance of an existing multithreaded logging system while preserving its functionality.
Challenge prompt
You are given a multithreaded logging system implemented in C++. The current implementation works correctly but has poor code quality with redundant locking, duplicated code, inconsistent naming, and inefficient resource management. Refactor the given code to improve clarity, reduce locking overhead, and enhance performance while ensuring the system remains thread-safe and maintains the exact same logging behavior and output. Your refactoring should focus on: - Reducing lock contention and redundant synchronization. - Improving modularity and code reuse. - Using modern C++ features where appropriate for safety and clarity. - Avoiding data races or deadlocks. Do not change the public interface or the output format of logs. Provide the refactored C++ function(s)/class(es) that implement the logger.
Guidance
- • Identify sections of code that unnecessarily lock multiple times or hold locks for longer than needed.
- • Extract duplicated code into helper methods and improve naming consistency for clearer intent.
- • Consider using RAII wrappers like std::lock_guard or std::unique_lock to automatically manage mutexes.
Hints
- • Think about minimizing the critical section inside mutex locks to just the shared data modification.
- • Review how the log message queue is accessed and consider safer concurrent containers or condition variables.
- • Leverage C++11 smart pointers and move semantics to avoid unnecessary copying and enhance performance.
Starter code
#include <iostream>
#include <string>
#include <queue>
#include <mutex>
#include <thread>
#include <condition_variable>
class Logger {
private:
std::queue<std::string> logs;
std::mutex mtx;
std::condition_variable cv;
bool stop = false;
public:
void log(const std::string &message) {
mtx.lock();
logs.push(message);
mtx.unlock();
cv.notify_one();
}
void processLogs() {
while (true) {
mtx.lock();
if (!logs.empty()) {
std::string msg = logs.front();
logs.pop();
mtx.unlock();
std::cout << msg << std::endl;
} else if (stop) {
mtx.unlock();
break;
} else {
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
}
void shutdown() {
mtx.lock();
stop = true;
mtx.unlock();
cv.notify_all();
}
};Expected output
Logs should be printed in the order they were received with no data races or crashes. Logging should continue smoothly until shutdown is called.
Core concepts
Challenge a Friend
Send this duel to someone else and see if they can solve it.