With Boost.Coroutine it is possible to use coroutines in C++. Coroutines are a feature of other programming languages, which often use the keyword yield for coroutines. In these programming languages, yield can be used like return. However, when yield is used, the function remembers the location, and if the function is called again, execution continues from that location.
in modern c++ the memory of returned object or value is saved to use an extern of function so there is no need to call copy or move constructor
A fun(){
A a(2);
cout<<&a<<endl;
return a;
}
int main(int argc,const char *argv[]){
A a=fun();
cout<<&a<<endl;//it have same address of object inside fun function
return 0;
}
A string is very similar to a std::vector The following code snippet has the std::string name with the value RainerGrimm. I use the STL algorithm std::find_if to get the upper letter and then extract my first and last name into the variables firstName and lastName. The expression name.begin()+1 shows, that strings support random access iterators:
#include <regex>
...
using std::regex_constants::ECMAScript;
using std::regex_constants::icase;
std::string theQuestion="C++ or c++, that's the question.";
std::string regExprStr(R"(c\+\+)");
std::regex rgx(regExprStr);
std::smatch smatch;
if (std::regex_search(theQuestion, smatch, rgx)){
std::cout << "case sensitive: " << smatch[0]; // c++
}
std::regex rgxIn(regExprStr, ECMAScript|icase);
if (std::regex_search(theQuestion, smatch, rgxIn)){
std::cout << "case insensitive: " << smatch[0]; // C++
}
#include <regex>
...
// regular expression holder for time
std::regex crgx("([01]?[0-9]|2[0-3]):[0-5][0-9]");
// const char*
std::cmatch cmatch;
const char* ctime{"Now it is 23:10."};
if (std::regex_search(ctime, cmatch, crgx)){
std::cout << ctime << std::endl; // Now it is 23:10.
std::cout << "Time: " << cmatch[0] << std::endl; // Time: 23:10
}
// std::string
std::smatch smatch;
std::string stime{"Now it is 23:25."};
if (std::regex_search(stime, smatch, crgx)){
std::cout << stime << std::endl; // Now it is 23:25.
std::cout << "Time: " << smatch[0] << std::endl; // Time: 23:25
}
// regular expression holder for time
std::wregex wrgx(L"([01]?[0-9]|2[0-3]):[0-5][0-9]");
// const wchar_t*
std::wcmatch wcmatch;
const wchar_t* wctime{L"Now it is 23:47."};
if (std::regex_search(wctime, wcmatch, wrgx)){
std::wcout << wctime << std::endl; // Now it is 23:47.
std::wcout << "Time: " << wcmatch[0] << std::endl; // Time: 23:47
}
// std::wstring
std::wsmatch wsmatch;
std::wstring wstime{L"Now it is 00:03."};
if (std::regex_search(wstime, wsmatch, wrgx)){
std::wcout << wstime << std::endl; // Now it is 00:03.
std::wcout << "Time: " << wsmatch[0] << std::endl; // Time: 00:03
}
QByteArray bytes="hello world 112";
std::regex reg("((\\s+)|([a-z]+)|(\\d+))+");
std::match_results<QByteArray::iterator> matches;
std::regex_search(bytes.begin(),bytes.end(),matches,reg);
for(auto& v : matches){
qDebug()<<v.first;
}
match
#include <regex>
...
std::string numberRegEx(R"([-+]?([0-9]*\.[0-9]+|[0-9]+))");
std::regex rgx(numberRegEx);
const char* numChar{"2011"};
if (std::regex_match(numChar, rgx)){
std::cout << numChar << " is a number." << std::endl;
} // 2011 is a number.
const std::string numStr{"3.14159265359"};
if (std::regex_match(numStr, rgx)){
std::cout << numStr << " is a number." << std::endl;
} // 3.14159265359 is a number.
const std::vector<char> numVec{{'-', '2', '.', '7', '1', '8', '2',
'8', '1', '8', '2', '8'}};
if (std::regex_match(numVec.begin(), numVec.end(), rgx)){
for (auto c: numVec){ std::cout << c ;};
std::cout << " is a number." << std::endl;
} // -2.718281828 is a number.
replace
string future{"Future"};
string unofficialName{"The unofficial name of the new C++ standard is C++0x."};
regex rgxCpp{R"(C\+\+0x)"};
string newCppName{"C++11"};
string newName{regex_replace(unofficialName, rgxCpp, newCppName)};
regex rgxOff{"unofficial"};
string makeOfficial{"official"};
string officialName{regex_replace(newName, rgxOff, makeOfficial)};
cout << officialName << endl;
// The official name of the new C++ standard is C++11.
filter
std::string future{"Future"};
const std::string unofficial{"unofficial, C++0x"};
const std::string official{"official, C++11"};
std::regex regValues{"(.*),(.*)"};
std::string standardText{"The $1 name of the new C++ standard is $2."};
std::string textNow= std::regex_replace(unofficial, regValues, standardText);
std::cout << textNow << std::endl;
// The unofficial name of the new C++ standard is C++0x.
std::smatch smatch;
if (std::regex_match(official, smatch, regValues)){
std::cout << smatch.str(); // official,C++11
std::string textFuture= smatch.format(standardText);
std::cout << textFuture << std::endl;
} // The official name of the new C++ standard is C++11.
C++ has a set of simple atomic data types. These are booleans, characters, numbers and pointers in many variants. They need the header <atomic>. You can define your atomic data type with the class template std::atomic, but there are serious restrictions for your type std::atomic<MyType>:
For MyType there are the following restrictions:
The copy assignment operator for MyType, for all base classes of MyType and all non-static members of MyType, must be trivial. Only a compiler generated copy assignment operator is trivial.
MyType must not have virtual methods or base classes.
MyType must be bitwise copyable and comparable so that the C functions memcpy or memcmp can be applied.
Atomic data types have atomic operations. For example load and store:
int cnt = 0;
auto f = [&]{cnt++;};
std::thread t1{f}, t2{f}, t3{f}; // undefined behavior
std::atomic<int> cnt{0};
auto f = [&]{cnt++;};
std::thread t1{f}, t2{f}, t3{f}; // OK
what is trivial ?
A trivial type is a type whose storage is contiguous (trivially copyable) and which only supports static default initialization (trivially default constructible), either cv-qualified or not. It includes scalar types, trivial classes and arrays of any such types.
A thread std::thread represents an executable unit. This executable unit, which the thread immediately starts, gets its work package as a callable unit. A callable unit can be a function, a function object or a lambda function
The creator of a thread has to take care of the lifetime of its created thread. The executable unit of the created thread ends with the end of the callable. Either the creator is waiting until the created thread t is done (t.join()) or the creator detaches itself from the created thread: t.detach(). A thread t is joinable if no operation t.join() or t.detach() was performed on it. A joinable thread calls in its destructor the exception std::terminate, and the program terminates.
thread t1(helloFunction); // function
HelloFunctionObject helloFunctionObject;
thread t2(helloFunctionObject); // function object
thread t3([]{ cout << "lambda function"; }); // lambda function
t1.join();
t2.join();
t3.join();
You can move a callable from one thread to another.
By performing t2= std::move(t) thread t2 has the callable of thread t. Assuming thread t2 already had a callable and is joinable the C++ runtime would call std::terminate. This happens exactly in t2= std::move(t3) because t2 neither executed t2.join() nor t2.detach() before.
Waits until thread t has finished its executable unit.
t.detach()
Executes the created thread t independent of the creator.
t.joinable()
Checks if thread t supports the calls join or detach.
t.get_id() and
Returns the identity of the thread.
this_thread::get_id()
thread::hardware_concurrency()
Indicates the number of threads that can be run in parallel.
this_thread::sleep_until(absTime)
Puts the thread t to sleep until time absTime.
this_thread::sleep_for(relTime)
Puts the thread t to sleep for the duration relTime.
this_thread::yield()
Offers the system to run another thread.
t.swap(t2) and
Swaps the threads.
swap(t1, t2)
You can only call t.join() or t.detach() once on a thread t. If you attempt to call these more than once you get the exception std::system_error. std::thread::hardware_concurrency returns the number of cores or 0 if the runtime cannot determine the number. The sleep_until and sleep_for operations needs a time point or a time duration as argument.
Threads cannot be copied but can be moved. A swap operation performs a move when possible.
The std::shared_time_mutex enables it to implement reader-writer locks. The method m.try_lock_for(relTime) needs a relative time duration; the method m.try_lock_until(absTime) a absolute time point.
Deadlocks A deadlock is a state in which two or more threads are blocked because each thread waits for the release of a resource before it releases its resource.
You can get a deadlock very quickly if you forget to call m.unlock(). That happens for example in case of an exception in the function getVar().
m.lock();
sharedVar= getVar();//dont use lock inside getVar
m.unlock()
Locks You should encapsulate a mutex in a lock to release the mutex automatically. A lock is an implementation of the RAII idiom because the lock binds the lifetime of the mutex to its lifetime. C++11 has std::lock_guard for the simple and std::unique_lock for the advanced use case, respectively. Both need the header <mutex>. With C++14 C++ has a std::shared_lock which is in the combination with the mutex std::shared_time_mutex the base for reader-writer locks.
std::lock_guard supports only the simple use case. Therefore it can only bind its mutex in the constructor and release it in the destructor.
std::mutex coutMutex;
struct Worker{
Worker(std::string n):name(n){};
void operator() (){
for (int i= 1; i <= 3; ++i){
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::lock_guard<std::mutex> myLock(coutMutex);
std::cout << name << ": " << "Work " << i << std::endl;
}
}
private:
std::string name;
};
unique_lock is a general-purpose mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership, and use with condition variables.
#include <mutex>
#include <thread>
#include <chrono>
struct Box {
explicit Box(int num) : num_things{num} {}
int num_things;
std::mutex m;
};
void transfer(Box &from, Box &to, int num)
{
// don't actually take the locks yet
std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
// lock both unique_locks without deadlock
std::lock(lock1, lock2);
from.num_things -= num;
to.num_things += num;
// 'from.m' and 'to.m' mutexes unlocked in 'unique_lock' dtors
}
int main()
{
Box acc1(100);
Box acc2(50);
std::thread t1(transfer, std::ref(acc1), std::ref(acc2), 10);
std::thread t2(transfer, std::ref(acc2), std::ref(acc1), 5);
t1.join();
t2.join();
}
Thread Local Data
By using the keyword thread_local, you have thread local data also known as thread local storage. Each thread has its copy of the data. Thread-local data behaves like static variables. They are created at their first usage, and their lifetime is bound to the lifetime of the thread.
Condition variables enable threads to be synchronised via messages. They need the header <condition_variable>. One thread acts as a sender, and the other as a receiver of the message. The receiver waits for the notification of the sender.
Method
Description
cv.notify_one()
Notifies a waiting thread.
cv.notify_all()
Notifies all waiting threads.
cv.wait(lock, ...)
Waits for the notification while holding a std::unique_lock.
cv.wait_for(lock, relTime, ...)
Waits for a time duration for the notification while holding a std::unique_lock.
cv.wait_until(lock, absTime, ...)
Waits until a time for the notification while holding a std::unique_lock.
Sender and receiver need a lock. In case of the sender a std::lock_guard is sufficient, because it only once calls lock and unlock. In the case of the receiver a std::unique_lock is necessary, because it typically often locks and unlocks its mutex.
In addition to threads, C++ has tasks to perform work asynchronously. Tasks need the header <future>. A task is parameterised with a work package and consists of the two associated components, a promise and a future. Both are connected via a data channel. The promise executes the work packages and puts the result in the data channel; the associated future picks up the result. Both communication endpoints can run in separate threads. What’s special is that the future can pick up the result at a later time. Therefore the calculation of the result by the promise is independent of the query of the result by the associated future.
asks behave like data channels. The promise puts its result in the data channel. The future waits for it and picks it up.
Threads are very different from tasks.
For the communication between the creator thread and the created thread, you have to use a shared variable. The task communicates via its data channel, which is implicitly protected. Therefore a task must not use a protection mechanism like a mutex.
The creator thread is waiting for its child with the join call. The future fut is using the `fut.get() call which is blocking if no result is there.
If an exception happens in the created thread, the created thread terminates and therefore the creator and the whole process. On the contrary, the promise can send the exceptions to the future, which has to handle the exception.
A promise can serve one or many futures. It can send a value, an exception or only a notification. You can use a task as a safe replacement for a condition variable.
std::async behaves like an asynchronous function call. This function call takes a callable and its arguments. std::async is a variadic template and can, therefore, take an arbitrary number of arguments. The call of std::async returns a future object fut. That’s your handle for getting the result via fut.get(). Optionally you can specify a start policy for std::async. You can explicitly determine with the start policy if the asynchronous call should be executed in the same thread (std::launch::deferred) or in another thread (std::launch::async).
What’s special about the call auto fut= std::async(std::launch::deferred, ... ) is that the promise will not immediately be executed. The call fut.get() lazy starts the promise.Lazy and eager with std::async
#include <future>
...
using std::chrono::duration;
using std::chrono::system_clock;
using std::launch;
auto begin= system_clock::now();
auto asyncLazy= std::async(launch::deferred, []{ return system_clock::now(); });
auto asyncEager= std::async(launch::async, []{ return system_clock::now(); });
std::this_thread::sleep_for(std::chrono::seconds(1));
auto lazyStart= asyncLazy.get() - begin;
auto eagerStart= asyncEager.get() - begin;
auto lazyDuration= duration<double>(lazyStart).count();
auto eagerDuration= duration<double>(eagerStart).count();
std::cout << lazyDuration << " sec"; // 1.00018 sec.
std::cout << eagerDuration << " sec"; // 0.00015489 sec.
The output of the program shows that the promise associated with the future asyncLazy is executed one second later than the promise associated with the future asyncEager. One second is exactly the time duration the creator is sleeping before the future asyncLazy asks for its result.
std::packaged_task enables you to build a simple wrapper for a callable, which can later be executed on a separate thread.
Therefore four steps are necessary.
std::packaged_task<int(int, int)> sumTask([](int a, int b){ return a+b; });
std::future<int> sumResult= sumTask.get_future();
sumTask(2000, 11);
sumResult.get();
...
#include <future>
...
using namespace std;
struct SumUp{
int operator()(int beg, int end){
for (int i= beg; i < end; ++i ) sum += i;
return sum;
}
private:
int beg;
int end;
int sum{0};
};
SumUp sumUp1, sumUp2;
packaged_task<int(int, int)> sumTask1(sumUp1);
packaged_task<int(int, int)> sumTask2(sumUp2);
future<int> sum1= sumTask1.get_future();
future<int> sum2= sumTask2.get_future();
deque< packaged_task<int(int, int)>> allTasks;
allTasks.push_back(move(sumTask1));
allTasks.push_back(move(sumTask2));
int begin{1};
int increment{5000};
int end= begin + increment;
while (not allTasks.empty()){
packaged_task<int(int, int)> myTask= move(allTasks.front());
allTasks.pop_front();
thread sumThread(move(myTask), begin, end);
begin= end;
end += increment;
sumThread.detach();
}
auto sum= sum1.get() + sum2.get();
cout << sum; // 50005000
The promises (std::packaged_task) are moved into the std::deque allTasks. The program iterates in the while loop through all promises. Each promise runs in its thread and performs its addition in the background (sumThread.detach()). The result is the sum of all numbers from 0 to 100000.
The pair std::promise and std::future give the full control over the task.
Method
Description
prom.swap(prom2) and
Swaps the promises.
std::swap(prom, prom2)
prom.get_future()
Returns the future.
prom.set_value(val)
Sets the value.
prom.set_exception(ex)
Sets the exception.
prom.set_value_at_thread_exit(val)
Stores the value and makes it ready if the promise exits.
prom.set_exception_at_thread_exit(ex)
Stores the exception and makes it ready if the promise exits.
Method
Description
fut.share()
Returns a std::shared_future.
fut.get()
Returns the result which can be a value or an exception.
fut.valid()
Checks if the result is available. Returns after the call fut.get() false.
fut.wait()
Waits for the result.
fut.wait_for(relTime)
Waits for a time duration for the result.
fut.wait_until(absTime)
Waits until a time for the result.
If a future fut asks more than once for the result, a std::future_error exception is thrown. The future creates a shared future by the call fut.share(). Shared future are associated with their promise and can independently ask for the result. A shared future has the same interface as a future.
Here is the usage of promise and future.
#include <future>
...
void product(std::promise<int>&& intPromise, int a, int b){
intPromise.set_value(a*b);
}
int a= 20;
int b= 10;
std::promise<int> prodPromise;
std::future<int> prodResult= prodPromise.get_future();
std::thread prodThread(product, std::move(prodPromise), a, b);
std::cout << "20*10= " << prodResult.get();//wait intPromise.set_value 20*10= 200
The promise prodPromise is moved into a separate thread and performs its calculation. The future gets the result by prodResult.get().
A future fut can be synchronised with is associated promise by the call fut.wait(). Contrary to condition variables, you need no locks and mutexes, and spurious and lost wakeups are not possible.
Chrono library is used to deal with date and time. This library was designed to deal with the fact that timers and clocks might be different on different systems and thus to improve over time in terms of precision. The unique thing about chrono is that it provides a precision-neutral concept by separating duration and point of time (“timepoint”) from specific clocks.
chrono is the name of a header and also of a sub-namespace: All the elements in this header (except for the common_type specializations) are not defined directly under the std namespace (like most of the standard library) but under the std::chrono namespace. The elements in this header deal with time. This is done mainly by means of three concepts:
constexpr auto year = 31556952ll; // seconds in average Gregorian year
int main()
{
using shakes = std::chrono::duration<int, std::ratio<1, 100000000>>;
using jiffies = std::chrono::duration<int, std::centi>;
using microfortnights = std::chrono::duration<float, std::ratio<14*24*60*60, 1000000>>;
using nanocenturies = std::chrono::duration<float, std::ratio<100*year, 1000000000>>;
std::chrono::seconds sec(1);
std::cout << "1 second is:\n";
// integer scale conversion with no precision loss: no cast
std::cout << std::chrono::microseconds(sec).count() << " microseconds\n"
<< shakes(sec).count() << " shakes\n"
<< jiffies(sec).count() << " jiffies\n";
// integer scale conversion with precision loss: requires a cast
std::cout << std::chrono::duration_cast<std::chrono::minutes>(sec).count()
<< " minutes\n";
// floating-point scale conversion: no cast
std::cout << microfortnights(sec).count() << " microfortnights\n"
<< nanocenturies(sec).count() << " nanocenturies\n";
}
Clock
A clock consists of a starting point (or epoch) and a tick rate. For example, a clock may have an epoch of February 22, 1996 and tick every second. C++ defines three clock types:
system_clock-It is the current time according to the system (regular clock which we see on the toolbar of the computer). It is written as- std::chrono::system_clock
steady_clock-It is a monotonic clock that will never be adjusted.It goes at a uniform rate. It is written as- std::chrono::steady_clock
high_resolution_clock– It provides the smallest possible tick period. It is written as-std::chrono::high_resolution_clock
converts std::time_t to a system clock time point (system_clock)
#include <iostream>
#include <chrono>
#include <ctime>
// Function to calculate
// Fibonacci series
long fibonacci(unsigned n)
{
if (n < 2) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
int main()
{
// Using time point and system_clock
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
std::cout << "f(42) = " << fibonacci(42) << '\n';
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::cout << "finished computation at " << std::ctime(&end_time)
<< "elapsed time: " << elapsed_seconds.count() << "s\n";
}
auto start = std::chrono::high_resolution_clock::now();
...
auto elapsed = std::chrono::high_resolution_clock::now() - start;
long long microseconds = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t t_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
std::cout << "24 hours ago, the time was "
<< std::put_time(std::localtime(&t_c), "%F %T") << '\n';
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
std::cout << "Hello World\n";
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Printing took "
<< std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
<< "us.\n";
std::prev_permutation and std::next_permutation return the previous smaller or next bigger permutation of the newly ordered range. If a smaller or bigger permutation is not available, the algorithms return false. Both algorithms need bidirectional iterators. Per default the predefined sorting criterion std::less is used. If you use your sorting criterion, it has to obey the strict weak ordering. If not, the program is undefined.
You can determine the minimum, the maximum and the minimum and maximum pair of a range with the algorithms std::min_element, std::max_element and std::minmax_element. Each algorithm can be configured with a binary predicate.