summaryrefslogtreecommitdiff
path: root/o3tl/qa/cow_wrapper_clients.hxx
blob: d0e416c96318a033e4936c1481c2ae29c89c70f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX
#define INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX

#include <o3tl/cow_wrapper.hxx>
#include <assert.h>
#include <iostream>

/* Definition of Cow_Wrapper_Clients classes */

namespace o3tltests {

/** This is a header and a separate compilation unit on purpose -
    cow_wrapper needs destructor, copy constructor and assignment
    operator to be outline, when pimpl idiom is used
 */

/// test non-opaque impl type
class cow_wrapper_client1
{
public:
    cow_wrapper_client1() : maImpl() {}
    explicit cow_wrapper_client1( int nVal ) : maImpl(nVal) {}

    void modify( int nVal ) { *maImpl = nVal; }
    int  queryUnmodified() const { return *maImpl; }

    void makeUnique() { maImpl.make_unique(); }
    bool is_unique() const { return maImpl.is_unique(); }
    oslInterlockedCount use_count() const { return maImpl.use_count(); }
    void swap( cow_wrapper_client1& r ) { o3tl::swap(maImpl, r.maImpl); }

    bool operator==( const cow_wrapper_client1& rRHS ) const { return maImpl == rRHS.maImpl; }
    bool operator!=( const cow_wrapper_client1& rRHS ) const { return maImpl != rRHS.maImpl; }
    bool operator<( const cow_wrapper_client1& rRHS ) const { return maImpl < rRHS.maImpl; }

private:
    o3tl::cow_wrapper< int > maImpl;
};


class cow_wrapper_client2_impl;

/** test opaque impl type - need to explicitly declare lifetime
    methods
 */
class cow_wrapper_client2
{
public:
    cow_wrapper_client2();
    explicit cow_wrapper_client2( int nVal );
    ~cow_wrapper_client2();

    cow_wrapper_client2( const cow_wrapper_client2& );
    cow_wrapper_client2(cow_wrapper_client2&&) noexcept;
    cow_wrapper_client2& operator=( const cow_wrapper_client2& );
    cow_wrapper_client2& operator=(cow_wrapper_client2&&) noexcept;

    void modify( int nVal );
    int  queryUnmodified() const;

    void makeUnique();
    bool is_unique() const;
    oslInterlockedCount use_count() const;
    void swap( cow_wrapper_client2& r );

    bool operator==( const cow_wrapper_client2& rRHS ) const;
    bool operator!=( const cow_wrapper_client2& rRHS ) const;
    bool operator<( const cow_wrapper_client2& rRHS ) const;

private:
    o3tl::cow_wrapper< cow_wrapper_client2_impl > maImpl;
};

/** test MT-safe cow_wrapper - basically the same as
    cow_wrapper_client2, only with different refcounting policy
 */
class cow_wrapper_client3
{
public:
    cow_wrapper_client3();
    explicit cow_wrapper_client3( int nVal );
    ~cow_wrapper_client3();

    cow_wrapper_client3( const cow_wrapper_client3& );
    cow_wrapper_client3(cow_wrapper_client3&&) noexcept;
    cow_wrapper_client3& operator=( const cow_wrapper_client3& );
    cow_wrapper_client3& operator=(cow_wrapper_client3&&) noexcept;

    void modify( int nVal );
    int  queryUnmodified() const;

    void makeUnique();
    bool is_unique() const;
    oslInterlockedCount use_count() const;
    void swap( cow_wrapper_client3& r );

    bool operator==( const cow_wrapper_client3& rRHS ) const;
    bool operator!=( const cow_wrapper_client3& rRHS ) const;
    bool operator<( const cow_wrapper_client3& rRHS ) const;

private:
    o3tl::cow_wrapper< cow_wrapper_client2_impl, o3tl::ThreadSafeRefCountingPolicy > maImpl;
};

/** test default-object comparison - have default-stored-client4 share
    the same static impl instance, check if isDefault does the right
    thing
 */
class cow_wrapper_client4
{
public:
    cow_wrapper_client4();
    explicit cow_wrapper_client4(int);
    ~cow_wrapper_client4();

    cow_wrapper_client4( const cow_wrapper_client4& );
    cow_wrapper_client4& operator=( const cow_wrapper_client4& );

    bool is_default() const;

    bool operator==( const cow_wrapper_client4& rRHS ) const;
    bool operator!=( const cow_wrapper_client4& rRHS ) const;
    bool operator<( const cow_wrapper_client4& rRHS ) const;

private:
    o3tl::cow_wrapper< int > maImpl;
};

// singleton ref-counting policy used to keep track of when
// incrementing and decrementing occurs
struct BogusRefCountPolicy
{
    static bool s_bShouldIncrement;
    static bool s_bShouldDecrement;
    static sal_uInt32 s_nEndOfScope;
    typedef sal_uInt32 ref_count_t;
    static void incrementCount( ref_count_t& rCount ) {
        assert(s_bShouldIncrement && "Ref-counting policy incremented when it should not have.");
        ++rCount;
        s_bShouldIncrement = false;
    }
    static bool decrementCount( ref_count_t& rCount ) {
        assert((s_nEndOfScope || s_bShouldDecrement) && "Ref-counting policy decremented when it should not have.");
        if(s_nEndOfScope)
        {
            --rCount;
            --s_nEndOfScope;
        }
        else if(s_bShouldDecrement)
        {
            --rCount;
            s_bShouldDecrement = false;
        }
        return rCount != 0;
    }
};

class cow_wrapper_client5
{
public:
    cow_wrapper_client5();
    explicit cow_wrapper_client5(int);
    ~cow_wrapper_client5();

    cow_wrapper_client5( const cow_wrapper_client5& );
    cow_wrapper_client5(cow_wrapper_client5&&) noexcept;
    cow_wrapper_client5& operator=( const cow_wrapper_client5& );
    cow_wrapper_client5& operator=(cow_wrapper_client5&&) noexcept;

    int queryUnmodified() const { return *maImpl; }
    sal_uInt32 use_count() const { return maImpl.use_count(); }

    bool operator==( const cow_wrapper_client5& rRHS ) const;
    bool operator!=( const cow_wrapper_client5& rRHS ) const;

private:
    o3tl::cow_wrapper< int, BogusRefCountPolicy > maImpl;
};

template< typename charT, typename traits >
inline std::basic_ostream<charT, traits> & operator <<(
    std::basic_ostream<charT, traits> & stream, const cow_wrapper_client5& client )
{
    return stream << client.queryUnmodified();
}

} // namespace o3tltests

#endif // INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */