#include
#include
#include
#include
#include
#include
using namespace std;
int main ()
{
try {
// query local time:
auto now = chrono::system_clock::now();
std::time_t t = chrono::system_clock::to_time_t(now);
tm* nowTM = std::localtime(&t);
// print local time with the global classic locale:
locale locC;
const time_put& tpC = use_facet>(locC);
// use single conversion specifier
tpC.put (cout, cout, ' ', nowTM, 'x');
cout << endl;
// use format string:
string format = "%A %x %I%p\n"; // format: weekday date hour
tpC.put (cout, cout, ' ', nowTM,
format.c_str(), format.c_str()+format.size() );
// print local time with German locale:
#ifdef _MSC_VER
locale locG("deu_deu.1252");
#else
locale locG("de_DE");
#endif
const time_put& tpG = use_facet>(locG);
tpG.put (cout, cout, ' ', nowTM, 'x');
cout << endl;
tpG.put (cout, cout, ' ', nowTM,
format.c_str(), format.c_str()+format.size() );
}
catch (const std::exception& e) {
cerr << "Exception: " << e.what() << endl;
return EXIT_FAILURE;
}
}
输出:
12/19/23
Tuesday 12/19/23 04PM
Exception: locale::facet::_S_create_c_locale name not valid
#include
#include
#include
#include
int main()
{
// create default engine as source of randomness
std::default_random_engine dre;
// use engine to generate integral numbers between 10 and 20 (both included)
std::uniform_int_distribution di(10,20);
for (int i=0; i<20; ++i) {
std::cout << di(dre) << " ";
}
std::cout << std::endl;
// use engine to generate floating-point numbers between 10.0 and 20.0
// (10.0 included, 20.0 not included)
std::uniform_real_distribution dr(10,20);
for (int i=0; i<8; ++i) {
std::cout << dr(dre) << " ";
}
std::cout << std::endl;
// use engine to shuffle elements
std::vector v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//...
std::shuffle (v.begin(), v.end(), // range
dre); // source of randomness
for (int i=0; i
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
// 等待随机的时间,打印字符
void doSomething (char c)
{
// random-number generator (use c as seed to get different sequences)
default_random_engine dre(c);
uniform_int_distribution id(10,1000);
// loop to print character after a random period of time
for (int i=0; i<10; ++i) {
this_thread::sleep_for(chrono::milliseconds(id(dre)));
cout.put(c).flush();
}
}
int main()
{
cout << "starting 2 operations asynchronously" << endl;
// start two loops in the background printing characters . or +
// 多线程环境下,两个线程会被启动,当然也有可能两个都不会被启动
auto f1 = async([]{ doSomething('.'); });
auto f2 = async([]{ doSomething('+'); });
// if at least one of the background tasks is running
// 询问是否至少有一个操作未被推迟
if (f1.wait_for(chrono::seconds(0)) != future_status::deferred ||
f2.wait_for(chrono::seconds(0)) != future_status::deferred) {
// poll until at least one of the loops finished
// 询问是否至少有一个操作已经完成,如果都没有完成继续询问
while (f1.wait_for(chrono::seconds(0)) != future_status::ready &&
f2.wait_for(chrono::seconds(0)) != future_status::ready) {
//...;
// 两个线程都没有完成,切换到另外的线程
this_thread::yield(); // hint to reschedule to the next thread
}
}
cout.put('\n').flush();
// wait for all loops to be finished and process any exception
try {
f1.get();
f2.get();
}
catch (const exception& e) {
cout << "\nEXCEPTION: " << e.what() << endl;
}
cout << "\ndone" << endl;
}
输出:
starting 2 operations asynchronously
+..+..+...+..+.
+++++
done
#include
#include
#include
#include
#include
using namespace std;
int queryNumber ()
{
// read number
cout << "read number: ";
int num;
cin >> num;
// throw exception if none
if (!cin) {
throw runtime_error("no number read");
}
return num;
}
void doSomething (char c, shared_future f)
{
try {
// wait for number of characters to print
int num = f.get(); // get result of queryNumber()
for (int i=0; i f = async(queryNumber);
// start three threads each processing this number in a loop
auto f1 = async(launch::async,doSomething,'.',f);
auto f2 = async(launch::async,doSomething,'+',f);
auto f3 = async(launch::async,doSomething,'*',f);
// wait for all loops to be finished
f1.get();
f2.get();
f3.get();
}
catch (const exception& e) {
cout << "\nEXCEPTION: " << e.what() << endl;
}
cout << "\ndone" << endl;
}
输入:7
.+**+..+*+*.+*..*+*+.
done
输入:x
EXCEPTION in thread EXCEPTION in thread 5: EXCEPTION in thread 4: no number read
3: no number read
no number read
done
#include
#include
#include
#include
#include
using namespace std;
void doSomething (int num, char c)
{
try {
// random-number generator (use c as seed to get different sequences)
default_random_engine dre(42*c);
uniform_int_distribution id(10,1000);
for (int i=0; i
#include
#include
#include
#include
#include
#include
#include
#include
void doSomething (std::promise& p)
{
try {
// read character and throw exception if 'x'
std::cout << "read char ('x' for exception): ";
char c = std::cin.get();
if (c == 'x') {
throw std::runtime_error(std::string("char ")+c+" read");
}
//...
std::string s = std::string("char ") + c + " processed";
p.set_value_at_thread_exit(std::move(s)); // store result
}
catch (...) {
p.set_exception_at_thread_exit(std::current_exception()); // store exception
}
}
int main()
{
try {
// create a promise to store the outcome
std::promise p;
// create a future to process the outcome
std::future f(p.get_future());
// start a thread using the promise to store the outcome
std::thread t(doSomething,std::ref(p));
t.detach();
//...
// process the outcome
std::cout << "result: " << f.get() << std::endl;
}
catch (const std::exception& e) {
std::cerr << "EXCEPTION: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "EXCEPTION " << std::endl;
}
}
输出:
result: read char ('x' for exception): 2
char 2 processed
result: read char ('x' for exception): x
EXCEPTION: char x read
std::unique_lock
是 C++ 标准库中的一个锁管理工具,它提供了对互斥量(std::mutex
)的更灵活的管理和使用方式。std::unique_lock
具有比 std::lock_guard
更多的特性,例如支持延迟锁定和手动解锁,使其在一些复杂的情境下更为适用。
std::unique_lock lock(mutex);
传递mutex互斥量,unique_lock对象会立即锁定互斥量。
与 std::lock_guard
不同,std::unique_lock
可以在构造时选择是否立即锁定互斥量。可以通过构造函数的第二个参数 std::defer_lock
来实现延迟锁定。
std::unique_lock lock(mutex, std::defer_lock);
//这里互斥量并未锁定
...
lock.lock(); //手动锁定互斥量
与 std::lock_guard
不同,std::unique_lock
允许在需要的时候手动解锁互斥量,然后再次锁定。
std::unique_lock lock(mutex);
//...
lock.unlock(); //手动解锁
//...
lock.lock(); //手动锁定
std::unique_lock
提供了与条件变量一起使用的特性,可以在等待条件满足时自动释放锁,以及在条件不满足时重新获取锁。
std::unique_lock lock(mutex);
cv.wait(lock, [](){return condition;});
std::unique_lock
允许锁定多个互斥量,以防止死锁。可以在构造函数中传递多个互斥量,并使用 std::lock
来避免死锁。
std::mutex mutex1, mutex2;
std::unique_lock lock1(mutex1, std::defer_lock);
std::unique_lock lock2(mutex2, std::defer_lock);
std::lock(lock1, lock2);
#include
#include
#include
#include
#include
#include
std::queue queue;
std::mutex queueMutex;
std::condition_variable queueCondVar;
void provider (int val)
{
// push different values (val til val+5 with timeouts of val milliseconds into the queue
for (int i=0; i<6; ++i) {
{
std::lock_guard lg(queueMutex);
queue.push(val+i);
} // release lock
queueCondVar.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(val));
}
}
void consumer (int num)
{
// pop values if available (num identifies the consumer)
while (true) {
int val;
{
std::unique_lock ul(queueMutex);
queueCondVar.wait(ul,[]{ return !queue.empty(); });
val = queue.front();
queue.pop();
} // release lock
std::cout << "consumer " << num << ": " << val << std::endl;
}
}
int main()
{
// start three providers for values 100+, 300+, and 500+
auto p1 = std::async(std::launch::async,provider,100);
auto p2 = std::async(std::launch::async,provider,300);
auto p3 = std::async(std::launch::async,provider,500);
// start two consumers printing the values
auto c1 = std::async(std::launch::async,consumer,1);
auto c2 = std::async(std::launch::async,consumer,2);
}
所有的notify_one()和notify_all()都会被自动同步化,所以他们的调用不需要放在加锁代码块里面。所有等待某个condition variable的线程都必须使用相同的mutex,当wait()家族的某个成员被调用时,该mutex必须被unique_lock锁定,否则会发生不明确的行为。
注意:condition variable的消费者总是在“被锁住的mutex”基础上操作,只有等待函数会执行以下三个atomic步骤暂时解除mutex:1.解除mutex然后进入等待状态,2.解除因等待而造成的阻塞。3.再次锁住mutex。