refcnttest.cc revision 7824
17824Sgblack@eecs.umich.edu/*
27824Sgblack@eecs.umich.edu * Copyright (c) 2010 The Regents of The University of Michigan
37824Sgblack@eecs.umich.edu * All rights reserved.
47824Sgblack@eecs.umich.edu *
57824Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67824Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77824Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87824Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97824Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107824Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117824Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127824Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137824Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147824Sgblack@eecs.umich.edu * this software without specific prior written permission.
157824Sgblack@eecs.umich.edu *
167824Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177824Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187824Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197824Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207824Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217824Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227824Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237824Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247824Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257824Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267824Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277824Sgblack@eecs.umich.edu *
287824Sgblack@eecs.umich.edu * Authors: Gabe Black
297824Sgblack@eecs.umich.edu */
307824Sgblack@eecs.umich.edu
317824Sgblack@eecs.umich.edu#include <cassert>
327824Sgblack@eecs.umich.edu#include <iostream>
337824Sgblack@eecs.umich.edu#include <list>
347824Sgblack@eecs.umich.edu
357824Sgblack@eecs.umich.edu#include "base/refcnt.hh"
367824Sgblack@eecs.umich.edu
377824Sgblack@eecs.umich.eduusing namespace std;
387824Sgblack@eecs.umich.edu
397824Sgblack@eecs.umich.edunamespace {
407824Sgblack@eecs.umich.edu
417824Sgblack@eecs.umich.educlass TestRC;
427824Sgblack@eecs.umich.edutypedef list<TestRC *> LiveList;
437824Sgblack@eecs.umich.eduLiveList liveList;
447824Sgblack@eecs.umich.edu
457824Sgblack@eecs.umich.eduint
467824Sgblack@eecs.umich.edulive()
477824Sgblack@eecs.umich.edu{
487824Sgblack@eecs.umich.edu    return liveList.size();
497824Sgblack@eecs.umich.edu}
507824Sgblack@eecs.umich.edu
517824Sgblack@eecs.umich.eduint
527824Sgblack@eecs.umich.eduliveChange()
537824Sgblack@eecs.umich.edu{
547824Sgblack@eecs.umich.edu    static int oldLive = 0;
557824Sgblack@eecs.umich.edu    int newLive = live();
567824Sgblack@eecs.umich.edu    int diff =  newLive - oldLive;
577824Sgblack@eecs.umich.edu    oldLive = newLive;
587824Sgblack@eecs.umich.edu    return diff;
597824Sgblack@eecs.umich.edu}
607824Sgblack@eecs.umich.edu
617824Sgblack@eecs.umich.educlass TestRC : public RefCounted
627824Sgblack@eecs.umich.edu{
637824Sgblack@eecs.umich.edu  protected:
647824Sgblack@eecs.umich.edu    const char *_tag;
657824Sgblack@eecs.umich.edu    LiveList::iterator liveIt;
667824Sgblack@eecs.umich.edu
677824Sgblack@eecs.umich.edu  public:
687824Sgblack@eecs.umich.edu    TestRC(const char *newTag) : _tag(newTag)
697824Sgblack@eecs.umich.edu    {
707824Sgblack@eecs.umich.edu        cout << "  Creating object \"" << _tag << "\"\n";
717824Sgblack@eecs.umich.edu        liveList.push_front(this);
727824Sgblack@eecs.umich.edu        liveIt = liveList.begin();
737824Sgblack@eecs.umich.edu    }
747824Sgblack@eecs.umich.edu
757824Sgblack@eecs.umich.edu    ~TestRC()
767824Sgblack@eecs.umich.edu    {
777824Sgblack@eecs.umich.edu        cout << "  Destroying object \"" << _tag << "\"\n";
787824Sgblack@eecs.umich.edu        liveList.erase(liveIt);
797824Sgblack@eecs.umich.edu    }
807824Sgblack@eecs.umich.edu
817824Sgblack@eecs.umich.edu    const char *
827824Sgblack@eecs.umich.edu    tag()
837824Sgblack@eecs.umich.edu    {
847824Sgblack@eecs.umich.edu        return _tag;
857824Sgblack@eecs.umich.edu    }
867824Sgblack@eecs.umich.edu
877824Sgblack@eecs.umich.edu    int testVal;
887824Sgblack@eecs.umich.edu};
897824Sgblack@eecs.umich.edu
907824Sgblack@eecs.umich.edutypedef RefCountingPtr<TestRC> Ptr;
917824Sgblack@eecs.umich.edu
927824Sgblack@eecs.umich.edu}
937824Sgblack@eecs.umich.edu
947824Sgblack@eecs.umich.eduint
957824Sgblack@eecs.umich.edumain()
967824Sgblack@eecs.umich.edu{
977824Sgblack@eecs.umich.edu    assert(live() == 0);
987824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
997824Sgblack@eecs.umich.edu
1007824Sgblack@eecs.umich.edu    // Create an empty Ptr and verify it's data pointer is NULL.
1017824Sgblack@eecs.umich.edu    cout << "NULL check.\n";
1027824Sgblack@eecs.umich.edu    Ptr nullCheck;
1037824Sgblack@eecs.umich.edu    assert(nullCheck.get() == NULL);
1047824Sgblack@eecs.umich.edu
1057824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1067824Sgblack@eecs.umich.edu
1077824Sgblack@eecs.umich.edu    // Construct a Ptr from a TestRC pointer.
1087824Sgblack@eecs.umich.edu    cout << "Construction from pointer.\n";
1097824Sgblack@eecs.umich.edu    Ptr constFromPointer = new TestRC("construction from pointer");
1107824Sgblack@eecs.umich.edu
1117824Sgblack@eecs.umich.edu    assert(liveChange() == 1);
1127824Sgblack@eecs.umich.edu
1137824Sgblack@eecs.umich.edu    // Construct a Ptr from an existing Ptr.
1147824Sgblack@eecs.umich.edu    cout << "Construction from a Ptr.\n";
1157824Sgblack@eecs.umich.edu    Ptr constFromPtr = constFromPointer;
1167824Sgblack@eecs.umich.edu
1177824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1187824Sgblack@eecs.umich.edu
1197824Sgblack@eecs.umich.edu    // Test a Ptr being destroyed.
1207824Sgblack@eecs.umich.edu    cout << "Destroying a Ptr.\n";
1217824Sgblack@eecs.umich.edu    Ptr *ptrPtr = new Ptr(new TestRC("destroying a ptr"));
1227824Sgblack@eecs.umich.edu    assert(liveChange() == 1);
1237824Sgblack@eecs.umich.edu    delete ptrPtr;
1247824Sgblack@eecs.umich.edu    assert(liveChange() == -1);
1257824Sgblack@eecs.umich.edu
1267824Sgblack@eecs.umich.edu    // Test assignment from a pointer and from a Ptr.
1277824Sgblack@eecs.umich.edu    cout << "Assignment operators.\n";
1287824Sgblack@eecs.umich.edu    Ptr assignmentTarget;
1297824Sgblack@eecs.umich.edu    TestRC *assignmentSourcePointer = new TestRC("assignment source 1");
1307824Sgblack@eecs.umich.edu    assert(liveChange() == 1);
1317824Sgblack@eecs.umich.edu    assignmentTarget = assignmentSourcePointer;
1327824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1337824Sgblack@eecs.umich.edu    assignmentTarget = NULL;
1347824Sgblack@eecs.umich.edu    assert(liveChange() == -1);
1357824Sgblack@eecs.umich.edu    Ptr assignmentSourcePtr(new TestRC("assignment source 2"));
1367824Sgblack@eecs.umich.edu    assert(liveChange() == 1);
1377824Sgblack@eecs.umich.edu    assignmentTarget = assignmentSourcePtr;
1387824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1397824Sgblack@eecs.umich.edu    assignmentSourcePtr = NULL;
1407824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1417824Sgblack@eecs.umich.edu    assignmentTarget = NULL;
1427824Sgblack@eecs.umich.edu    assert(liveChange() == -1);
1437824Sgblack@eecs.umich.edu
1447824Sgblack@eecs.umich.edu    // Test access to members of the pointed to class and dereferencing.
1457824Sgblack@eecs.umich.edu    cout << "Access to members.\n";
1467824Sgblack@eecs.umich.edu    TestRC *accessTest = new TestRC("access test");
1477824Sgblack@eecs.umich.edu    Ptr accessTestPtr = accessTest;
1487824Sgblack@eecs.umich.edu    accessTest->testVal = 1;
1497824Sgblack@eecs.umich.edu    assert(accessTestPtr->testVal == 1);
1507824Sgblack@eecs.umich.edu    assert((*accessTestPtr).testVal == 1);
1517824Sgblack@eecs.umich.edu    accessTest->testVal = 2;
1527824Sgblack@eecs.umich.edu    assert(accessTestPtr->testVal == 2);
1537824Sgblack@eecs.umich.edu    assert((*accessTestPtr).testVal == 2);
1547824Sgblack@eecs.umich.edu    accessTestPtr->testVal = 3;
1557824Sgblack@eecs.umich.edu    assert(accessTest->testVal == 3);
1567824Sgblack@eecs.umich.edu    (*accessTestPtr).testVal = 4;
1577824Sgblack@eecs.umich.edu    assert(accessTest->testVal == 4);
1587824Sgblack@eecs.umich.edu    accessTestPtr = NULL;
1597824Sgblack@eecs.umich.edu    accessTest = NULL;
1607824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1617824Sgblack@eecs.umich.edu
1627824Sgblack@eecs.umich.edu    // Test bool and ! operator overloads.
1637824Sgblack@eecs.umich.edu    cout << "Conversion to bool and ! overload.\n";
1647824Sgblack@eecs.umich.edu    Ptr boolTest = new TestRC("bool test");
1657824Sgblack@eecs.umich.edu    assert(boolTest == true);
1667824Sgblack@eecs.umich.edu    assert(!boolTest == false);
1677824Sgblack@eecs.umich.edu    boolTest = NULL;
1687824Sgblack@eecs.umich.edu    assert(boolTest == false);
1697824Sgblack@eecs.umich.edu    assert(!boolTest == true);
1707824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1717824Sgblack@eecs.umich.edu
1727824Sgblack@eecs.umich.edu    // Test the equality operators.
1737824Sgblack@eecs.umich.edu    cout << "Equality operators.\n";
1747824Sgblack@eecs.umich.edu    TestRC *equalTestA = new TestRC("equal test a");
1757824Sgblack@eecs.umich.edu    Ptr equalTestAPtr = equalTestA;
1767824Sgblack@eecs.umich.edu    Ptr equalTestAPtr2 = equalTestA;
1777824Sgblack@eecs.umich.edu    TestRC *equalTestB = new TestRC("equal test b");
1787824Sgblack@eecs.umich.edu    Ptr equalTestBPtr = equalTestB;
1797824Sgblack@eecs.umich.edu    assert(equalTestA == equalTestAPtr);
1807824Sgblack@eecs.umich.edu    assert(equalTestAPtr == equalTestA);
1817824Sgblack@eecs.umich.edu    assert(equalTestAPtr == equalTestAPtr2);
1827824Sgblack@eecs.umich.edu    assert(equalTestA != equalTestBPtr);
1837824Sgblack@eecs.umich.edu    assert(equalTestAPtr != equalTestB);
1847824Sgblack@eecs.umich.edu    assert(equalTestAPtr != equalTestBPtr);
1857824Sgblack@eecs.umich.edu
1867824Sgblack@eecs.umich.edu    cout << flush;
1877824Sgblack@eecs.umich.edu}
188