Skip to content

Instantly share code, notes, and snippets.

@potat-dev
Created June 3, 2024 00:46
Show Gist options
  • Save potat-dev/407227e2383e8a9135759c3d610b60c0 to your computer and use it in GitHub Desktop.
Save potat-dev/407227e2383e8a9135759c3d610b60c0 to your computer and use it in GitHub Desktop.
super simple thread safe console implementation C++ using mutex and queue
// 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