2015-02-15 3 views
2

Предположим, я хотел реализовать собственный std :: атомный тип (конечно, я не хочу, я только прошу из любопытства). Как реализовать метод загрузки? Мое предположение было бы что-то вроде следующего (m_mutex это мьютекс используется для блокировки операций и m_object объект, атомное в настоящее время проводит):Как можно реализовать std :: atomic :: load

T& load() { 
    std::lock_guard<std::mutex> lck(m_mutex); 

    return m_object; 
} 

Очевидно, что это не будет работать, потому что при вызове a.load().doSomething() призыв к doSomething не будет защищен, потому что m_object уже возвращается с load и не охраняется lock_guard.

Я хотел бы задать два вопроса:

  1. Как бы один реализовать правильную версию нагрузки?
  2. Что было бы простой техникой для реализации load не с мьютексом, а с блокировкой datastructure?
+1

Он будет использовать специальные инструкции и функции для конкретных целей и процессоров. –

+0

Вы имеете в виду встроенный код сборки при реализации std :: atomic? Просто очень упрощено, как это будет выглядеть? – user2683038

+0

Либо встроенная сборка, либо встроенные функции внутри компилятора. –

ответ

1

Как реализовать правильную версию нагрузки?

template <typename T> 
class atomic { 
public: 
    static_assert(std::is_trivially_copyable<T>(), 
       "atomic<T> requires trivially copyable T"); 

    // ... 

    // Ignores the memory ordering parameter and always provides 
    // sequential consistency. This is *correct*, but possibly 
    // sacrifices performance. 
    T load(std::memory_order) const noexcept { 
    std::lock_guard<std::mutex> guard{mtx_}; 
    return t_; 
    } 

private: 
    std::mutex mtx_; 
    T t_; 
}; 

Что бы простой метод, чтобы реализовать загрузку не с взаимной блокировкой, но с структурой данными безблокировочной?

Блокированные структуры данных в C++ реализованы без блокировки атомных объектов. Реализация объектов без блокировки объектов невозможна в рамках стандарта C++; им нужна поддержка от встроенных встроенных сборок компилятора и/или платформы, для выполнения операций с атомной памятью с надлежащими гарантиями порядка. Взгляните на реализацию std::atomic в стандартной библиотеке по вашему выбору для многих подробностей.

1

Очевидно, что это не будет работать, потому что при вызове a.load(). DoSomething() вызов DoSomething не будет защищен , потому что m_object он уже вернулся из нагрузки и не охранялся lock_guard любого Больше.

Это неизбежный побочный эффект этого интерфейса и не может быть изменен ни одной реализацией. Если вы хотите не только загрузить, но и защитить некоторые другие случайные функции, то это совершенно другой чайник.

Если вы думаете, что это безопасно с std::atomic, это не так.