Skip to content

File lockfree_address_marker.hpp

File List > base > lockfree_address_marker.hpp

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

//
// lock-free address marker
//

#ifndef _LOCKFREE_ADDRESS_MARKER_HPP_
#define _LOCKFREE_ADDRESS_MARKER_HPP_

#include <atomic>
#include <cstdint>

namespace lockfree
{
  template <class T>
  class address_marker
  {
    private:
      using convert_type = std::uint64_t;
      static const convert_type MARK = 0x1;

      static convert_type to_cnv_type (T *addr);
      static T *to_addr (convert_type ct);

    public:
      address_marker ();
      address_marker (T *addr);

      bool is_marked () const;
      T *get_address () const;
      T *get_address_no_strip () const;

      static T *set_adress_mark (T *addr);
      static T *strip_address_mark (T *addr);
      static bool is_address_marked (T *addr);

      static T *atomic_strip_address_mark (T *addr);

    private:
      static bool is_ct_marked (convert_type ct);
      static convert_type set_ct_mark (convert_type ct);
      static convert_type strip_ct_mark (convert_type ct);

      std::atomic<T *> m_addr;
  };
} // namespace lockfree

//
// implementation
//

namespace lockfree
{
  //
  // address marker
  //
  template <class T>
  address_marker<T>::address_marker ()
    : m_addr { NULL }
  {
  }

  template <class T>
  address_marker<T>::address_marker (T *addr)
    : m_addr (addr)
  {
  }

  template <class T>
  typename address_marker<T>::convert_type
  address_marker<T>::to_cnv_type (T *addr)
  {
    return (convert_type) addr;
  }

  template <class T>
  T *
  address_marker<T>::to_addr (convert_type ct)
  {
    return (T *) ct;
  }

  template <class T>
  bool
  address_marker<T>::is_marked () const
  {
    return is_address_marked (m_addr.load ());
  }

  template <class T>
  T *
  address_marker<T>::get_address () const
  {
    return strip_address_mark (m_addr.load ());
  }

  template <class T>
  T *
  address_marker<T>::get_address_no_strip () const
  {
    return m_addr.load ();
  }

  template <class T>
  bool
  address_marker<T>::is_ct_marked (convert_type ct)
  {
    return (ct & MARK) != 0;
  }

  template <class T>
  typename address_marker<T>::convert_type
  address_marker<T>::set_ct_mark (convert_type ct)
  {
    return (ct | MARK);
  }

  template <class T>
  typename address_marker<T>::convert_type
  address_marker<T>::strip_ct_mark (convert_type ct)
  {
    return (ct & (~MARK));
  }

  template <class T>
  T *
  address_marker<T>::set_adress_mark (T *addr)
  {
    return to_addr (set_ct_mark (to_cnv_type (addr)));
  }

  template <class T>
  T *
  address_marker<T>::strip_address_mark (T *addr)
  {
    return to_addr (strip_ct_mark (to_cnv_type (addr)));
  }

  template <class T>
  bool
  address_marker<T>::is_address_marked (T *addr)
  {
    return is_ct_marked (to_cnv_type (addr));
  }

  template <class T>
  T *
  address_marker<T>::atomic_strip_address_mark (T *addr)
  {
    return address_marker (addr).get_address ();
  }
} // namespace lockfree
#endif // !_LOCKFREE_ADDRESS_MARKER_HPP_