2013-11-02 7 views
2

Я хотел знать, есть ли у boost какие-либо библиотеки, которые помогают в реализации спиновых замков. Я знаю, что boost поддерживает мьютексы, но я не мог найти примеров, которые показывают или описывают spinlocks в boost. Будут оценены примеры, показывающие, как реализовать прямую блокировку с использованием boost (предпочтительно). (C++ 98)Реализация спин-блокировки в Boost. Необходимый пример:

ответ

0

образец с использованием C++, 11 атомарный:

#include <atomic> 

typedef std::atomic<bool> Lock; 

void enterCritical(Lock& lock) { 
    bool unlocked = false; 
    while (!lock.compare_exchange_weak(unlocked, true)); 
} 

void exitCritical(Lock& lock) { 
    lock.store(false); 
} 
+0

1. Лучше использовать 'зЬй :: atomic_flag' для этой цели, потому что он гарантированно безблокировочного. 2. Существует библиотека 'Boost.Atomic', которая также имеет' boost :: atomic_flag'. –

+0

Однако интерфейс atom_flag отличается: http://en.cppreference.com/w/cpp/atomic/atomic_flag -> вы не можете использовать сравнение и обмен, проверяйте и устанавливайте. – erenon

+0

re2: Зачем использовать Boost, если есть эквивалент STL? (Предполагая, что C++ 11) – erenon

3

Пример использования Boost.Atomic:

#include <boost/atomic.hpp> 

class SpinLock 
{ 
    boost::atomic_flag flag; // it differs from std::atomic_flag a bit - 
          // does not require ATOMIC_FLAG_INIT 
public: 
    void lock() 
    { 
     while(flag.test_and_set(boost::memory_order_acquire)) 
      ; 
    } 
    bool try_lock() 
    { 
     return !flag.test_and_set(boost::memory_order_acquire); 
    } 
    void unlock() 
    { 
     flag.clear(boost::memory_order_release); 
    } 
}; 

LIVE Demo on Coliru

#include <boost/range/algorithm.hpp> 
#include <boost/atomic.hpp> 
#include <boost/thread.hpp> 
#include <iostream> 
#include <vector> 

class SpinLock 
{ 
    boost::atomic_flag flag; 
public: 
    void lock() 
    { 
     while(flag.test_and_set(boost::memory_order_acquire)) 
      ; 
    } 
    bool try_lock() 
    { 
     return !flag.test_and_set(boost::memory_order_acquire); 
    } 
    void unlock() 
    { 
     flag.clear(boost::memory_order_release); 
    } 
}; 

int main() 
{ 
    using namespace std; using namespace boost; 

    SpinLock lock; 
    vector<thread> v; 
    for(auto i = 0; i!=4; ++i) 
     v.emplace_back([&lock, i] 
     { 
      for(auto j = 0; j!=16; ++j) 
      { 
       this_thread::yield(); 
       lock_guard<SpinLock> x(lock); 
       cout << "Hello from " << i << flush << "\tj = " << j << endl; 
      } 
     }); 
    for(auto &t: v) 
     t.join(); 
} 

Выход:

Hello from 0 j = 0 
Hello from 1 j = 0 
Hello from 3 j = 0 
Hello from 2 j = 0 
Hello from 3 j = 1 
Hello from 1 j = 1 
Hello from 3 j = 2 
Hello from 2 j = 1 
Hello from 1 j = 2 
Hello from 2 j = 2 
Hello from 1 j = 3 
Hello from 2 j = 3 
Hello from 1 j = 4 
Hello from 3 j = 3 
Hello from 2 j = 4 
Hello from 1 j = 5 
Hello from 2 j = 5 
Hello from 1 j = 6 
Hello from 2 j = 6 
Hello from 1 j = 7 
Hello from 2 j = 7 
Hello from 1 j = 8 
Hello from 2 j = 8 
Hello from 3 j = 4 
Hello from 2 j = 9 
Hello from 3 j = 5 
Hello from 1 j = 9 
Hello from 2 j = 10 
Hello from 1 j = 10 
Hello from 2 j = 11 
Hello from 3 j = 6 
Hello from 1 j = 11 
Hello from 2 j = 12 
Hello from 3 j = 7 
Hello from 1 j = 12 
Hello from 2 j = 13 
Hello from 3 j = 8 
Hello from 2 j = 14 
Hello from 3 j = 9 
Hello from 1 j = 13 
Hello from 2 j = 15 
Hello from 1 j = 14 
Hello from 3 j = 10 
Hello from 1 j = 15 
Hello from 3 j = 11 
Hello from 3 j = 12 
Hello from 3 j = 13 
Hello from 3 j = 14 
Hello from 3 j = 15 
Hello from 0 j = 1 
Hello from 0 j = 2 
Hello from 0 j = 3 
Hello from 0 j = 4 
Hello from 0 j = 5 
Hello from 0 j = 6 
Hello from 0 j = 7 
Hello from 0 j = 8 
Hello from 0 j = 9 
Hello from 0 j = 10 
Hello from 0 j = 11 
Hello from 0 j = 12 
Hello from 0 j = 13 
Hello from 0 j = 14 
Hello from 0 j = 15 
0
The spinlock solution provided by erenon sometimes generated crumble cout result. but the boost::mutext solution won't. So either the solution is incorrect, or my understanding of cout is wrong. 
#include <iostream> 
#include <thread> 
#include <atomic> 
#include <boost/thread/mutex.hpp> 
using namespace std; 

class spinlock { 
    private: 
     std::atomic<bool> lock_; 

    public: 
     spinlock() { 
      lock_.store(false); 
     } 

     void lock() { 
      bool unlocked = false; 
      while (!lock_.compare_exchange_weak(unlocked, true)); 

     } 

     void unlock() { 
      lock_.store(false); 
     } 
    }; 


class add_one 
{ 
    private: 
     std::string name_; 
     unsigned int& num_; 
     spinlock & lock_; 
     boost::mutex & mutex_; 
    public: 
    add_one(std::string name, unsigned int& num, spinlock &lock, boost::mutex &mutex) 
    :name_(name), 
    num_(num), 
    lock_(lock), 
    mutex_(mutex) 
    { 

    } 

    void add_and_display() 
    { 
     while(true) 
     { 
      lock_.lock(); 
      //boost::lock_guard<boost::mutex> g(mutex_); 
      std::cout << name_ << " " << num_ << endl; 
      if(num_ == 10000000) 
      { 

       return; 
      } 
      num_++; 
      lock_.unlock(); 

     } 
    } 
}; 

int main() 
{ 
    cout << "Hello World" << endl; 
    unsigned int n = 0; 
    spinlock lock; 
    boost::mutex mutex; 
    add_one one("t1", n ,lock, mutex); 
    add_one two("t2", n ,lock, mutex); 
    add_one three("t3", n ,lock, mutex); 
    //add_one four("t4", n ,lock, mutex); 
    std::thread t1(std::bind(&add_one::add_and_display, one)); 
    std::thread t2(std::bind(&add_one::add_and_display, two)); 
    std::thread t3(std::bind(&add_one::add_and_display, three)); 
    //std::thread t4(std::bind(&add_one::add_and_display, four)); 

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

    return 0; 
} 
Смежные вопросы