Created
June 3, 2024 00:46
-
-
Save potat-dev/407227e2383e8a9135759c3d610b60c0 to your computer and use it in GitHub Desktop.
super simple thread safe console implementation C++ using mutex and queue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// thread_safe_iostream.hpp | |
#ifndef THREAD_SAFE_CONSOLE_HPP | |
#define THREAD_SAFE_CONSOLE_HPP | |
#include <iostream> | |
#include <queue> | |
#include <mutex> | |
#include <sstream> | |
#include <thread> | |
class ThreadSafeConsole { | |
public: | |
// Get the singleton instance | |
static ThreadSafeConsole& getInstance() { | |
static ThreadSafeConsole instance; | |
return instance; | |
} | |
// Delete copy constructor and assignment operator | |
ThreadSafeConsole(const ThreadSafeConsole&) = delete; | |
ThreadSafeConsole& operator=(const ThreadSafeConsole&) = delete; | |
// Method for thread-safe output | |
void print(const std::string &message) { | |
std::unique_lock<std::mutex> lock(mutex_); | |
if (isReading) { | |
messageQueue.push(message); | |
} else { | |
std::cout << message; | |
} | |
} | |
// Method for thread-safe input | |
void read(std::string &input) { | |
std::unique_lock<std::mutex> lock(mutex_); | |
isReading = true; | |
lock.unlock(); | |
// Read data from console | |
std::getline(std::cin, input); | |
lock.lock(); | |
isReading = false; | |
// Print queued messages | |
while (!messageQueue.empty()) { | |
std::cout << messageQueue.front(); | |
messageQueue.pop(); | |
} | |
} | |
private: | |
// Private constructor | |
ThreadSafeConsole() : isReading(false) {} | |
std::mutex mutex_; // Mutex for synchronizing access to the console | |
std::queue<std::string> messageQueue; // Queue for deferred messages | |
bool isReading; // Flag to check if reading input | |
}; | |
class ThreadSafeOStream { | |
public: | |
ThreadSafeOStream() : console_(ThreadSafeConsole::getInstance()) {} | |
// Overload the << operator | |
template<typename T> | |
ThreadSafeOStream &operator<<(const T &value) { | |
std::ostringstream oss; | |
oss << value; | |
console_.print(oss.str()); | |
return *this; | |
} | |
private: | |
ThreadSafeConsole &console_; | |
}; | |
class ThreadSafeIStream { | |
public: | |
ThreadSafeIStream() : console_(ThreadSafeConsole::getInstance()) {} | |
// Overload the >> operator | |
template<typename T> | |
ThreadSafeIStream &operator>>(T &value) { | |
std::string input; | |
console_.read(input); | |
std::istringstream iss(input); | |
iss >> value; | |
return *this; | |
} | |
private: | |
ThreadSafeConsole &console_; | |
}; | |
// Global instances of the streams | |
inline ThreadSafeOStream ts_cout; | |
inline ThreadSafeIStream ts_cin; | |
#endif // THREAD_SAFE_CONSOLE_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment