    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Pooled Lists</title>
        <link>https://members.accu.org/index.php/journals/1308</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #76 - Dec 2006 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c207/">76</a>
                    (5)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c207-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c207+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Pooled Lists</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 10 December 2006 09:43:00 +00:00 or Sun, 10 December 2006 09:43:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Christopher Baus explains the advantages of using a pooled memory allocation strategy for high performance applications.</p>
<p><strong>Body:</strong>&nbsp;<p>By default, the C++ <tt class="code">list</tt> container allocates memory with the global operator <tt class="code">new</tt> when elements are added to the list, and frees memory with the global operator <tt class="code">delete</tt> when elements are removed. While this provides a convenient interface for most applications, high performance and long lived applications could benefit from a pooled memory allocation strategy, where all memory used by the list is preallocated at list creation time.
  </p><p>
    Most default implementations of the operators <tt class="code">new</tt> and <tt class="code">delete</tt> resolve to a direct call to the underlying system heap. This has the following drawbacks:
  </p>
        <ul><li>
    List insertion operations may throw indeterminately.
  </li><li>
    System heap operations create contention between otherwise unrelated threads.
  </li><li>
    System heap operations require an often expensive system call.
  </li><li>
    Frequent allocations and deallocations of small objects can result in fragmentation, and inefficient use of memory.
  </li></ul><p>
    Kevlin Henney [<a href="#Henney">Henney</a>] says this regarding collection memory management:
  </p>
        <p><span class="quote">
    If you are serious about managing the allocation of a container, then get serious and manage it: Write your own container type.
  </span></p><p>
    The standard <tt class="code">list</tt> allocator interface is the logical starting point for implementing a pooled list container, but as Pablo Halpern noted in his proposal to the C++ standards committee [<a href="#Halpern2005">Halpern, 2005</a>], there some inconsistencies in the standard. The handling of allocators which compare unequal is currently under specified in C++, as is noted in issue 431 of the C++ Standard Library Active Issues List [<a href="#C++ActiveIssues">C++ Active Issues</a>]. While Howard E. Hinnant [<a href="#Hinnant">Hinnant</a>] provides guidance for a solution, it currently is not part of the standard library. Instances of pool allocators of the same type compare unequally when they allocate from different memory pools, hence it isn't possible to implement satisfactory pooled allocators given the current standard. This leaves Kevlin's suggestion to implement a custom container.
  </p><p>
    This article investigates implementing a pooled list container using the C++ standard <tt class="code">list</tt> as the underlying data store. The objective is to provide pooling whilst delegating most functionality to the standard library.
  </p><h2>
    The Interface
  </h2><p>
    The <tt class="code">pooled_list</tt> class provides a simple and familiar interface to C++ developers. With a few exceptions, <tt class="code">pooled_list</tt>s behave similarly to standard <tt class="code">list</tt>s. When using <tt class="code">pooled_list</tt>, the user must first create a <tt class="code">pool</tt> as follows:
  </p><pre class="programlisting">
 size_t pool_size = 256;
 pooled_list&lt;int&gt;::pool list_pool(pool_size);
    </pre><p>
    The <tt class="code">pool</tt> allocates memory for both the element data and the <tt class="code">list</tt>'s internal structure. No additional allocations will be made after the <tt class="code">list_pool</tt> has been constructed.
  </p><p>
    One or more <tt class="code">list</tt>s are attached to the pool:
  </p><pre class="programlisting">
 pooled_list&lt;int&gt; my_list(list_pool);
    </pre><p>
    The user can then operate on the <tt class="code">list</tt> just as a standard <tt class="code">list</tt>. For instance:
  </p><pre class="programlisting">
 my_list.push_back(5);
 my_list.pop_front();
    </pre><h2>
    Exceptions and error handling
  </h2><p>
    Using the standard <tt class="code">list</tt> container <tt class="code">insert</tt> operations can fail unpredictably. If memory is not available to complete the operation they will throw <tt class="code">std::bad_alloc</tt>. In comparison, the <tt class="code">pooled_list</tt> container provides deterministic failure. <tt class="code">Insert</tt> operations only throw on a <tt class="code">pooled_list</tt> with a depleted <tt class="code">pool</tt>. Since the <tt class="code">pooled_list</tt> takes a reference to a <tt class="code">pool</tt>, pools must have a lifetime greater than all the lists from which they are created. If a <tt class="code">pool</tt> is destroyed before the lists which are created from it, the behaviour is undefined.
  </p><p>
    Since memory is allocated from the C++ runtime heap to create <tt class="code">pool</tt>s, <tt class="code">pool</tt> construction may throw <tt class="code">std::bad_alloc</tt>.
  </p><p>
    The semantics of operations which act upon multiple lists are affected by pooling. The operations including the overloading of <tt class="code">merge()</tt> and <tt class="code">splice()</tt> require that <tt class="code">pooled_list</tt>s are allocated from the same pool. The condition is checked with an <tt class="code">assert</tt> and violation results in undefined behaviour. These semantics are borrowed directly from Howard E. Hinnant's recommendation for swapping containers with unequal allocators [<a href="#Hinnant">Hinnant</a>].
  </p><p>
    To provide the strong exception guarantee, the assignment operator is implemented by creating a temporary copy of the right hand list, and then swapping the temporary with the left hand list. The pools of the left hand side and right hand side are also swapped (again as recommended by Hinnant). This requires that the right hand side list's pool contains at least as many free elements as are used by the right hand side list, even though fewer elements maybe required upon completion of the operation.
  </p><p>
    In explicit terms, the assignment operation involves three lists: the list being assigned from (<tt class="code">right</tt>), the initial list being assigned to (<tt class="code">left</tt>), and the final state of the list being assigned to (<tt class="code">left'</tt>). Following the operation both <tt class="code">left'</tt> and <tt class="code">right</tt> will use the same <tt class="code">pool</tt>, even if <tt class="code">left</tt> has used a different <tt class="code">pool</tt>. All elements will be allocated from the <tt class="code">pool</tt> used by <tt class="code">right</tt>. The assignment operator, again, to provide the strong exception guarantee, creates <tt class="code">left'</tt> (as a copy of <tt class="code">right</tt>) before <tt class="code">left</tt> is destroyed. For the operation to succeed, the <tt class="code">pool</tt> used by <tt class="code">right</tt> must contain at least the number of elements in <tt class="code">right</tt>. When <tt class="code">right</tt> contains more elements than <tt class="code">left</tt>, and uses the same <tt class="code">pool</tt> as <tt class="code">left</tt>, it is not sufficient for the <tt class="code">pool</tt> used by <tt class="code">right</tt> to contain <tt class="code">right</tt> minus <tt class="code">left</tt> number of elements, even though that number of elements will be used (in conjunction by <tt class="code">left'</tt> and <tt class="code">right</tt>) after the operation completes.
  </p><h2>
    Concurrency
  </h2><p>
    The global heap is a resource which is shared among all threads, and access to the heap is often serialized by the underlying operating system to prevent corruption. Microsoft [<a href="#Microsoft">Microsoft</a>] describes the problem and offers the following with respect to Windows:
  </p>
        <p><span class="quote">
    A single global lock protects the heap against multi threaded usage... This lock is essential to protecting the heap data structures from random access across multiple threads. This lock can have an adverse impact on performance when heap operations are too frequent.
  </span></p>
        <p><span class="quote">
    In all the server systems (such as IIS, MSProxy, DatabaseStacks, Network servers, Exchange, and others), the heap lock is a BIG bottleneck. The larger the number of processors, the worse the contention.
  </span></p><p>
    Heap access causes contention between threads which would otherwise be unrelated. The standard <tt class="code">lists insert()</tt> and <tt class="code">erase()</tt> operations require heap access, and hence can cause contention. Consider the following example: a program contains two threads in which each thread creates a <tt class="code">list</tt> which is only accessed by that thread. While it is safe for either thread to <tt class="code">insert</tt> or <tt class="code">erase</tt> elements from its respective list, access to the heap is serialized by those operations. The result is reduced performance even though there is no data shared between the threads. A <tt class="code">pooled_list</tt> does not access the heap directly after the pool is created, so there is no contention between lists.
  </p><p>
    Like the STL, the <tt class="code">pooled_list</tt> class makes few guarantees about thread safety. There is no thread synchronization in the <tt class="code">pooled_list</tt> class, hence multiple threads can not concurrently <tt class="code">insert</tt> or <tt class="code">erase</tt> elements in lists which share the same pool. This requires that users externally synchronize list operations when one or more lists which use the same pool are accessed from multiple threads. If <tt class="code">pooled_list</tt>s do not share pools, there is no need to synchronize access to <tt class="code">pooled_list</tt>s.
  </p><h2>
    The implementation
  </h2><p>
    Linked lists impose storage overhead beyond contiguous arrays due to their node structure. Typically a <tt class="code">list</tt> node holds pointers to the next node in the <tt class="code">list</tt> and the previous node in the <tt class="code">list</tt>. A <tt class="code">list</tt> node could be defined as shown in Listing 1.
  </p>
<p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 template&lt;typename T&gt;
 struct node {
   node(T initial_value):element_(initial_value){}
   node* next_;
   node* previous_;
   T element_;
 }</pre>
 </td></tr>
 <tr><td class="title">Listing 1</td></tr>
 </table>
 </p>
<p>
    List allocation requires not only memory for the element data, but the <tt class="code">list</tt> node structure as well. This is why the specification requires that allocators provide a <tt class="code">rebind() </tt>[<a href="#Rebind">Rebind</a>]  implementation, which allows them to allocate node types. Providing allocators that only return elements of type <tt class="code">T</tt> is insufficient. In classical C linked list implementations, such as the one provided by the Linux kernel [<a href="#LinkedList">LinkedList</a>], the user provides user allocated nodes at insertion time. With the C++ standard <tt class="code">list</tt>, nodes are abstracted from the user.
  </p><p>
    The goal of the <tt class="code">pooled_list</tt> implementation was to preallocate not only element data, but the node data, and hence all the memory used by the <tt class="code">list</tt>. This can be achieved by implementing the <tt class="code">list</tt> from scratch - creating new node types and implementing all the <tt class="code">list</tt> operations. For the sake of expediency and correctness, I chose a hybrid approach which uses the standard <tt class="code">list</tt> itself as the underlying structure for the <tt class="code">pooled_list</tt>.
  </p><p>
    The <tt class="code">pooled_list</tt> implementation uses two standard lists: the free and active lists. When created, the free list contains &lt;sup class=&quot;footnoteref&quot;&gt;n</sup> number of elements and the active list is empty. When elements are inserted, the required nodes are moved from the free list to the active list. When elements are erased, the released nodes are moved from the active list to the free list. This is accomplished with the standard list's <tt class="code">splice()</tt> operation, which allows lists to be combined in constant time without memory allocation. While this is a rudimentary implementation, it does offer some challenges in correctly providing value semantics.
  </p><h2>
    A naive implementation
  </h2><p>
    The structure of my first attempted implementation was similar to Listing 2.
  </p>
<p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 template&lt;typename T&gt;
 class pooled_list
 {
   ...
 private:
 std::list&lt;T&gt; free_list_;
 std::list&lt;T&gt; active_list_;
 };
 </pre>
 </td></tr>
 <tr><td class="title">Listing 2</td></tr>
 </table>
 </p>
  <p>
    While it will work for built-in types and PODs [<a href="#POD">POD</a>], it results in the constructors for objects being called when the free <tt class="code">list</tt> is created, not when elements are inserted. Likewise, destructors for the elements are called when the free <tt class="code">list</tt> is deleted and not when elements are erased. To solve this problem the underlying lists must contain unstructured data, which leads to the next attempt, Listing 3.
  </p>
<p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 template&lt;typename T&gt;
 class pooled_list
 {
 ...
      iterator insert(iterator pos, const T&amp; value)
      {
         if(!free_list_-&gt;empty()){
           // use inplace new on the raw data
           // and splice from the free list to
           // the active list
           ...
        }
         else{
           throw std::bad_alloc();
         }
         return --pos;
       }
 ...
 private:

 std::list&lt;char[sizeof(T)]&gt; free_list_;
 std::list&lt;char[sizeof(T)]&gt; active_list_;
 }; </pre>
 </td></tr>
 <tr><td class="title">Listing 3</td></tr>
 </table>
</p>
  <p>
    By using standard lists of arrays of <tt class="code">char</tt> the construction/destruction of elements can be constrained to <tt class="code">insert</tt> and <tt class="code">erase</tt> operations, properly implementing value semantics. Unfortunately this leads to some subtle alignment problems. Internally to the standard <tt class="code">list</tt>, the <tt class="code">char</tt><tt class="code">array</tt> is a member of the node, as shown in the node code example in Listing 3, and C++ does not guarantee all types T will be properly aligned. Stephen Cleary [<a href="#Cleary">Cleary</a>] provides further discussion of alignment in his documentation for the boost <tt class="code">pool</tt> library.
  </p><p>
    Lists of type <tt class="code">std::list&lt;char*&gt;</tt> are used by the final implementation which is based on the following from Cleary's discussion:
  </p>
        <p><span class="quote">
    Any block of memory allocated as an array of characters through operator </span></p><p>
    For an example, see Listing 4.
  </p>
<p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 template&lt;typename T&gt;
 class pooled_list
 {
 ...
     pooled_list():free_pool_(pool_size, 0)
     {
       std::list&lt;char*&gt;::iterator cur;
       std::list&lt;char*&gt;::iterator end
         = free_list_.end();
       for(cur = free_list_.begin(); cur != end;
          ++cur){
          *cur = new char[sizeof(T)];
       }
     }
 ...
      iterator insert(iterator pos, const T&amp; value)
      {
         if(!free_list_-&gt;empty()){
           // use inplace new on the raw data,
           // and splice from the free list to the
           // active list
           ...
         }
         else{
           throw std::bad_alloc();
         }
         return --pos;
       }
 ...
 private:

 std::list&lt;char*&gt; free_list_;
 std::list&lt;char*&gt; active_list_;
 };
 </pre>
 </td></tr>
 <tr><td class="title">Listing 4</td></tr>
 </table>
 </p>
  <p>
    The final implementation differs slightly in that the <tt class="code">free_list_</tt> is moved to&lt;sup class=&quot;footnoteref&quot;&gt; </sup>a separate pool class which allows it to be shared by multiple <tt class="code">pooled_list</tt>s. The alignment workaround does impose one pointer's worth of space overhead per element for each node used in free and active lists. This could be avoided by developing a custom <tt class="code">list</tt> rather than using the standard <tt class="code">list</tt> as a base implementation.
  </p><h2>
    List iterators
  </h2><p>
    Since the underlying list is of type <tt class="code">std::list&lt;char*&gt;</tt> and not <tt class="code">std::list&lt;T&gt;</tt>, iterators to the active list can not be used directly. The data must be dereferenced and cast to the type <tt class="code">T</tt>. The boost iterator library is employed to perform the operation. This greatly simplifies the implementation at the cost of a dependency on the boost iterator library (see Listing 5).
  </p>
<p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 template&lt;typename T&gt;
 class pooled_list
 {
 ...

 // Functor to convert iterator to underlying data type to type T.
 class reinterpret_raw_data_ptr
 {
 public:
   typedef T&amp; result_type;
   T&amp; operator()(raw_data_type&amp; raw_data) const
   {
     return *reinterpret_cast&lt;T*&gt;(raw_data);
   }
 };

 typedef char* raw_data_type;
 typedef std::list&lt;raw_data_type&gt; raw_data_ptr_list;
 typedef typename std::list&lt;raw_data_type&gt;::iterator raw_data_ptr_list_it;
 typedef boost::transform_iterator&lt;reinterpret_raw_data_ptr, typename raw_data_ptr_list::iterator,
    T&amp;, T &gt; iterator;
 ...
 };
 </pre>
 </td></tr>
 <tr><td class="title">Listing 5</td></tr>
 </table>
 </p>
  <h2>
    Potential enhancements
  </h2><p>
    As noted in the threading section, multiple threads can not concurrently <tt class="code">insert</tt> or <tt class="code">erase</tt> elements in lists which share the same <tt class="code">pool</tt>. I chose to not impose the overhead of thread synchronization by default. I do not recommend sharing <tt class="code">pool</tt>s across threads, but this could be supported by adding a synchronization policy to the <tt class="code">pool</tt> with no additional overhead for the default case.
  </p><p>
    Element data is allocated by the pool using <tt class="code">new[]</tt>. This might not be sufficient for all use cases (for instance if the user wants to allocate elements from an arena or global <tt class="code">pool</tt>). This could be also be addressed by adding an allocation strategy to the <tt class="code">pool</tt>. It should be noted that because the standard <tt class="code">list</tt> is used as the underlying data structure, it would be difficult to change the allocation strategy of the node structures. Providing an alternate strategy to allocate <tt class="code">list</tt> nodes would require a reimplementation of the <tt class="code">list</tt> structure.
  </p><h2>
    Conclusion
  </h2><p>
    The C++ library specification currently requires developing custom containers to implement allocators with shared state. While it might be possible to develop <tt class="code">pool</tt> allocators which work with existing standard library implementations, it is not be possible to guarantee that the <tt class="code">pool</tt> allocators would work correctly across library implementations. As Kevlin says, if you are serious about memory management, you must rely on custom containers. Pool allocation is a proven strategy for many long lived, concurrent applications with high reliability and performance requirements such as network servers. The provided implementation provides a simple solution which successfully leverages the standard library for most operations. The result is a pooled list container that is compatible with any standard compliant standard library implementation.</p><h2>
    Acknowledgements
  </h2><p>
    Thanks to C++ guru Thomas Becker for discussion on data alignment and help with <tt class="code">const_iterator</tt> syntax.
  </p><h2>
    References
  </h2><p class="bibliomixed">
    [<a name="C++ActiveIssues">C++ Active Issues</a>] Issue 431,  C++ Standard Library Active Issues List : <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html">http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#431</a>
  </p><p class="bibliomixed">
    [<a name="Cleary">Cleary</a>] Stephen Cleary : <a href="http://www.boost.org/libs/pool/doc/implementation/alignment.html">http://www.boost.org/libs/pool/doc/implementation/alignment.html</a>
  </p><p class="bibliomixed">
    [<a name="Halpern, 2005">Halpern, 2005</a>] Proposal to the C++ standards committee : <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1850.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1850.pdf</a>
  </p><p class="bibliomixed">
    [<a name="Henney">Henney</a>] Dr Dobb's Journal : <a href="http://www.ddj.com/dept/cpp/184403779">http://www.ddj.com/dept/cpp/184403779</a>
  </p><p class="bibliomixed">
    [<a name="Hinnant">Hinnant</a>] Hinnant, H.E. : <a href="http://www.open-std.org/jtc1/wg21/docs/papers/2004/n1599.html">http://www.open-std.org/jtc1/wg21/docs/papers/2004/n1599.html</a>
  </p><p class="bibliomixed">
    [<a name="LinkedList">LinkedList</a>] Classical C linked list : <a href="http://isis.poly.edu/kulesh/stuff/src/klist/">http://isis.poly.edu/kulesh/stuff/src/klist/</a>
  </p><p class="bibliomixed">
    [<a name="Microsoft">Microsoft</a>] Microsoft : <a href="http://msdn2.microsoft.com/en-us/library/ms810466.aspx">http://msdn2.microsoft.com/en-us/library/ms810466.aspx</a>
  </p><p class="bibliomixed">
    [<a name="POD">POD</a>] PODs : <a href="http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html">http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html</a>
  </p><p class="bibliomixed">
    [<a name="Rebind">Rebind</a>] Rebind documentation : <a href="http://msdn2.microsoft.com/en-us/library/5fk3e8ek.aspx">http://msdn2.microsoft.com/en-us/library/5fk3e8ek.aspx</a>
  </p></p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
