Posts

Showing posts from April, 2018

std::shared_mutex

std::shared_mutex are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so. To protect shared data from being simultaneously accessed by multiple threads. #include<iostream> #include<mutex> #include<shared_mutex> #include<thread> class MutipleReaderSingleWriter {           int get() const           {                    std::shared_lock <std::shared_mutex> lock(mutex_);                    return _value;           }           void increment()           {                    std::unique_lock <std::shared_mutex> lock(mutex_);                     _value++;           }                     private:                    mutable std::shared_mutex mutex_;                    int _value = 0; }; int main() {           MutipleReaderSingleWriter list;                     auto incrementAndPrint = [&list

std::weak_ptr

std::weak_ptr std::weak_ptr is'nt a standalone smart pointer. It's an augmentation of std::shared_ptr.  It do not contribute to the reference count of the managed object they refer to. By using just the raw pointer, it is impossible to know if the referenced data has been deallocated or not. std::weak_ptr provides a "expired" API to check if the shared_ptr it was pointing to is expired. In a nutshell - The weak_ptr class template stores a “weak reference” to an object that’s already managed by a shared_ptr . To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor or the member function lock. When the last shared_ptr to the object goes away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, and weak_ptr::lock will return an empty shared_ptr . auto

Rvalue references vs Universal references

Whenever we see " T&& " it seems reasonable to assume that we are referring to "rvalue reference", but it's not. " T&& " has two different meanings - rvalue reference universal reference. For instance, below all are rvalue references because the types are known and not deduced. void fun(Base&& aObj); // rvalue reference Base&& a = Base();            // rvalue reference Universal references below in which the type is deduced. The most common is function template and auto declarations. template<typename T> void f(T&& param);     // param is being deduced, a universal reference auto&& obj2 = obj1;   // obj2 is a universal reference If we look at "T&&" without type deduction, it;s an rvalue reference. Universal reference can accept both rvalue and lvalue references, but they must be initialized.  If the initializer is rvalue, the universal refere

std::shared_ptr

Image
std::shared_ptr  for shared ownership An object accessed via std::shared_ptr s has its lifetime managed by those pointers through shared ownership. No specific std::shared_ptr owns the object. Instead all shared_ptr’s pointing to it collaborates to ensure its destruction at the point where it’s no longer needed. When the last shared_ptr pointing to an object stops pointing there, that shared_ptr destroys the object it points to. A shared_ptr can tell whether it’s the last one pointing to a resource by consulting the resource’s reference count, a value associated with the resource that keeps track of how many shared_ptrs point to it. Shared_ptrs constructors increments this count shared_ptr s destructors decrements it and copy assignment operators do both. If sp1 and sp2 are shared_ptr s to different objects, the assignment “ sp1=sp2 ” , modifies sp1 such that it points  to the object pointed to by sp2 . sp1 reference count is decremented, while that for the object point

std::unique_ptr

Smart Pointers Smart pointers are wrappers  around raw pointers that act much like the raw pointers they wrap, but that avoid many of their pitfalls. You should therefore prefer smart pointers to raw pointers.  Smart pointers can do virtually everything raw pointers can, but with far fewer  opportunities for error. std::auto_ptr is a deprecated leftover from C++98. It was an attempt to standardize  what later became C++11’s std::unique_ptr . Doing the job right required move  semantics, but C++98 didn’t have them. As a workaround, std::auto_ptr co-opted  its copy operations for moves. This led to surprising code (copying a std::auto_ptr sets it to null!) std::unique_ptr does everything std::auto_ptr does, plus more. It does it as efficiently,  and it does it without warping what it means to copy an object. It’s better  than std::auto_ptr in every way. The only legitimate use case for std::auto_ptr  is a need to compile code with C++98 compilers. Unless you have that

std::future and std::promise

Image
std::future  and std::promise These are the ways to pass data from one thread to another thread. While this can also be done with other capabilities, such as global variables, Old way - share data among threads using pointers, std::future and std::promise works without them  promise is non-copyable. One can move it, but cannot copy it. future is also non-copyable, but a future can become a shared_future that is copyable. So you can have multiple destinations, but only one source. promise can only set the value, it can't even get it back. future can only get the value, it cannot set it. Old Way – Share data among threads using pointers. Pass a pointer to the new thread and this thread will set data in it. Till then in main thread keep on waiting using a condition variable. When new thread sets the data an signals the condition variable, then main thread will wake up and fetch data from that pointer. To do a simple thing we used a condition variable, a mutex and

std::move and std::forward

std::move std::move does'nt move anything and std::forward does'nt forward anything. std::move unconditionally casts its arguments to an rvalue std::forward performs this casts only if a particular condition is fulfilled. Sample implementation of std::move below template<typename T> typename remove_reference<T>::type&& move(T param) {       using ReturnType = typename remove_reference<T>::type&&;       return static_cast<ReturnType> (param);       } std::move takes a reference to an object and it returns a reference to the same object. The "&&" part of the functions return type implies that std::move returns an rvalue reference, but if the type T happens to be an lvalue reference, T&& would become an lvalue reference. To prevent this from happening, the type trait remove_reference is applied to T, thus ensuring that " && " is applied to a type isn;t a reference. That gua