Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/more/count_bdy.htm @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 28.0 KB
Line 
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4<head>
5  <meta http-equiv="Content-Language" content="en-us">
6  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
7  <meta name="GENERATOR" content="Microsoft FrontPage 6.0">
8  <meta name="Author" content="Kevlin Henney">
9  <meta name="KeyWords" content=
10  "C++, Reference Counting, Advanced Techniques, Smart Pointers, Patterns">
11
12  <title>Counted Body Techniques</title>
13</head>
14
15<body bgcolor="#FFFFFF" text="#000000">
16  <h1 align="center"><i><font size="+4">Counted Body Techniques</font></i></h1>
17
18  <center>
19    <p><b><font size="+1"><a href="../people/kevlin_henney.htm">Kevlin Henney</a><br></font> 
20    (<a href=
21    "mailto:kevlin@acm.org">kevlin@acm.org</a>, <a href=
22    "mailto:khenney@qatraining.com">khenney@qatraining.com</a>)</b></p>
23  </center>
24
25  <div style="margin-left: 2em">
26    <p>Reference counting techniques? Nothing new, you might think. Every good
27    C++ text that takes you to an intermediate or advanced level will
28    introduce the concept. It has been explored with such thoroughness in the
29    past that you might be forgiven for thinking that everything that can be
30    said has been said. Well, let's start from first principles and see if we
31    can unearth something new....</p>
32  </div>
33  <hr width="100%">
34
35  <h2>And then there were none...</h2>
36
37  <div style="margin-left: 2em">
38    <p>The principle behind reference counting is to keep a running usage
39    count of an object so that when it falls to zero we know the object is
40    unused. This is normally used to simplify the memory management for
41    dynamically allocated objects: keep a count of the number of references
42    held to that object and, on zero, delete the object.</p>
43
44    <p>How to keep a track of the number of users of an object? Well, normal
45    pointers are quite dumb, and so an extra level of indirection is required
46    to manage the count. This is essentially the P<font size="-1">ROXY</font>
47    pattern described in <i>Design Patterns</i> [Gamma, Helm, Johnson &amp; 
48    Vlissides, Addison-Wesley, <font size="-1">ISBN</font> 0-201-63361-2]. The
49    intent is given as</p>
50
51    <div style="margin-left: 2em">
52      <p><i>Provide a surrogate or placeholder for another object to control
53      access to it.</i></p>
54    </div>
55
56    <p>Coplien [<i>Advanced C++ Programming Styles and Idioms</i>,
57    Addison-Wesley, <font size="-1">ISBN</font> 0-201-56365-7] defines a set
58    of idioms related to this essential separation of a handle and a body
59    part. The <i>Taligent Guide to Designing Programs</i> [Addison-Wesley,
60    <font size="-1">ISBN</font> 0-201-40888-0] identifies a number of specific
61    categories for proxies (aka surrogates). Broadly speaking they fall into
62    two general categories:</p>
63
64    <ul>
65      <li><i>Hidden</i>: The handle is the object of interest, hiding the body
66      itself. The functionality of the handle is obtained by delegation to the
67      body, and the user of the handle is unaware of the body. Reference
68      counted strings offer a transparent optimisation. The body is shared
69      between copies of a string until such a time as a change is needed, at
70      which point a copy is made. Such a C<font size=
71      "-1">OPY</font> <font size="-1">ON</font> W<font size="-1">RITE</font>
72      pattern (a specialisation of L<font size="-1">AZY</font> E<font size=
73      "-1">VALUATION</font>) requires the use of a hidden reference counted
74      body.</li>
75
76      <li><i>Explicit</i>: Here the body is of interest and the handle merely
77      provides intelligence for its access and housekeeping. In C++ this is
78      often implemented as the S<font size="-1">MART</font> P<font size=
79      "-1">OINTER</font> idiom. One such application is that of reference
80      counted smart pointers that collaborate to keep a count of an object,
81      deleting it when the count falls to zero.</li>
82    </ul>
83  </div>
84  <hr width="100%">
85
86  <h2>Attached vs detached</h2>
87
88  <div style="margin-left: 2em">
89    <p>For reference counted smart pointers there are two places the count can
90    exist, resulting in two different patterns, both outlined in
91    <i>Software Patterns</i> [Coplien, SIGS, <font size="-1">ISBN</font>
92    0-884842-50-X]:</p>
93
94    <ul>
95      <li>C<font size="-1">OUNTED</font> B<font size="-1">ODY</font> or A<font size="-1">TTACHED</font> 
96      C<font size="-1">OUNTED</font>
97      H<font size="-1">ANDLE</font>/B<font size="-1">ODY</font> places the
98      count within the object being counted. The benefits are that
99      countability is a part of the object being counted, and that reference
100      counting does not require an additional object. The drawbacks are
101      clearly that this is intrusive, and that the space for the reference
102      count is wasted when the object is not heap based. Therefore the
103      reference counting ties you to a particular implementation and style of
104      use.</li>
105
106      <li>D<font size="-1">ETACHED</font> C<font size="-1">OUNTED</font>
107      H<font size="-1">ANDLE</font>/B<font size="-1">ODY</font> places the
108      count outside the object being counted, such that they are handled
109      together. The clear benefit of this is that this technique is completely
110      unintrusive, with all of the intelligence and support apparatus in the
111      smart pointer, and therefore can be used on classes created
112      independently of the reference counted pointer. The main disadvantage is
113      that frequent use of this can lead to a proliferation of small objects,
114      i.e. the counter, being created on the heap.</li>
115    </ul>
116
117    <p>Even with this simple analysis, it seems that the D<font size=
118    "-1">ETACHED</font> C<font size="-1">OUNTED</font> H<font size=
119    "-1">ANDLE</font>/B<font size="-1">ODY</font> approach is ahead. Indeed,
120    with the increasing use of templates this is often the favourite, and is
121    the principle behind the common - but not standard - <tt><font size=
122    "+1">counted_ptr</font></tt>. <i>[The Boost name is <a href=
123    "../libs/smart_ptr/shared_ptr.htm"><tt><font size=
124    "+1">shared_ptr</font></tt></a> rather than <tt><font size=
125    "+1">counted_ptr</font></tt>.]</i></p>
126
127    <p>A common implementation of C<font size="-1">OUNTED</font> B<font size=
128    "-1">ODY</font> is to provide the counting mechanism in a base class that
129    the counted type is derived from. Either that, or the reference counting
130    mechanism is provided anew for each class that needs it. Both of these
131    approaches are unsatisfactory because they are quite closed, coupling a
132    class into a particular framework. Added to this the non-cohesiveness of
133    having the count lying dormant in a non-counted object, and you get the
134    feeling that excepting its use in widespread object models such as COM and
135    CORBA the C<font size="-1">OUNTED</font> B<font size="-1">ODY</font>
136    approach is perhaps only of use in specialised situations.</p>
137  </div>
138  <hr width="100%">
139
140  <h2>A requirements based approach</h2>
141
142  <div style="margin-left: 2em">
143    <p>It is the question of openness that convinced me to revisit the
144    problems with the C<font size="-1">OUNTED</font> B<font size=
145    "-1">ODY</font> idiom. Yes, there is a certain degree of intrusion
146    expected when using this idiom, but is there anyway to minimise this and
147    decouple the choice of counting mechanism from the smart pointer type
148    used?</p>
149
150    <p>In recent years the most instructive body of code and specification for
151    constructing open general purpose components has been the Stepanov and
152    Lee's STL (Standard Template Library), now part of the C++ standard
153    library. The STL approach makes extensive use of compile time polymorphism
154    based on well defined operational requirements for types. For instance,
155    each container, contained and iterator type is defined by the operations
156    that should be performable on an object of that type, often with
157    annotations describing additional constraints. Compile time polymorphism,
158    as its name suggests, resolves functions at compile time based on function
159    name and argument usage, i.e. overloading. This is less intrusive,
160    although less easily diagnosed if incorrect, than runtime poymorphism that
161    is based on types, names and function signatures.</p>
162
163    <p>This requirements based approach can be applied to reference counting.
164    The operations we need for a type to be <i>Countable</i> are loosely:</p>
165
166    <ul>
167      <li>An <tt><font size="+1">acquire</font></tt> operation that registers
168      interest in a <i>Countable</i> object.</li>
169
170      <li>A <tt><font size="+1">release</font></tt> operation unregisters
171      interest in a <i>Countable</i> object.</li>
172
173      <li>An <tt><font size="+1">acquired</font></tt> query that returns
174      whether or not a <i>Countable</i> object is currently acquired.</li>
175
176      <li>A <tt><font size="+1">dispose</font></tt> operation that is
177      responsible for disposing of an object that is no longer acquired.</li>
178    </ul>
179
180    <p>Note that the count is deduced as a part of the abstract state of this
181    type, and is not mentioned or defined in any other way. The openness of
182    this approach derives in part from the use of global functions, meaning
183    that no particular member functions are implied; a perfect way to wrap up
184    an existing counted body class without modifying the class itself. The
185    other aspect to the openness comes from a more precise specification of
186    the operations.</p>
187
188    <p>For a type to be <i>Countable</i> it must satisfy the following
189    requirements, where <tt><font size="+1">ptr</font></tt> is a non-null
190    pointer to a single object (i.e. not an array) of the type, and
191    <i><tt><font size="+1">#function</font></tt></i> indicates number of calls
192    to <tt><font size="+1"><i>function(</i>ptr<i>)</i></font></tt>:</p>
193
194    <center>
195      <table border="1" cellspacing="2" cellpadding="2" summary="">
196        <tr>
197          <td><i>Expression</i></td>
198
199          <td><i>Return type</i></td>
200
201          <td><i>Semantics and notes</i></td>
202        </tr>
203
204        <tr>
205          <td><tt><font size="+1">acquire(ptr)</font></tt></td>
206
207          <td>no requirement</td>
208
209          <td><i>post</i>: <tt><font size="+1">acquired(ptr)</font></tt></td>
210        </tr>
211
212        <tr>
213          <td><tt><font size="+1">release(ptr)</font></tt></td>
214
215          <td>no requirement</td>
216
217          <td><i>pre</i>: <tt><font size="+1">acquired(ptr)<br></font></tt>
218          <i>post</i>: <tt><font size="+1">acquired(ptr) == #acquire -
219          #release</font></tt></td>
220        </tr>
221
222        <tr>
223          <td><tt><font size="+1">acquired(ptr)</font></tt></td>
224
225          <td>convertible to <tt><font size="+1">bool</font></tt></td>
226
227          <td><i>return</i>: <tt><font size="+1">#acquire &gt; #release</font></tt></td>
228        </tr>
229
230        <tr>
231          <td><tt><font size="+1">dispose(ptr, ptr)</font></tt></td>
232
233          <td>no requirement</td>
234
235          <td><i>pre</i>: <tt><font size="+1">!acquired(ptr)<br></font></tt>
236          <i>post</i>: <tt><font size="+1">*ptr</font></tt> no longer usable</td>
237        </tr>
238      </table>
239    </center>
240
241    <p>Note that the two arguments to <tt><font size="+1">dispose</font></tt>
242    are to support selection of the appropriate type safe version of the
243    function to be called. In the general case the intent is that the first
244    argument determines the type to be deleted, and would typically be
245    templated, while the second selects which template to use, e.g. by
246    conforming to a specific base class.</p>
247
248    <p>In addition the following requirements must also be satisfied, where
249    <tt><font size="+1">null</font></tt> is a null pointer to the
250    <i>Countable</i> type:</p>
251
252    <center>
253      <table border="1" summary="">
254        <tr>
255          <td><i>Expression</i></td>
256
257          <td><i>Return type</i></td>
258
259          <td><i>Semantics and notes</i></td>
260        </tr>
261
262        <tr>
263          <td><tt><font size="+1">acquire(null)</font></tt></td>
264
265          <td>no requirement</td>
266
267          <td><i>action</i>: none</td>
268        </tr>
269
270        <tr>
271          <td><tt><font size="+1">release(null)</font></tt></td>
272
273          <td>no requirement</td>
274
275          <td><i>action</i>: none</td>
276        </tr>
277
278        <tr>
279          <td><tt><font size="+1">acquired(null)</font></tt></td>
280
281          <td>convertible to <tt><font size="+1">bool</font></tt></td>
282
283          <td><i>return</i>: <tt><font size="+1">false</font></tt></td>
284        </tr>
285
286        <tr>
287          <td><tt><font size="+1">dispose(null, null)</font></tt></td>
288
289          <td>no requirement</td>
290
291          <td><i>action</i>: none</td>
292        </tr>
293      </table>
294    </center>
295
296    <p>Note that there are no requirements on these functions in terms of
297    exceptions thrown or not thrown, except that if exceptions are thrown the
298    functions themselves should be exception safe.</p>
299  </div>
300  <hr width="100%">
301
302  <h2>Getting smart</h2>
303
304  <div style="margin-left: 2em">
305    <p>Given the <i>Countable</i> requirements for a type, it is possible to
306    define a generic smart pointer type that uses them for reference counting:</p>
307
308    <div style="margin-left: 2em">
309      <pre>
310<tt>template&lt;typename countable_type&gt;
311class countable_ptr
312{
313public: // construction and destruction
314
315    explicit countable_ptr(countable_type *);
316    countable_ptr(const countable_ptr &amp;);
317    ~countable_ptr();
318
319public: // access
320
321    countable_type *operator-&gt;() const;
322    countable_type &amp;operator*() const;
323    countable_type *get() const;
324
325public: // modification
326
327    countable_ptr &amp;clear();
328    countable_ptr &amp;assign(countable_type *);
329    countable_ptr &amp;assign(const countable_ptr &amp;);
330    countable_ptr &amp;operator=(const countable_ptr &amp;);
331
332private: // representation
333
334    countable_type *body;
335
336};
337</tt>
338</pre>
339    </div>
340
341    <p>The interface to this class has been kept intentionally simple, e.g.
342    member templates and <tt><font size="+1">throw</font></tt> specs have been
343    omitted, for exposition. The majority of the functions are quite simple in
344    implementation, relying very much on the <tt><font size=
345    "+1">assign</font></tt> member as a keystone function:</p>
346
347    <div style="margin-left: 2em">
348      <pre>
349<tt>template&lt;typename countable_type&gt;
350countable_ptr&lt;countable_type&gt;::countable_ptr(countable_type *initial)
351  : body(initial)
352{
353    acquire(body);
354}
355
356template&lt;typename countable_type&gt;
357countable_ptr&lt;countable_type&gt;::countable_ptr(const countable_ptr &amp;other)
358  : body(other.body)
359{
360    acquire(body);
361}
362
363template&lt;typename countable_type&gt;
364countable_ptr&lt;countable_type&gt;::~countable_ptr()
365{
366    clear();
367}
368
369template&lt;typename countable_type&gt;
370countable_type *countable_ptr&lt;countable_type&gt;::operator-&gt;() const
371{
372    return body;
373}
374
375template&lt;typename countable_type&gt;
376countable_type &amp;countable_ptr&lt;countable_type&gt;::operator*() const
377{
378    return *body;
379}
380
381template&lt;typename countable_type&gt;
382countable_type *countable_ptr&lt;countable_type&gt;::get() const
383{
384    return body;
385}
386
387template&lt;typename countable_type&gt;
388countable_ptr&lt;countable_type&gt; &amp;countable_ptr&lt;countable_type&gt;::clear()
389{
390    return assign(0);
391}
392
393template&lt;typename countable_type&gt;
394countable_ptr&lt;countable_type&gt; &amp;countable_ptr&lt;countable_type&gt;::assign(countable_type *rhs)
395{
396    // set to rhs (uses Copy Before Release idiom which is self assignment safe)
397    acquire(rhs);
398    countable_type *old_body = body;
399    body = rhs;
400
401    // tidy up
402    release(old_body);
403    if(!acquired(old_body))
404    {
405        dispose(old_body, old_body);
406    }
407
408    return *this;
409}
410
411template&lt;typename countable_type&gt;
412countable_ptr&lt;countable_type&gt; &amp;countable_ptr&lt;countable_type&gt;::assign(const countable_ptr &amp;rhs)
413{
414    return assign(rhs.body);
415}
416
417template&lt;typename countable_type&gt;
418countable_ptr&lt;countable_type&gt; &amp;countable_ptr&lt;countable_type&gt;::operator=(const countable_ptr &amp;rhs)
419{
420    return assign(rhs);
421}
422</tt>
423</pre>
424    </div>
425  </div>
426  <hr width="100%">
427
428  <h2>Public accountability</h2>
429
430  <div style="margin-left: 2em">
431    <p>Conformance to the requirements means that a type can be used with
432    <tt><font size="+1">countable_ptr</font></tt>. Here is an implementation
433    mix-in class (<i>mix-imp</i>) that confers countability on its derived
434    classes through member functions. This class can be used as a class
435    adaptor:</p>
436
437    <div style="margin-left: 2em">
438      <pre>
439<tt>class countability
440{
441public: // manipulation
442
443    void acquire() const;
444    void release() const;
445    size_t acquired() const;
446
447protected: // construction and destruction
448
449    countability();
450    ~countability();
451
452private: // representation
453
454    mutable size_t count;
455
456private: // prevention
457
458    countability(const countability &amp;);
459    countability &amp;operator=(const countability &amp;);
460
461};
462</tt>
463</pre>
464    </div>
465
466    <p>Notice that the manipulation functions are <tt><font size=
467    "+1">const</font></tt> and that the <tt><font size="+1">count</font></tt>
468    member itself is <tt><font size="+1">mutable</font></tt>. This is because
469    countability is not a part of an object's abstract state: memory
470    management does not depend on the <tt><font size=
471    "+1">const</font></tt>-ness or otherwise of an object. I won't include the
472    definitions of the member functions here as you can probably guess them:
473    increment, decrement and return the current count, respectively for the
474    manipulation functions. In a multithreaded environment you should ensure
475    that such read and write operations are atomic.</p>
476
477    <p>So how do we make this class <i>Countable</i>? A simple set of
478    forwarding functions does the job:</p>
479
480    <div style="margin-left: 2em">
481      <pre>
482<tt>void acquire(const countability *ptr)
483{
484    if(ptr)
485    {
486        ptr-&gt;acquire();
487    }
488}
489
490void release(const countability *ptr)
491{
492    if(ptr)
493    {
494        ptr-&gt;release();
495    }
496}
497
498size_t acquired(const countability *ptr)
499{
500    return ptr ? ptr-&gt;acquired() : 0;
501}
502
503template&lt;class countability_derived&gt;
504void dispose(const countability_derived *ptr, const countability *)
505{
506    delete ptr;
507}
508</tt>
509</pre>
510    </div>
511
512    <p>Any type that now derives from <tt><font size=
513    "+1">countability</font></tt> may now be used with <tt><font size=
514    "+1">countable_ptr</font></tt>:</p>
515
516    <div style="margin-left: 2em">
517      <pre>
518<tt>class example : public countability
519{
520    ...
521};
522
523void simple()
524{
525    countable_ptr&lt;example&gt; ptr(new example);
526    countable_ptr&lt;example&gt; qtr(ptr);
527    ptr.clear(); // set ptr to point to null
528}   // allocated object deleted when qtr destructs
529</tt>
530</pre>
531    </div>
532  </div>
533  <hr width="100%">
534
535  <h2>Runtime mixin</h2>
536
537  <div style="margin-left: 2em">
538    <p>The challenge is to apply C<font size="-1">OUNTED</font> B<font size=
539    "-1">ODY</font> in a non-intrusive fashion, such that there is no overhead
540    when an object is not counted. What we would like to do is confer this
541    capability on a per object rather than on a per class basis. Effectively
542    we are after <i>Countability</i> on any object, i.e. anything pointed to
543    by a <tt><font size="+1">void *</font></tt>! It goes without saying that <tt><font size="+1">
544    void</font></tt> is perhaps the least committed of any type.</p>
545
546    <p>The forces to resolve on this are quite interesting, to say the least.
547    Interesting, but not insurmountable. Given that the class of a runtime
548    object cannot change dynamically in any well defined manner, and the
549    layout of the object must be fixed, we have to find a new place and time
550    to add the counting state. The fact that this must be added only on heap
551    creation suggests the following solution:</p>
552
553    <div style="margin-left: 2em">
554      <pre>
555<tt>struct countable_new;
556extern const countable_new countable;
557
558void *operator new(size_t, const countable_new &amp;);
559void operator delete(void *, const countable_new &amp;);</tt>
560</pre>
561    </div>
562
563    <p>We have overloaded <tt><font size="+1">operator new</font></tt> with a
564    dummy argument to distinguish it from the regular global <tt><font size=
565    "+1">operator new</font></tt>. This is comparable to the use of the
566    <tt><font size="+1">std::nothrow_t</font></tt> type and <tt><font size=
567    "+1">std::nothrow</font></tt> object in the standard library. The
568    placement <tt><font size="+1">operator delete</font></tt> is there to
569    perform any tidy up in the event of failed construction. Note that this is
570    not yet supported on all that many compilers.</p>
571
572    <p>The result of a <tt><font size="+1">new</font></tt> expression using
573    <tt><font size="+1">countable</font></tt> is an object allocated on the
574    heap that has a header block that holds the count, i.e. we have extended
575    the object by prefixing it. We can provide a couple of features in an
576    anonymous namespace (not shown) in the implementation file for for
577    supporting the count and its access from a raw pointer:</p>
578
579    <div style="margin-left: 2em">
580      <pre>
581<tt>struct count
582{
583    size_t value;
584};
585
586count *header(const void *ptr)
587{
588    return const_cast&lt;count *&gt;(static_cast&lt;const count *&gt;(ptr) - 1);
589}
590</tt>
591</pre>
592    </div>
593
594    <p>An important constraint to observe here is the alignment of
595    <tt><font size="+1">count</font></tt> should be such that it is suitably
596    aligned for any type. For the definition shown this will be the case on
597    almost all platforms. However, you may need to add a padding member for
598    those that don't, e.g. using an anonymous <tt><font size=
599    "+1">union</font></tt> to coalign <tt><font size="+1">count</font></tt>
600    and the most aligned type. Unfortunately, there is no portable way of
601    specifying this such that the minimum alignment is also observed - this is
602    a common problem when specifying your own allocators that do not directly
603    use the results of either <tt><font size="+1">new</font></tt> or
604    <tt><font size="+1">malloc</font></tt>.</p>
605
606    <p>Again, note that the count is not considered to be a part of the
607    logical state of the object, and hence the conversion from
608    <tt><font size="+1">const</font></tt> to non-<tt><font size=
609    "+1">const</font></tt> - <tt><font size="+1">count</font></tt> is in
610    effect a <tt><font size="+1">mutable</font></tt> type.</p>
611
612    <p>The allocator functions themselves are fairly straightforward:</p>
613
614    <div style="margin-left: 2em">
615      <pre>
616<tt>void *operator new(size_t size, const countable_new &amp;)
617{
618    count *allocated = static_cast&lt;count *&gt;(::operator new(sizeof(count) + size));
619    *allocated = count(); // initialise the header
620    return allocated + 1; // adjust result to point to the body
621}
622
623void operator delete(void *ptr, const countable_new &amp;)
624{
625    ::operator delete(header(ptr));
626}
627</tt>
628</pre>
629    </div>
630
631    <p>Given a correctly allocated header, we now need the <i>Countable</i>
632    functions to operate on <tt><font size="+1">const void *</font></tt> to
633    complete the picture:</p>
634
635    <div style="margin-left: 2em">
636      <pre>
637<tt>void acquire(const void *ptr)
638{
639    if(ptr)
640    {
641        ++header(ptr)-&gt;value;
642    }
643}
644
645void release(const void *ptr)
646{
647    if(ptr)
648    {
649        --header(ptr)-&gt;value;
650    }
651}
652
653size_t acquired(const void *ptr)
654{
655    return ptr ? header(ptr)-&gt;value : 0;
656}
657
658template&lt;typename countable_type&gt;
659void dispose(const countable_type *ptr, const void *)
660{
661    ptr-&gt;~countable_type();
662    operator delete(const_cast&lt;countable_type *&gt;(ptr), countable);
663}
664</tt>
665</pre>
666    </div>
667
668    <p>The most complex of these is the <tt><font size=
669    "+1">dispose</font></tt> function that must ensure that the correct type
670    is destructed and also that the memory is collected from the correct
671    offset. It uses the value and type of first argument to perform this
672    correctly, and the second argument merely acts as a strategy selector,
673    i.e. the use of <tt><font size="+1">const void *</font></tt>
674    distinguishes it from the earlier dispose shown for <tt><font size=
675    "+1">const countability *</font></tt>.</p>
676  </div>
677  <hr width="100%">
678
679  <h2>Getting smarter</h2>
680
681  <div style="margin-left: 2em">
682    <p>Now that we have a way of adding countability at creation for objects
683    of any type, what extra is needed to make this work with the
684    <tt><font size="+1">countable_ptr</font></tt> we defined earlier? Good
685    news: nothing!</p>
686
687    <div style="margin-left: 2em">
688      <pre>
689<tt>class example
690{
691    ...
692};
693
694void simple()
695{
696    countable_ptr&lt;example&gt; ptr(new(countable) example);
697    countable_ptr&lt;example&gt; qtr(ptr);
698    ptr.clear(); // set ptr to point to null
699}   // allocated object deleted when qtr destructs
700</tt>
701</pre>
702    </div>
703
704    <p>The <tt><font size="+1">new(countable)</font></tt> expression defines a
705    different policy for allocation and deallocation and, in common with other
706    allocators, any attempt to mix your allocation policies, e.g. call
707    <tt><font size="+1">delete</font></tt> on an object allocated with
708    <tt><font size="+1">new(countable)</font></tt>, results in undefined
709    behaviour. This is similar to what happens when you mix <tt><font size=
710    "+1">new[]</font></tt> with <tt><font size="+1">delete</font></tt> or
711    <tt><font size="+1">malloc</font></tt> with <tt><font size=
712    "+1">delete</font></tt>. The whole point of <i>Countable</i> conformance
713    is that <i>Countable</i> objects are used with <tt><font size=
714    "+1">countable_ptr</font></tt>, and this ensures the correct use.</p>
715
716    <p>However, accidents will happen, and inevitably you may forget to
717    allocate using <tt><font size="+1">new(countable)</font></tt> and instead
718    use <tt><font size="+1">new</font></tt>. This error and others can be
719    detected in most cases by extending the code shown here to add a check
720    member to the <tt><font size="+1">count</font></tt>, validating the check
721    on every access. A benefit of ensuring clear separation between header and
722    implementation source files means that you can introduce a checking
723    version of this allocator without having to recompile your code.</p>
724  </div>
725  <hr width="100%">
726
727  <h2>Conclusion</h2>
728
729  <div style="margin-left: 2em">
730    <p>There are two key concepts that this article has introduced:</p>
731
732    <ul>
733      <li>The use of a generic requirements based approach to simplify and
734      adapt the use of the C<font size="-1">OUNTED</font> B<font size=
735      "-1">ODY</font> pattern.</li>
736
737      <li>The ability, through control of allocation, to dynamically and
738      non-intrusively add capabilities to fixed types using the R<font size=
739      "-1">UNTIME</font> M<font size="-1">IXIN</font> pattern.</li>
740    </ul>
741
742    <p>The application of the two together gives rise to a new variant of the
743    essential C<font size="-1">OUNTED</font> B<font size="-1">ODY</font>
744    pattern, U<font size="-1">NINTRUSIVE</font> C<font size=
745    "-1">OUNTED</font> B<font size="-1">ODY</font>. You can take this theme
746    even further and contrive a simple garbage collection system for C++.</p>
747
748    <p>The complete code for <tt><font size="+1">countable_ptr</font></tt>,
749    <tt><font size="+1">countability</font></tt>, and the <tt><font size=
750    "+1">countable new</font></tt> is also available.</p>
751  </div>
752
753  <div align="right">
754    <hr width="100%">
755    <font size="-1"><i>First published in</i> <a href=
756    "http://www.accu.org/c++sig/public/Overload.html">Overload</a> <i>25,
757    April 1998, ISSN 1354-3172</i></font>
758  </div>
759 
760  <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
761  "http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
762  height="31" width="88"></a></p>
763
764  <p>Revised
765  <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->04 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38514" --></p>
766
767  <p><i>Copyright &copy; 1998-1999 Kevlin Henney</i></p>
768
769  <p><i>Distributed under the Boost Software License, Version 1.0. (See
770  accompanying file <a href="../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
771  at <a href=
772  "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
773</body>
774</html>
Note: See TracBrowser for help on using the repository browser.