C++14stlintermediate
std::shared_timed_mutex
C++14 · Modern Refined · Compiler flag: -std=c++14
Explanation
A mutex that supports both exclusive (write) and shared (read) ownership, with the ability to specify timeouts via `try_lock_for` and `try_lock_shared_for`. Multiple threads can hold a shared lock simultaneously for reading, while an exclusive lock blocks all other access for writing.
Real-World Scenario
A real-time stock ticker serves thousands of reader threads displaying prices while a single writer thread updates quotes from the exchange feed. `std::shared_timed_mutex` maximizes read concurrency while ensuring safe writes, with timeouts preventing reader starvation.
Quick Snippet
snippet.cpp
#include <shared_mutex>
#include <thread>
#include <iostream>
#include <chrono>
std::shared_timed_mutex rw_mutex;
int shared_data = 0;
void reader(int id) {
rw_mutex.lock_shared();
std::cout << "Reader " << id << " sees: " << shared_data << "\n";
rw_mutex.unlock_shared();
}
void writer(int value) {
rw_mutex.lock();
shared_data = value;
std::cout << "Writer set: " << value << "\n";
rw_mutex.unlock();
}
int main() {
std::thread w(writer, 42);
w.join();
std::thread r1(reader, 1), r2(reader, 2);
r1.join(); r2.join();
}Full Example
shared_timed_mutex.cpp
// CodeNebula - C++14 Example: std::shared_timed_mutex
// Compile: g++ -std=c++14 -Wall -Wextra -pthread -o example shared_timed_mutex.cpp
// Demonstrates std::shared_timed_mutex for reader-writer locking with timeout
// support. Multiple threads can hold shared (read) locks simultaneously, but
// exclusive (write) locks are solitary. Real-world use: caches, configuration
// stores, and any data structure with many readers and few writers.
#include <iostream>
#include <shared_mutex>
#include <thread>
#include <vector>
#include <chrono>
#include <string>
#include <sstream>
#include <mutex>
// ------------------------------------------------------------------
// Thread-safe print helper (avoid interleaved output)
// ------------------------------------------------------------------
std::mutex cout_mutex;
void safe_print(const std::string& msg)
{
std::lock_guard<std::mutex> lock(cout_mutex);
std::cout << msg << std::endl;
}
// ------------------------------------------------------------------
// Shared cache protected by shared_timed_mutex
// ------------------------------------------------------------------
class ThreadSafeCache
{
mutable std::shared_timed_mutex mutex_;
std::string data_ = "(empty)";
int version_ = 0;
public:
// Read operation: shared lock (multiple readers OK)
std::string read(const std::string& reader_name) const
{
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
std::ostringstream oss;
oss << " [" << reader_name << "] READ v" << version_
<< ": " << data_;
return oss.str();
}
// Write operation: exclusive lock (single writer)
void write(const std::string& writer_name, const std::string& value)
{
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
++version_;
data_ = value;
std::ostringstream oss;
oss << " [" << writer_name << "] WRITE v" << version_
<< ": " << data_;
safe_print(oss.str());
}
// Timed read: try to acquire shared lock with timeout
bool try_read_for(const std::string& reader_name,
std::chrono::milliseconds timeout) const
{
std::shared_lock<std::shared_timed_mutex> lock(mutex_, timeout);
if (lock.owns_lock())
{
std::ostringstream oss;
oss << " [" << reader_name << "] TIMED READ v" << version_
<< ": " << data_;
safe_print(oss.str());
return true;
}
safe_print(" [" + reader_name + "] TIMED READ: timeout!");
return false;
}
// Timed write: try to acquire exclusive lock with timeout
bool try_write_for(const std::string& writer_name,
const std::string& value,
std::chrono::milliseconds timeout)
{
std::unique_lock<std::shared_timed_mutex> lock(mutex_, timeout);
if (lock.owns_lock())
{
++version_;
data_ = value;
std::ostringstream oss;
oss << " [" << writer_name << "] TIMED WRITE v" << version_
<< ": " << data_;
safe_print(oss.str());
return true;
}
safe_print(" [" + writer_name + "] TIMED WRITE: timeout!");
return false;
}
};
int main()
{
ThreadSafeCache cache;
// ------------------------------------------------------------------
// 1. Single-threaded demonstration
// ------------------------------------------------------------------
std::cout << "=== Single-Threaded Read/Write ===" << std::endl;
cache.write("main", "initial data");
safe_print(cache.read("main"));
cache.write("main", "updated data");
safe_print(cache.read("main"));
std::cout << std::endl;
// ------------------------------------------------------------------
// 2. Multiple concurrent readers
// ------------------------------------------------------------------
std::cout << "=== Concurrent Readers ===" << std::endl;
cache.write("main", "shared value");
std::vector<std::thread> readers;
for (int i = 0; i < 4; ++i)
{
readers.emplace_back([&cache, i]() {
std::string name = "reader" + std::to_string(i);
safe_print(cache.read(name));
});
}
for (auto& t : readers) t.join();
std::cout << std::endl;
// ------------------------------------------------------------------
// 3. Timed lock attempts
// ------------------------------------------------------------------
std::cout << "=== Timed Lock Operations ===" << std::endl;
cache.try_read_for("timed_reader", std::chrono::milliseconds(100));
cache.try_write_for("timed_writer", "timed value",
std::chrono::milliseconds(100));
cache.try_read_for("timed_reader2", std::chrono::milliseconds(100));
std::cout << std::endl;
// ------------------------------------------------------------------
// 4. Writer-reader interaction
// ------------------------------------------------------------------
std::cout << "=== Writer-Reader Interaction ===" << std::endl;
std::thread writer([&cache]() {
for (int i = 1; i <= 3; ++i)
{
cache.write("writer", "data_v" + std::to_string(i));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
});
std::thread reader([&cache]() {
for (int i = 0; i < 3; ++i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
safe_print(cache.read("reader"));
}
});
writer.join();
reader.join();
return 0;
}
/*
Expected output (thread ordering may vary):
=== Single-Threaded Read/Write ===
[main] WRITE v1: initial data
[main] READ v1: initial data
[main] WRITE v2: updated data
[main] READ v2: updated data
=== Concurrent Readers ===
[main] WRITE v3: shared value
[reader0] READ v3: shared value
[reader1] READ v3: shared value
[reader2] READ v3: shared value
[reader3] READ v3: shared value
=== Timed Lock Operations ===
[timed_reader] TIMED READ v3: shared value
[timed_writer] TIMED WRITE v4: timed value
[timed_reader2] TIMED READ v4: timed value
=== Writer-Reader Interaction ===
[writer] WRITE v5: data_v1
[reader] READ v5: data_v1
[writer] WRITE v6: data_v2
[reader] READ v6: data_v2
[writer] WRITE v7: data_v3
[reader] READ v7: data_v3
*/
Run command
g++ -std=c++14 -Wall -Wextra -pthread -o example shared_timed_mutex.cpp