Monday, September 18, 2017

C++11: recursive_mutex

C++11 added a timed_mutex template class that allows you to recursively obtain a lock by a single thread. Here is an example:

#include <iostream>
#include <mutex>
#include <thread>

int gSharedData[2] = {1, 1};
std::recursive_mutex gRecursiveMutex;

void updateData()
{
  gRecursiveMutex.lock();
  gSharedData[0] = gSharedData[0] + 1;
  gRecursiveMutex.lock();
  gSharedData[1] = gSharedData[1] + 1;
  gRecursiveMutex.lock();
  std::cout << gSharedData[0] << " " << gSharedData[1] << " ";
  gRecursiveMutex.unlock();
  gRecursiveMutex.unlock();
  gRecursiveMutex.unlock();
}

struct FunctionClass
{
  void operator()()
  {
    int temp = 0;
    for (int i = 0; i < 3; i++)
    {
      updateData();
    }
  }
};

int main()
{
  std::thread t1{FunctionClass()};
  std::thread t2{FunctionClass()};
  std::thread t3{FunctionClass()};

  t1.join();
  t2.join();
  t3.join();
  std::cout << std::endl;
  return 0;
}
// Output: 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10



C++11: try_lock_until

C++11 added a timed_mutex template class that allows you to try for a lock until a specific point in time. Here is an example:

#include <iostream>
#include <mutex>
#include <thread>

std::timed_mutex gTimedMutex;

int main()
{
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }
  gTimedMutex.unlock();
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }

  std::cout << std::endl;
  return 0;
}
// Output: got_lock try_lock_timeout got_lock



C++11: timed_mutex: try_lock_for

C++11 added a timed_mutex template class that allows you to try for a lock for a specified period of time. Here is an example:

#include <iostream>
#include <mutex>
#include <thread>
 
std::timed_mutex gTimedMutex;
 
int main()
{
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }
  gTimedMutex.unlock();
  if (gTimedMutex.try_lock_for(std::chrono::milliseconds(100)))
  {
    std::cout << "got_lock ";
  }
  else
  {
    std::cout << "try_lock_timeout ";
  }
 
  std::cout << std::endl;
  return 0;
}
// Output: got_lock try_lock_timeout got_lock




C++11: At_Quick_Exit

C++11 added the function at_quick_exit to register functions that are called when quick_exit is called, after of which the process ends. Here is an example:

#include <cstdlib>
#include <iostream>

void f1() {std::cout << "f1 called: ";}
void f2() {std::cout << "f2 called: ";}
void f3() {std::cout << "f3 called: ";}

int main()
{
  at_quick_exit(f1);
  at_quick_exit(f2);
  at_quick_exit(f3);
  quick_exit(EXIT_SUCCESS);
  return 0;
}
// Output: f3 called: f2 called: f1 called:
Reference: http://www.cplusplus.com/reference/cstdlib/quick_exit/

C++11: Async

C++11 added the template function async that runs a function asynchronously. Here is an example:

#include <chrono>
#include <future>
#include <iostream>
#include <string>
#include <thread>

class FunctionClass
{
 private:
  std::string mThreadName;
  int         mSleepTime;
  
 public:
  int operator()()
  {
    std::this_thread::sleep_for(
                        std::chrono::milliseconds(mSleepTime));
    for (int i = 0; i < 3; i++)
    {
      std::cout << mThreadName;
    }
    std::cout << " ";
    return mSleepTime + 1000;
  }
  FunctionClass(std::string threadName, int sleepTime)
  : mThreadName(threadName), mSleepTime(sleepTime)
  {}
};

int main()
{
  FunctionClass f1("F1", 200);

  auto handle = std::async(std::launch::async, f1);

  std::cout << handle.get() << std::endl;

  return 0;
}
// Output: F1F1F1 1200
Reference: http://en.cppreference.com/w/cpp/thread/async

C++11: Promise

C++11 added template class std::promise that enables a thread to store a value or exception that can be accessed by another thread. Here is an example:

#include <chrono>
#include <future>
#include <iostream>
#include <string>
#include <thread>

class FunctionClass
{
 private:
  std::string mThreadName;
  int         mSleepTime;
  
 public:
  void operator()(std::promise promise)
  {
    std::this_thread::sleep_for(
                        std::chrono::milliseconds(mSleepTime));
    for (int i = 0; i < 3; i++)
    {
      std::cout << mThreadName;
    }
    std::cout << " ";
    promise.set_value(mSleepTime + 1000);
  }
  FunctionClass(std::string threadName, int sleepTime)
  : mThreadName(threadName), mSleepTime(sleepTime)
  {}
};

int main()
{
  FunctionClass f1("F1", 100);

  std::promise<int> promise1;
  std::future<int>  future1 = promise1.get_future();
  std::thread       t1(f1, std::move(promise1));

  future1.wait();
  std::cout << future1.get() << std::endl;

  t1.join();

  return 0;
}
// Output: F1F1F1 1100
Reference: http://en.cppreference.com/w/cpp/thread/promise

C++11: Future

C++11 added template class std::future that enables a thread to access the result of an asynchronous operation. Here is an example:

#include <chrono>
#include <future>
#include <iostream>
#include <string>
#include <thread>

class FunctionClass
{
 private:
  std::string mThreadName;
  int         mSleepTime;
  
 public:
  int operator()()
  {
    std::this_thread::sleep_for(
                        std::chrono::milliseconds(mSleepTime));
    for (int i = 0; i < 3; i++)
    {
      std::cout << mThreadName;
    }
    return mSleepTime + 1000;
  }
  FunctionClass(std::string threadName, int sleepTime)
  : mThreadName(threadName), mSleepTime(sleepTime)
  {}
};

int main()
{
  FunctionClass f1("F1", 300);
  FunctionClass f2("F2", 200);
  FunctionClass f3("F3", 100);

  std::packaged_task<int()> task3(f3)           ;
  std::future<int>          future3             = task3.get_future();
  std::thread               t1(f1)              ;
  std::thread               t2(f2)              ;
  std::thread               t3(std::move(task3));

  future3.wait();
  std::cout << future3.get();

  t1.join();
  t2.join();
  t3.join();

  std::cout << std::endl;
  return 0;
}
// Output: F3F3F31100F2F2F2F1F1F1
Reference: http://en.cppreference.com/w/cpp/thread/future