Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1723

Show
Ignore:
Timestamp:
07/04/10 21:54:33 (14 years ago)
Author:
andrei
Message:

Changed broken opAssign to assign, plus minor changes to RefCounted?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/typecons.d

    r1676 r1723  
    4646Copyright: Copyright the respective authors, 2008- 
    4747License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 
    4848Authors:   $(WEB erdani.org, Andrei Alexandrescu), 
    4949           $(WEB bartoszmilewski.wordpress.com, Bartosz Milewski), 
    5050           Don Clugston, 
    5151           Shin Fujishiro 
    5252 */ 
    5353module std.typecons; 
    5454import core.stdc.stdlib, std.algorithm, std.array, std.contracts, std.conv, 
    5555    std.metastrings, std.traits, std.typetuple, core.memory; 
     56version(unittest) import std.stdio; 
    5657 
    5758/** 
    5859Encapsulates unique ownership of a resource.  Resource of type T is 
    5960deleted at the end of the scope, unless it is transferred.  The 
    6061transfer can be explicit, by calling $(D release), or implicit, when 
    6162returning Unique from a function. The resource can be a polymorphic 
    6263class object, in which case Unique behaves polymorphically too. 
    6364 
    6465Example: 
    6566*/ 
     
    321322    } 
    322323    alias field expand; 
    323324    // @@@BUG 2800 
    324325    //alias field this; 
    325326     
    326327/** 
    327328   Default constructor. 
    328329 */ 
    329330    this(U...)(U values) if (U.length == 0) 
    330331    { 
    331          
    332332    } 
    333333 
    334334/** 
    335335   Constructor taking one value for each field. Each argument must be 
    336336   implicitly assignable to the respective element of the target. 
    337337 */ 
    338338    this(U...)(U values) if (U.length == Types.length) 
    339339    { 
    340340        foreach (i, Unused; Types) 
    341341        { 
     
    359359 
    360360/** 
    361361   Comparison for equality. 
    362362 */ 
    363363    bool opEquals(T)(T rhs) if (is(typeof(T.field))) 
    364364    { 
    365365        static assert(field.length == rhs.field.length, 
    366366                "Length mismatch in attempting to compare a " 
    367367                ~typeof(this).stringof 
    368368                ~" with a "~typeof(rhs).stringof); 
    369         foreach (i, f; field
    370         { 
    371             if (f != rhs.field[i]) return false; 
     369        foreach (i, Unused; Types
     370        { 
     371            if (field[i] != rhs.field[i]) return false; 
    372372        } 
    373373        return true; 
    374374    } 
    375375 
    376376/** 
    377377   Comparison for ordering. 
    378378 */ 
    379379    int opCmp(T)(T rhs) if (is(typeof(T.field))) 
    380380    { 
    381381        static assert(field.length == rhs.field.length, 
    382382                "Length mismatch in attempting to compare a " 
    383383                ~typeof(this).stringof 
    384384                ~" with a "~typeof(rhs).stringof); 
    385         foreach (i, f; field) 
    386         { 
    387             if (f != rhs.field[i]) return f < rhs.field[i] ? -1 : 1; 
     385        foreach (i, Unused; Types) 
     386        { 
     387            if (field[i] != rhs.field[i]) 
     388            { 
     389                return field[i] < rhs.field[i] ? -1 : 1; 
     390            } 
    388391        } 
    389392        return 0; 
    390393    } 
    391394 
     395// Should really be opAssign, not assign 
    392396/** 
    393397   Assignment from another tuple. Each element of the source must be 
    394398   implicitly assignable to the respective element of the target. 
    395399 */ 
    396     void opAssign(U)(U rhs) if (is(typeof(U.init.field[0]))) 
    397     { 
    398         foreach (i, Unused; noStrings!(T).Result
     400    void assign(U)(U rhs) if (is(typeof(U.init.field[0]))) 
     401    { 
     402        foreach (i, Unused; Types
    399403        { 
    400404            field[i] = rhs.field[i]; 
    401405        } 
    402406    } 
     407 
    403408/** 
    404409   Takes a slice of the tuple. 
    405410 
    406411   Example: 
    407412 
    408413---- 
    409414Tuple!(int, string, float, double) a; 
    410415a.field[1] = "abc"; 
    411416a.field[2] = 4.5; 
    412417auto s = a.slice!(1, 3); 
     
    473478        auto c = Tuple!(int, "a", double, "b")(a); 
    474479        assert(c.field[0] == 1 && c.field[1] == 2); 
    475480    } 
    476481    Tuple!(int, int) nosh; 
    477482    nosh.field[0] = 5; 
    478483    assert(nosh.field[0] == 5); 
    479484    // Tuple!(int, int) nosh1; 
    480485    // assert(!is(typeof(nosh) == typeof(nosh1))); 
    481486    assert(nosh.toString == "Tuple!(int,int)(5, 0)", nosh.toString); 
    482487    Tuple!(int, short) yessh; 
    483     nosh = yessh
     488    nosh.assign(yessh)
    484489 
    485490    Tuple!(int, "a", float, "b") x; 
    486491    static assert(x.a.offsetof == x.field[0].offsetof); 
    487492    static assert(x.b.offsetof == x.field[1].offsetof); 
    488493    x.b = 4.5; 
    489494    x.a = 5; 
    490495    assert(x.field[0] == 5 && x.field[1] == 4.5); 
    491496    assert(x.a == 5 && x.b == 4.5); 
    492497 
    493498    { 
     
    20242029// Reference semantics 
    20252030rc2 = 42; 
    20262031assert(rc1 == 42); 
    20272032// the pair will be freed when rc1 and rc2 go out of scope 
    20282033---- 
    20292034 */ 
    20302035struct RefCounted(T, RefCountedAutoInitialize autoInit = 
    20312036        RefCountedAutoInitialize.yes) 
    20322037if (!is(T == class)) 
    20332038{ 
    2034     private Tuple!(T, "payload_", size_t, "count_") * refCountedStore_
     2039    private Tuple!(T, "_payload", size_t, "_count") * _refCountedStore
    20352040 
    20362041    private void refCountedInitialize(A...)(A args) 
    20372042    { 
    2038    const sz = (*refCountedStore_).sizeof; 
     2043        const sz = (*_refCountedStore).sizeof; 
    20392044        auto p = malloc(sz)[0 .. sz]; 
    20402045    if (sz >= size_t.sizeof && p.ptr) 
    20412046        GC.addRange(p.ptr, sz); 
    20422047        emplace!T(p[0 .. T.sizeof], args); 
    2043         refCountedStore_ = cast(typeof(refCountedStore_)) p; 
    2044         refCountedStore_.count_ = 1; 
     2048        _refCountedStore = cast(typeof(_refCountedStore)) p; 
     2049        _refCountedStore._count = 1; 
    20452050    } 
    20462051 
    20472052/** 
    20482053Returns $(D true) if and only if the underlying store has been 
    20492054allocated and initialized. 
    20502055 */ 
    20512056    @property bool refCountedIsInitialized() const 
    20522057    { 
    2053         return refCountedStore_ !is null; 
     2058        return _refCountedStore !is null; 
    20542059    } 
    20552060 
    20562061/** 
    20572062Makes sure the payload was properly initialized. Such a call is 
    20582063typically inserted before using the payload. 
    20592064 */ 
    20602065    void refCountedEnsureInitialized() 
    20612066    { 
    2062         if (refCountedIsInitialized()) return; 
     2067        if (refCountedIsInitialized) return; 
    20632068        refCountedInitialize(); 
    20642069    } 
    20652070 
    20662071/** 
    20672072Constructor that initializes the payload. 
    20682073 
    20692074Postcondition: $(D refCountedIsInitialized) 
    20702075 */ 
    20712076    this(A...)(A args) if (A.length > 0) 
    20722077    { 
    20732078        refCountedInitialize(args); 
    20742079    } 
    20752080 
    20762081/** 
    20772082Constructor that tracks the reference count appropriately. If $(D 
    20782083!refCountedIsInitialized), does nothing. 
    20792084 */ 
    20802085    this(this) 
    20812086    { 
    20822087        if (!refCountedIsInitialized) return; 
    2083         ++refCountedStore_.count_
     2088        ++_refCountedStore._count
    20842089    } 
    20852090 
    20862091/** 
    20872092Destructor that tracks the reference count appropriately. If $(D 
    20882093!refCountedIsInitialized), does nothing. When the reference count goes 
    20892094down to zero, calls $(D clear) agaist the payload and calls $(D free) 
    20902095to deallocate the corresponding resource. 
    20912096 */ 
    20922097    ~this() 
    20932098    { 
    2094         if (!refCountedStore_ || --refCountedStore_.count_) return; 
     2099        if (!_refCountedStore || --_refCountedStore._count) return; 
    20952100        // Done, deallocate 
    2096         clear(*refCountedStore_); 
    2097    if ((*refCountedStore_).sizeof >= size_t.sizeof && refCountedStore_
    2098        GC.removeRange(refCountedStore_); 
    2099         free(refCountedStore_); 
    2100         refCountedStore_ = null; 
     2101        clear(*_refCountedStore); 
     2102        if (hasIndirections!T && _refCountedStore
     2103            GC.removeRange(_refCountedStore); 
     2104        free(_refCountedStore); 
     2105        _refCountedStore = null; 
    21012106    } 
    21022107 
    21032108/** 
    21042109Assignment operators 
    21052110 */ 
    2106     void opAssign(RefCounted!T rhs) 
    2107     { 
    2108         swap(refCountedStore_, rhs.refCountedStore_); 
     2111    void opAssign(RefCounted rhs) 
     2112    { 
     2113        swap(_refCountedStore, rhs._refCountedStore); 
    21092114    } 
    21102115 
    21112116/// Ditto 
    21122117    void opAssign(T rhs) 
    21132118    { 
    21142119        refCountedPayload() = move(rhs); 
    21152120    } 
    21162121 
    21172122/** 
    21182123Returns a reference to the payload. If (autoInit == 
     
    21322137 */ 
    21332138    @property ref T refCountedPayload() { 
    21342139        static if (autoInit == RefCountedAutoInitialize.yes) 
    21352140        { 
    21362141            refCountedEnsureInitialized(); 
    21372142        } 
    21382143        else 
    21392144        { 
    21402145            assert(refCountedIsInitialized); 
    21412146        } 
    2142         return refCountedStore_.payload_; 
     2147        return _refCountedStore._payload; 
     2148    } 
     2149 
     2150// 
     2151    @property ref const(T) refCountedPayload() const { 
     2152        static if (autoInit == RefCountedAutoInitialize.yes) 
     2153        { 
     2154            // @@@ 
     2155            //refCountedEnsureInitialized(); 
     2156            assert(refCountedIsInitialized); 
     2157        } 
     2158        else 
     2159        { 
     2160            assert(refCountedIsInitialized); 
     2161        } 
     2162        return _refCountedStore._payload; 
    21432163    } 
    21442164} 
    21452165 
    21462166unittest 
    21472167{ 
    21482168    RefCounted!int* p; 
    21492169    { 
    21502170        auto rc1 = RefCounted!int(5); 
    21512171        p = &rc1; 
    21522172        assert(rc1 == 5); 
    2153         assert(rc1.refCountedStore_.count_ == 1); 
     2173        assert(rc1._refCountedStore._count == 1); 
    21542174        auto rc2 = rc1; 
    2155         assert(rc1.refCountedStore_.count_ == 2); 
     2175        assert(rc1._refCountedStore._count == 2); 
    21562176        // Reference semantics 
    21572177        rc2 = 42; 
    21582178        assert(rc1 == 42); 
    21592179        rc2 = rc2; 
    2160         assert(rc2.refCountedStore_.count_ == 2); 
     2180        assert(rc2._refCountedStore._count == 2); 
    21612181        rc1 = rc2; 
    2162         assert(rc1.refCountedStore_.count_ == 2); 
    2163     } 
    2164     assert(p.refCountedStore_ == null); 
    2165 
    2166  
     2182        assert(rc1._refCountedStore._count == 2); 
     2183    } 
     2184    assert(p._refCountedStore == null); 
     2185 
     2186    // RefCounted as a member 
     2187    struct A 
     2188    { 
     2189        RefCounted!int x; 
     2190        this(int y) 
     2191        { 
     2192            x.refCountedInitialize(y); 
     2193        } 
     2194        A copy() 
     2195        { 
     2196            auto another = this; 
     2197            return another; 
     2198        } 
     2199    } 
     2200    auto a = A(4); 
     2201    auto b = a.copy(); 
     2202    if (a.x._refCountedStore._count != 2) { 
     2203        stderr.writeln("*** BUG 4356 still unfixed"); 
     2204    } 
     2205
     2206