Open Source & Linux Lab

It's better when it's simple

User Tools

Site Tools


projects:hpx:start

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
projects:hpx:start [2020/05/16 05:51] agaevprojects:hpx:start [2020/06/08 10:30] (current) agaev
Line 40: Line 40:
   static void retire( T * p )   static void retire( T * p )
  
-Disposer это шаблонный параметр, и на самом деле тип, а не объект.+Disposer это шаблонный параметр, и на самом деле тип, а не объект. В стандарте должен быть объектом, "Registers the expression ​reclaim(static_cast<T*>(this))​ to be evaluated asynchronously"
  
 +if на linux и membarrier
  
 ====== folly ====== ====== folly ======
Line 61: Line 62:
  
 Дополнительные вещи, не из стандарта: Дополнительные вещи, не из стандарта:
 +
 hazptr_array<N> для N hazptr-ов сразу, быстрее. hazptr_array<N> для N hazptr-ов сразу, быстрее.
 +
 hazptr_local<N> немного быстрее, но обязывает иметь ровно 1 активный hazptr_* на поток hazptr_local<N> немного быстрее, но обязывает иметь ровно 1 активный hazptr_* на поток
 +
 +====== p1121 (последний) ======
 + header <hazard_pointer>
 +
 + // ?.?, Class hazard_pointer_domain:
 + class hazard_pointer_domain;
 +
 + // ?.?, Default hazard_pointer_domain:
 + hazard_pointer_domain& hazard_pointer_default_domain() noexcept;
 +
 + // ?.?, For a set of hazard_pointer_obj_base objects O in ​domain​ for whichO.retire(reclaim, domain) has been called, ensures that O has been reclaimed.
 + void hazard_pointer_clean_up(    hazard_pointer_domain& domain = hazard_pointer_default_domain());
 +
 + // ?.?, Class template hazard_pointer_obj_base:
 + template <typename T, typename D = default_delete<T>>  class hazard_pointer_obj_base;4
 +
 + // ?.?, Class hazard_pointer
 + class hazard_pointer;
 +
 + // ?.?, Construct non-empty hazard_pointer
 + hazard_pointer make_hazard_pointer(    hazard_pointer_domain& domain = hazard_pointer_default_domain());
 +
 + // ?.?, Hazard pointer swap
 + void swap(hazard_pointer&, hazard_pointer&) noexcept;
 +
 + class hazard_pointer_domain { 
 +          public:  
 +          // ?.?.? constructor:  
 +          explicit hazard_pointer_domain(      std::pmr::polymorphic_allocator<byte> poly_alloc = {});
 +        ...
 +        }
 +        
 +        class hazard_pointer { 
 +        public:  
 + ...
 + bool empty() const noexcept;
 + template <typename T>    T* protect(const atomic<T*>& src) noexcept;
 + template <typename T>  bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
 + template <typename T>  void reset_protection(const T* ptr) noexcept;
 + void reset_protection(nullptr_t = nullptr) noexcept;
 + void swap(hazard_pointer&) noexcept;};
 +
 +
 +====== Аргумент против standard proposal(Hooks) ======
 +[[https://www.boost.org/doc/libs/1_54_0/doc/html/intrusive/usage.html|Boost.Intrusive]]
 +
 +В стандарте сейчас используется что-то похожее на base_hook
 +
 +В Boost.Intrusive говорится(И это и есть аргумент):
 + Sometimes an 'is-a' relationship between list hooks and the list value types is not desirable.
 + In this case, using a member hook as a data member instead of 'disturbing' the hierarchy might be the right way:
 +А потом ещё и
 + A programmer might find that base or member hooks are not flexible enough in some situations.
 + In some applications it would be optimal to put a hook deep inside a member of a class or just outside the class.
 + Boost.Intrusive has an easy option to allow such cases: function_hook. 
 +
 +===== Как можно исправить =====
 +
 +И кажется, что в стандарт можно записать эти три варианта сразу. То есть позволить программисту самому определять, как он хочет, чтобы указатель на его структуру преобразовывался в указатель на HP.
 +
 +Стандарт говорит, что "Наследуйся от hazptr_obj_base и приводиться будет к нему".
 +
 +Я могу предложить аналог member_hook: "Вставь в себя typedef на тот тип, к указателю на который ты будешь приводиться при помещении в массив HP"
 +
 +А аналог function_hook могу предложить такой:
 +
 +Boost.Intrusive:
 + //This functor converts between value_type and a hook_type
 +        struct Functor
 +        {
 +           //Required types
 +           typedef /*impl-defined*/      hook_type;
 +           typedef /*impl-defined*/      hook_ptr;
 +           typedef /*impl-defined*/      const_hook_ptr;
 +           typedef /*impl-defined*/      value_type;
 +           typedef /*impl-defined*/      pointer;
 +           typedef /*impl-defined*/      const_pointer;
 +           //Required static functions
 +           static hook_ptr to_hook_ptr (value_type &value);
 +           static const_hook_ptr to_hook_ptr(const value_type &value);
 +           static pointer to_value_ptr(hook_ptr n);
 +           static const_pointer to_value_ptr(const_hook_ptr n);
 +        };
 +
 +My version(hook -> hazptr):
 + //This functor converts between value_type and a hazptr_type
 +        struct Functor
 +        {
 +           //Required types
 +           typedef /*impl-defined*/      hazptr_type;
 +           typedef /*impl-defined*/      hazptr_ptr;
 +           typedef /*impl-defined*/      const_hazptr_ptr;
 +           typedef /*impl-defined*/      value_type;
 +           typedef /*impl-defined*/      pointer;
 +           typedef /*impl-defined*/      const_pointer;
 +           //Required static functions
 +           static hazptr_ptr to_hazptr_ptr (value_type &value);
 +           static const_hazptr_ptr to_hazptr_ptr(const value_type &value);
 +           static pointer to_value_ptr(hazptr_ptr n);
 +           static const_pointer to_value_ptr(const_hazptr_ptr n);
 +        };
 +
 +То есть с помощью Functor нужно будет самому задать, указатели на объекты какого типа нужно будет хранить в массиве HP.
 +
 +Кажется бесполезное преимущество, т.к. добавляет память : Более того, можно будет добавить данных в хуки(hazptr_obj_base), и тем самым влиять на структуру массива HP(сделать его Boost.Intrusive.list). Я не придумал ещё полезных применений(можно хранить timestamp, можно хранить указатель на функцию, которую вызывать при освобождении hp(для статистики мб))
 +
 +В массиве HP в libcds хранится каст к void*. В proposal'е каст к hazptr_obj_base*.
 +
 +Моя идея в том, чтобы как и в Boost.Intrusive, добавить к hazptr_domain или hazard_pointer::protect шаблонный параметр, указывающий на то, как получать hazptr_ptr из нашего класса
 +
 +===== Почему их hazptr_obj_base -- плохо? =====
 +
 +Как говорится в Boost.Intrusive: Sometimes an 'is-a' relationship between list hooks and the list value types is not desirable.
 +
 +Мои варианты: Множественное наследование от двух типов, каждый из которых наследуется от hazptr_obj_base
 +Function hook решает эту проблему.
 +
 +===== Альтернативные варианты ====
 +
 +Наша задача, по сути, научиться определять, защищен ли в текущий момент такой вот указатель(Тип его не знаем(void*), либо RTTI). То есть необходимо сравнить его с другими Hazard Pointers, и определить, равняются ли они, логически.
 +
 +В protect мы кладём какой-то указатель, в retire программист должен дать какой-то isDefendedBy(HP*), с помощью которого можно будет определить, защищен ли сейчас объект, который мы хотим удалить.
 +
 +Сейчас это isDefendedBy == isSame для libcds, и static_cast<hazptr_obj_base>::isSame() для folly и prorosals.
 +
 +Это позволит делать улучшенную логику. К примеру, когда, пытаясь удалить какой-то объект, мы должны убедиться, что никто не защищает его потомков(К примеру, удаляя узел дерево, мы должны убедиться, что дети и далее не защищены).
 +
 +====== Is HP obsolete? ======
 +
 +Hazard eras: http://concurrencyfreaks.blogspot.com/2017/05/hazard-eras-non-blocking-memory.html
 +
 +Wait free eras: https://rusnikola.github.io/files/wfe-ppopp20.pdf
projects/hpx/start.1589597501.txt.gz · Last modified: 2020/05/16 05:51 by agaev