c++ - Correctly using atomic<T> -


i struggling writing lockless code atomic variables c++11 thread pool class based on https://github.com/nbsdx/threadpool. here modified class:

class threadpool { public:     explicit threadpool(int threadcount) :         _jobsleft(0),         _bailout(false)     {         _threads = std::vector<std::thread>(threadcount);         (int index = 0; index < threadcount; ++index)         {             _threads[index] = std::move(std::thread([this]                 {                     this->task();                 }));         }     }      void addjob(std::function<void(void)> job)     {         {             std::lock_guard<std::mutex> lock(_queuemutex);             _queue.emplace(job);         }         {             std::lock_guard<std::mutex> lock(_jobsleftmutex);             ++_jobsleft;         }         _jobavailablevar.notify_one();     }      void joinall()     {         if (!_bailout)         {             _bailout = true;             _jobavailablevar.notify_all();             (auto& x : _threads)             {                 if (x.joinable())                 {                     x.join();                 }             }         }     }      void waitall()     {         std::unique_lock<std::mutex> lock(_jobsleftmutex);         if (_jobsleft > 0)         {             _waitvar.wait(lock, [this]                           {                               return _jobsleft == 0;                           });         }     }  private:     void task()     {         while (!_bailout)         {             std::function<void(void)> job;             {                 std::unique_lock<std::mutex> lock(_queuemutex);                 _jobavailablevar.wait(lock, [this]                                       {                                           return _queue.size() > 0 || _bailout;                                       });                 if (_bailout)                 {                     return;                 }                 job = _queue.front();                 _queue.pop();             }             job();             {                 std::lock_guard<std::mutex> lock(_jobsleftmutex);                 --_jobsleft;             }             _waitvar.notify_one();         }     }      std::vector<std::thread> _threads;     std::queue<std::function<void(void)>> _queue;     int _jobsleft;     std::atomic<bool> _bailout;     std::condition_variable _jobavailablevar;     std::condition_variable _waitvar;     std::mutex _jobsleftmutex;     std::mutex _queuemutex; }; 

i puzzled following , appreciate pointers:

  • how make usage of _bailout atomic? played around atomic_flag not work in scenario.
  • is possible make _jobsleft behave correctly using atomic<int> without locks? had issue original thread pool waitall() not correctly return in rare cases. works fine feel wastes performance.

edit: final version normal locks available here: https://github.com/stfx/threadpool2

look @ atomic methods: http://en.cppreference.com/w/cpp/atomic/atomic

you should use load method atomically read value. however, aware following not atomic.

if (!_bailout) {     _bailout = true; 

there method perform these comparison , value swaps. see compare_exchange_weak method. jobcount can use atomic. ++ , -- atomic.

however, aware atomic single method call, after call situation may change. still need synchronized queue , need lock. not need standard os lock, can create lock using atomic variable (using store , compare_exchange_weak methods). see following post: https://webkit.org/blog/6161/locking-in-webkit/


Comments

Popular posts from this blog

javascript - Laravel datatable invalid JSON response -

java - Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; -

sql server 2008 - My Sql Code Get An Error Of Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value '8:45 AM' to data type int -