【问题标题】:C++11 Atomics. Why does this compile, but not link?C++11 原子。为什么这个编译,但没有链接?
【发布时间】:2011-09-18 19:17:34
【问题描述】:

我正在尝试编写一个多生产者、多消费者队列。 我在 Arch Linux 上使用 G++ 4.6,它也在 G++ 4.7 上中断。

#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

我不确定为什么会发生这种情况,但这似乎表明我需要链接到某些东西。 关于我哪里出错的任何想法?任何指针都非常感谢。

【问题讨论】:

  • 在 Ubuntu Natty 64bit gcc 4.6.1 上确认; Debian Sid 32 位 gcc 4.6.1
  • 我也是! g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 / Ubuntu 12.04.1 LTS x86_64

标签: c++ linker g++ c++11


【解决方案1】:

因为 std::atomic 只存在于某些 Ts,主要是数字类型。

【讨论】:

  • 太棒了,谢谢!当我使用 atomic 而不是枚举时,代码成功链接。我想我需要等待实现来支持其他数据类型?
  • 是的,但它也不会支持所有数据类型,29.5 指定了一些要求,例如 T 可以轻松复制。
  • @Reuben :在这种情况下,我认为它不起作用的唯一原因是因为您的枚举未命名(这会改变它的链接)。尝试将typedef enum { ... } state_t; 更改为enum state_t { ... };
  • 等等,不应该使用基于互斥锁的实现来生成 atomic 的通用实现,以用于类型太大或其他什么的吗?
猜你喜欢
  • 1970-01-01
  • 2012-04-20
  • 2015-08-21
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
相关资源
最近更新 更多