2016-07-19 53 views
0

我想在C++ 11中實現計數信號量。這是我的審判......在C++中使用condition_variable實現信號量11

#include <iostream> 
#include <thread> 
#include <mutex> 
#include <future> 
#include <vector> 
using namespace std; 

class Semaphore{ 
private: 
    int count; 
    condition_variable cv; 
    mutex mtx; 

public: 

    Semaphore(int count_):count(count_){} 
    void take(){ 
    unique_lock<mutex> lck(mtx); 
    while(count == 0) 
     cv.wait(lck); 
    count--; 
    cout << "Take\n"; 
    } 
    void release(){ 
    unique_lock<mutex> lck(mtx); 
    count++; 
    cout << "Release\n"; 
    cv.notify_one(); 
    } 

}; 
int main() { 
    Semaphore sem(5); 

    vector<thread> threads; 
    for(int i = 0; i < 10; i++){ 
    threads.push_back(thread(&Semaphore::release, sem)); 
    } 
    for(int i = 0; i < 10; i++){ 
    threads.push_back(thread(&Semaphore::release, sem)); 
    } 
    for(int i = 0; i < threads.size(); i++) 
     threads[i].join(); 
    return 0; 

} 

然而,編譯時,它與下面的錯誤而失敗......

note: 'Semaphore::Semaphore(Semaphore&&)' is implicitly deleted because the default definition would be ill-formed: 
    class Semaphore{ 

我最好的猜測是,這是因爲使用condition_variable類裏面的,它既不可複製也不可移動,因此當它作爲參數傳遞給std :: thread時會引發問題。但是,我不知道如何解決這個問題。任何線索?

更新: 這是完全錯誤日誌...

In file included from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/functional:55:0, 
       from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/thread:39, 
       from /Users/emostafa/Desktop/cpp/A.cpp:2: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple: In instantiation of 'constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = Semaphore; long unsigned int _Idx = 1ul; _Head = Semaphore]': 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:369:49: required from 'constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head>&&) [with long unsigned int _Idx = 1ul; _Head = Semaphore]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:1162:12: required from 'struct std::__is_nt_constructible_impl<std::_Tuple_impl<1ul, Semaphore>, std::_Tuple_impl<1ul, Semaphore>&&>' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:137:12: required from 'struct std::__and_<std::is_constructible<std::_Tuple_impl<1ul, Semaphore>, std::_Tuple_impl<1ul, Semaphore>&&>, std::__is_nt_constructible_impl<std::_Tuple_impl<1ul, Semaphore>, std::_Tuple_impl<1ul, Semaphore>&&> >' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:1174:12: required from 'struct std::is_nothrow_constructible<std::_Tuple_impl<1ul, Semaphore>, std::_Tuple_impl<1ul, Semaphore>&&>' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:1205:12: required from 'struct std::__is_nothrow_move_constructible_impl<std::_Tuple_impl<1ul, Semaphore>, true>' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:1211:12: required from 'struct std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, Semaphore> >' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/type_traits:137:12: required from 'struct std::__and_<std::is_nothrow_move_constructible<std::_Mem_fn<void (Semaphore::*)()> >, std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, Semaphore> > >' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:218:7: required from 'constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 0ul; _Head = std::_Mem_fn<void (Semaphore::*)()>; _Tail = {Semaphore}]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/functional:1559:41: required from 'typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (Semaphore::*)(); _Args = {Semaphore&}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<std::_Mem_fn<void (Semaphore::*)()>(Semaphore)>]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/thread:142:59: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Semaphore::*)(); _Args = {Semaphore&}]' 
/Users/emostafa/Desktop/cpp/A.cpp:37:54: required from here 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:115:42: error: use of deleted function 'Semaphore::Semaphore(Semaphore&&)' 
    : _M_head_impl(std::forward<_UHead>(__h)) { } 
             ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: note: 'Semaphore::Semaphore(Semaphore&&)' is implicitly deleted because the default definition would be ill-formed: 
class Semaphore{ 
    ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: error: use of deleted function 'std::condition_variable::condition_variable(const std::condition_variable&)' 
In file included from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/future:41:0, 
       from /Users/emostafa/Desktop/cpp/A.cpp:4: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/condition_variable:81:5: note: declared here 
    condition_variable(const condition_variable&) = delete; 
    ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: error: use of deleted function 'std::mutex::mutex(const std::mutex&)' 
class Semaphore{ 
    ^
In file included from /Users/emostafa/Desktop/cpp/A.cpp:3:0: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/mutex:129:5: note: declared here 
    mutex(const mutex&) = delete; 
    ^
In file included from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/functional:55:0, 
       from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/thread:39, 
       from /Users/emostafa/Desktop/cpp/A.cpp:2: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple: In instantiation of 'constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with long unsigned int _Idx = 1ul; _Head = Semaphore]': 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:357:21: required from 'constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const _Head&) [with long unsigned int _Idx = 1ul; _Head = Semaphore]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:206:44: required from 'constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 0ul; _Head = std::_Mem_fn<void (Semaphore::*)()>; _Tail = {Semaphore}]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:606:30: required from 'constexpr std::tuple<_T1, _T2>::tuple(const _T1&, const _T2&) [with _T1 = std::_Mem_fn<void (Semaphore::*)()>; _T2 = Semaphore]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/functional:1510:72: required from 'std::_Bind_simple<_Callable(_Args ...)>::_Bind_simple(_Tp&&, _Up&& ...) [with _Tp = std::_Mem_fn<void (Semaphore::*)()>; _Up = {Semaphore&}; _Callable = std::_Mem_fn<void (Semaphore::*)()>; _Args = {Semaphore}]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/functional:1559:41: required from 'typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (Semaphore::*)(); _Args = {Semaphore&}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<std::_Mem_fn<void (Semaphore::*)()>(Semaphore)>]' 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/thread:142:59: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Semaphore::*)(); _Args = {Semaphore&}]' 
/Users/emostafa/Desktop/cpp/A.cpp:37:54: required from here 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/tuple:108:25: error: use of deleted function 'Semaphore::Semaphore(const Semaphore&)' 
     : _M_head_impl(__h) { } 
         ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: note: 'Semaphore::Semaphore(const Semaphore&)' is implicitly deleted because the default definition would be ill-formed: 
class Semaphore{ 
    ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: error: use of deleted function 'std::condition_variable::condition_variable(const std::condition_variable&)' 
In file included from /usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/future:41:0, 
       from /Users/emostafa/Desktop/cpp/A.cpp:4: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/condition_variable:81:5: note: declared here 
    condition_variable(const condition_variable&) = delete; 
    ^
/Users/emostafa/Desktop/cpp/A.cpp:9:7: error: use of deleted function 'std::mutex::mutex(const std::mutex&)' 
class Semaphore{ 
    ^
In file included from /Users/emostafa/Desktop/cpp/A.cpp:3:0: 
/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/mutex:129:5: note: declared here 
    mutex(const mutex&) = delete; 
+0

'Semaphore(Semaphore &&)= delete;' –

+1

對不起,我的壞。這只是告訴我,它被隱式刪除。實際的錯誤是我試圖在刪除時使用它。錯誤說「錯誤:使用已刪除的功能...」。所以顯式刪除構造函數會產生相同的錯誤。 –

+2

嘗試'threads.push_back(thread(&Semaphore :: release,std :: ref(sem)));'你想通過引用將'sem'傳遞給線程,但是'std :: thread'通常會嘗試複製它的價值。 –

回答

0

你傳遞sem對象作爲thread構造。這就要求它被複制,這就是「使用已刪除的函數」所指的內容。

如果你想要一個線程,任務,異步上下文......來引用你的信號量,可以通過std::ref(sem)來傳遞它,或者回退到普通的舊指針並傳遞它的地址:&sem

+0

非常感謝!這工作!我記得我之前嘗試過,但由於另一個bug,它失敗了,所以我認爲std :: ref不是問題,但現在嘗試它後,它的工作原理:) –