2011-09-18 7 views
7

私はマルチプロデューサ、マルチコンシューマキューを作成しようとしています。 私はG ++ 4.6をArch Linuxで使用していますが、G ++ 4.7でも動作します。C++ 11 Atomics。なぜこれはコンパイルされますが、リンクされませんか?

#include <atomic> 
#include <condition_variable> 
#include <memory> 
#include <mutex> 
#include <vector> 
#include <iostream> 
#include <string> 
#include <sstream> 

template <typename T> class concurrent_queue 
{ 
    public: 
    concurrent_queue(size_t n) : items(n), item_states(n), producer_index(0), consumer_index(0) { 
    } 
    virtual ~concurrent_queue() { 
    } 
    T * consume() { 
    auto index = consumer_index; 
    T * item = nullptr; 
    state_t state = USED; 

    // Extract item and block location. 
    while (!item_states[index].compare_exchange_strong(state, BLOCKED, std::memory_order_acquire, std::memory_order_acquire)) { 
     // Wait for an item to become available 
     std::unique_lock<std::mutex> lock(item_mutex); 
     has_items.wait(lock); 

     // Move to the newly available item (might already have been taken by another consumer). 
     index = consumer_index; 
    } 

    // Tell consumers to move to next location, wrap to beginning of circular buffer if necessary. 
    ++consumer_index; 
    consumer_index %= items.size(); 

    // Unblock index so that producers can write to it. 
    items[index] = nullptr; 
    return item; 
    } 
    void produce(T * value) { 
    items[producer_index] = value; 
    ++producer_index; 
    producer_index %= items.size(); 
    has_items.notify_one(); 
    } 
private: 
    typedef enum { 
    EMPTY, 
    USED, 
    BLOCKED 
    } state_t; 

    // Used as a buffer of items 
    std::vector<T* > items; 
    std::vector<std::atomic<state_t> > item_states; 
    size_t producer_index; 
    size_t consumer_index; 
    std::mutex item_mutex; 
    std::condition_variable has_items; 
}; 

// Test code 
using namespace std; 

template <typename T> void pop_n_print(concurrent_queue<T> & queue) { 
    stringstream message; 
    message << "popped " << *queue.consume() << endl; 
    cout << message.str(); 
} 

int main() 
{ 
    concurrent_queue<int> ints(5); 
    ints.produce(new int(1)); 
    ints.produce(new int(2)); 

    pop_n_print(ints); 
    pop_n_print(ints); 

    return 0; 
} 

私はg++ --std=c++0x queue.cc -o test_queueでこのコードをコンパイルし、私は、このエラーメッセージが表示されます:

/tmp/ccqCjADk.o: In function `concurrent_queue<int>::consume()': 
queue.cc:(.text._ZN16concurrent_queueIiE7consumeEv[concurrent_queue<int>::consume()]+0x9f): undefined reference to `std::atomic<concurrent_queue<int>::state_t>::compare_exchange_strong(concurrent_queue<int>::state_t&, concurrent_queue<int>::state_t, std::memory_order, std::memory_order)' 
collect2: ld returned 1 exit status 

私はなぜこれが起こっているわからないんだけど、私が何かに対してリンクする必要があることを示唆しているようです。 私はどこに間違っているのでしょうか?どんな指針も大変ありがとうございます。

+0

Ubuntu Natty 64bit gcc 4.6.1で確認済み。 Debian Sid 32bit gcc 4.6.1 – sehe

+0

私も! g ++(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3/Ubuntu 12.04.1 LTS x86_64 – nodakai

+0

4.7で修正http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49445 – nodakai

答えて

10

std :: atomicは特定のTs(主に数値型)にのみ存在するためです。

+0

素晴らしい、ありがとう!列挙型の代わりに原子番号を使用すると、コードは正常にリンクします。私は実装が他のデータ型をサポートするのを待つ必要があると思いますか? –

+0

ええ、それはすべてのデータ型にも対応していません。29.5では、Tが簡単にコピー可能なようないくつかの要件を指定しています。 – PlasmaHH

+1

@Reuben:この場合、動作しない唯一の理由は、enumの名前が付けられていない(リンケージが変更されている)ためです。 'typedef enum {...} state_t;'を 'enum state_t {...}'に変更してみてください。 – ildjarn

関連する問題