71 lines
10 KiB
XML
71 lines
10 KiB
XML
|
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||
|
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.6">
|
||
|
<compounddef id="group__FuncMemAllocator" kind="group">
|
||
|
<compoundname>FuncMemAllocator</compoundname>
|
||
|
<title>Using allocators with Gecode</title>
|
||
|
<innerclass refid="structGecode_1_1space__allocator" prot="public">Gecode::space_allocator</innerclass>
|
||
|
<innerclass refid="structGecode_1_1region__allocator" prot="public">Gecode::region_allocator</innerclass>
|
||
|
<briefdescription>
|
||
|
</briefdescription>
|
||
|
<detaileddescription>
|
||
|
<para>Gecode provides two allocator classes that can be used with generic data structures such as those of the STL (e.g. <computeroutput>std::set</computeroutput>). Memory can be allocated from the space heap (see <ref refid="classGecode_1_1Space" kindref="compound">Space</ref>) or from a region (see <ref refid="classGecode_1_1Region" kindref="compound">Region</ref>).</para><sect1 id="group__FuncMemAllocator_1FuncMemAllocatorA">
|
||
|
<title>Using allocators with dynamic data structures</title>
|
||
|
<para>There are two possible scenarios for allocator usage. One is to let the dynamic data structure allocate memory from the space or region:</para><para><programlisting><codeline><highlight class="keyword">struct<sp/></highlight><highlight class="normal">MySpace<sp/>:<sp/></highlight><highlight class="keyword">public</highlight><highlight class="normal"><sp/>Space<sp/>{</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keyword">typedef</highlight><highlight class="normal"><sp/>std::set<int,<sp/>std::less<int>,<sp/><ref refid="structGecode_1_1space__allocator" kindref="compound">Gecode::space_allocator<int></ref><sp/>><sp/>S;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>S<sp/>safe_set;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>MySpace(</highlight><highlight class="keywordtype">void</highlight><highlight class="normal">)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>:<sp/>safe_set(S::key_compare(),<sp/>S::allocator_type(*this))</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>{}</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>MySpace(</highlight><highlight class="keywordtype">bool</highlight><highlight class="normal"><sp/>share,<sp/>MySpace&<sp/>other)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>:<sp/>Space(share,<sp/>other),<sp/></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/>safe_set(other.safe_set.begin(),<sp/>other.safe_set.end(),<sp/></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>S::key_compare(),<sp/>S::allocator_type(*this))</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>{}</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>...</highlight></codeline>
|
||
|
<codeline><highlight class="normal">};</highlight></codeline>
|
||
|
</programlisting></para><para>In this example, <emphasis>S</emphasis> is a set that allocates its nodes from the space heap. Note that we pass an instance of <ref refid="structGecode_1_1space__allocator" kindref="compound">space_allocator</ref> bound to this space to the constructor of the set. A similar thing must be done in the copying constructor, where we must be sure to pass an allocator that allocates memory from the destination ("this") space, not "other". Note that the set itself is a member of <emphasis>MySpace</emphasis>, so it is destroyed within <emphasis>MySpace::~MySpace</emphasis> as usual. The set destructor destroys all contained items and deallocates all nodes in its destructors.</para></sect1>
|
||
|
<sect1 id="group__FuncMemAllocator_1FuncMemAllocatorB">
|
||
|
<title>Preventing unnecessary destruction overhead</title>
|
||
|
<para>In the above example, we know that the value type in <emphasis>S</emphasis> is a builtin type and does not have a destructor. So what happens during <emphasis>safe_set</emphasis> destruction is that it just deallocates all nodes. However, we know that all nodes were allocated from the space heap, which is going to disappear with the space anyway. If we prevent calling <emphasis>safe_set</emphasis> destructor, we may save a significant amount of time during space destruction. A safe way of doing this is to allocate the set object itself on the space heap, and keep only a reference to it as a member of the space. We can use the convenience helpers <ref refid="classGecode_1_1Space_1a995b57f345f83b31cf91c8dd8a4c80ae" kindref="member">Space::construct</ref> for the construction.</para><para><programlisting><codeline><highlight class="keyword">struct<sp/></highlight><highlight class="normal">MySpace<sp/>:<sp/></highlight><highlight class="keyword">public</highlight><highlight class="normal"><sp/>Space<sp/>{</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keyword">typedef</highlight><highlight class="normal"><sp/>std::set<int,<sp/>std::less<int>,<sp/><ref refid="structGecode_1_1space__allocator" kindref="compound">Gecode::space_allocator<int></ref><sp/>><sp/>S;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>S&<sp/>fast_set;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>MySpace(</highlight><highlight class="keywordtype">void</highlight><highlight class="normal">)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>:<sp/>fast_set(construct<S>(S::key_compare(),<sp/>S::allocator_type(*this)))</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>{}</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>MySpace(</highlight><highlight class="keywordtype">bool</highlight><highlight class="normal"><sp/>share,<sp/>MySpace&<sp/>other)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>:<sp/>Space(share,<sp/>other),<sp/></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>fast_set(construct<S>(other.safe_set.begin(),<sp/>other.safe_set.end(),<sp/></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>S::key_compare(),<sp/>S::allocator_type(*this)))</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>{}</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>...</highlight></codeline>
|
||
|
<codeline><highlight class="normal">};</highlight></codeline>
|
||
|
</programlisting></para></sect1>
|
||
|
<sect1 id="group__FuncMemAllocator_1FuncMemAllocatorC">
|
||
|
<title>Region example</title>
|
||
|
<para>The above examples were using a <ref refid="structGecode_1_1space__allocator" kindref="compound">space_allocator</ref>. A <ref refid="structGecode_1_1region__allocator" kindref="compound">region_allocator</ref> works similarly, one just should keep in mind that regions never really release any memory. Similar to <ref refid="classGecode_1_1Space" kindref="compound">Space</ref>, <ref refid="classGecode_1_1Region" kindref="compound">Region</ref> provides helper functions <ref refid="classGecode_1_1Region_1a3f59930c9fc1c3b9028c2a80b6b4962c" kindref="member">Region::construct</ref> to make non-stack allocation easy.</para><para><programlisting><codeline><highlight class="normal">Space&<sp/>home<sp/>=<sp/>...;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight><highlight class="keyword">typedef</highlight><highlight class="normal"><sp/>std::set<int,<sp/>std::less<int>,<sp/><ref refid="structGecode_1_1region__allocator" kindref="compound">Gecode::region_allocator<int></ref><sp/>><sp/>SR;</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight><highlight class="comment">//<sp/>Create<sp/>a<sp/>set<sp/>with<sp/>the<sp/>region<sp/>allocator.<sp/>Note<sp/>that<sp/>the<sp/>set<sp/>destructor<sp/>is<sp/>still<sp/>quite<sp/>costly...</highlight><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal">{</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>Region<sp/>r(home);</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>SR<sp/>r_safe_set(SR::key_compare(),<sp/>(SR::allocator_type(r)));</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i=0;<sp/>i<10000;<sp/>++i)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>r_safe_set.insert(i*75321%10000);</highlight></codeline>
|
||
|
<codeline><highlight class="normal">}</highlight></codeline>
|
||
|
<codeline><highlight class="normal"></highlight><highlight class="comment">//<sp/>Create<sp/>a<sp/>set<sp/>directly<sp/>in<sp/>the<sp/>region<sp/>(not<sp/>on<sp/>the<sp/>stack).<sp/>No<sp/>destructors<sp/>will<sp/>be<sp/>called.</highlight><highlight class="normal"></highlight></codeline>
|
||
|
<codeline><highlight class="normal">{</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>Region<sp/>r(*</highlight><highlight class="keyword">this</highlight><highlight class="normal">);</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/>SR&<sp/>r_fast_set=r.construct<SR>(SR::key_compare(),<sp/>SR::allocator_type(r));</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i=0;<sp/>i<10000;<sp/>++i)</highlight></codeline>
|
||
|
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/>r_fast_set.insert(i*75321%10000);</highlight></codeline>
|
||
|
<codeline><highlight class="normal">}</highlight></codeline>
|
||
|
</programlisting> </para></sect1>
|
||
|
</detaileddescription>
|
||
|
</compounddef>
|
||
|
</doxygen>
|