1  /*
   2   * \brief  Utility for the manual placement of objects
   3   * \author Norman Feske
   4   * \date   2014-02-07
   5   */

   6  
   7  /*
   8   * Copyright (C) 2014 Genode Labs GmbH
   9   *
  10   * This file is part of the Genode OS framework, which is distributed
  11   * under the terms of the GNU General Public License version 2.
  12   */

  13  
  14  #ifndef _INCLUDE__UTIL__CONSTRUCT_AT_H_
  15  #define _INCLUDE__UTIL__CONSTRUCT_AT_H_
  16  
  17  #include <base/stdint.h>
  18  #include <base/printf.h>
  19  
  20  namespace Genode {
  21  
  22     template <typename T, typename... ARGS>
  23     static inline *construct_at(void *, ARGS &&...);

  24  }

  25  
  26  
  27  /**
  28   * Construct object of given type at a specific location
  29   *
  30   * \param T     object type
  31   * \param at    desired object location
  32   * \param args  list of arguments for the object constructor
  33   *
  34   * \return  typed object pointer
  35   *
  36   * We use move semantics (ARGS &&) because otherwise the compiler would create
  37   * a temporary copy of all arguments that have a reference type and use a
  38   * reference to this copy instead of the original within this function.
  39   *
  40   * There is a slight difference between the object that is constructed by this
  41   * function and a common object of the given type. If the destructor of the
  42   * given type or of any base of the given type is virtual, the vtable of the
  43   * returned object references an empty delete(void *) operator for that
  44   * destructor. However, this shouldn`t be a problem as an object constructed by
  45   * this function should never get destructed implicitely or through a delete
  46   * expression.
  47   */

  48  template <typename T, typename... ARGS>
  49  static inline * Genode::construct_at(void *at, ARGS &&... args)
  50  {
  51     /**
  52      * Utility to equip an existing type `T` with a placement new operator
  53      */

  54     struct Placeable : T
  55     {
  56        Placeable(ARGS &&... args) : T(args...) { }
  57  
  58        void * operator new (size_t, void *ptr) { return ptr; }
  59        void   operator delete (void *, void *) { }
  60  
  61        /**
  62         * Standard delete operator
  63         *
  64         * As we explicitely define one version of the delete operator, the
  65         * compiler won`t implicitely define any delete version for this class.
  66         * But if type T has a virtual destructor, the compiler implicitely
  67         * defines a `virtual ~Placeable()` which needs the following operator.
  68         */

  69        void  operator delete (void *)
  70        {
  71           PERR("cxx: Placeable::operator delete (void *) not supported.");
  72        }

  73     }
;

  74  
  75     /*
  76      * If the args input to this function contains rvalues, the compiler would
  77      * use the according rvalue references as lvalues at the following call if
  78      * we don`t cast them back to rvalue references explicitely. We can not use
  79      * lvalues here because the compiler can not bind them to rvalue references
  80      * as expected by Placeable.
  81      */

  82     return new (at) Placeable(static_cast<ARGS &&>(args)...);

  83  }

  84  
  85  #endif /* _INCLUDE__UTIL__CONSTRUCT_AT_H_ */