aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/Self.h
blob: 5a62984028a257467f547cb1ff40cb90d009b256 (plain) (blame)
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#ifndef   Self_h__
#define   Self_h__

#include <cstdlib>

namespace meow {

/*!
 *@brief 具有copy on write, 且擁有比C++更靈活的reference機制
 *
 *使用上就是把所有成員變數包到一個class/structure裡, 送給Self \n
 *例如以下
 *@code{.cpp}
 * class A {
 * private:
 *   struct Myself {
 *     int data;
 *     Myself(){
 *       data = 0;
 *     }
 *     ~Myself() {
 *     }
 *     Myself copyFrom(Myself const& ms) const {
 *       data = ms.data;
 *     }
 *   };
 *   Self<Myself> const self;
 * public:
 *   A(): self(true) { // self(true) 表示要建立實體, 即struct Myself
 *   }
 *   A(A const& a): self(false) { // for std::swap
 *     copyFrom(a);
 *   }
 *   // A(A const& a); // disable 模糊用法, 與上者二選一
 *   A(A const& a, bool reference): self(false) {
 *     if (reference) {
 *       referenceFrom(a);
 *     } else {
 *       copyFrom(a);
 *     }
 *   }
 *   ~A() {
 *   }
 *   void setMemeber(int k) {
 *     self()->data = k;  // self()->?? 可以有write權限
 *   }
 *   int getMemember(int wh) const {
 *     return self->data; // self->?? 只有const
 *   }
 *   A referenceFrom(A const& a) {
 *     self.referenceFrom(a.self);
 *   }
 *   A copyFrom(A const& a) {
 *     self.copyFrom(a.self);
 *   }
 *   A& operator=(A const& b) { // for std::swap
 *     copyFrom(b);
 *   }
 *   A& operator=(A const& b); // 避免諢亂用法
 * };
 * @endcode
 *
 *@author cathook
 *
 *@warning \c Self 這個class會把\c operator= 給disable掉, 所以使用它當
 *         kernel的class預設的 \c operator= 都會無法使用
 */
template<class Data>
class Self {
private:
  class Body {
  private:
    struct Kernel {
      Data    data_;
      int  counter_;
      Kernel() {
        counter_ = 1;
      }
      Kernel(Data const& data) {
        counter_ = 1;
        data_.copyFrom(data);
      }
    };
    Kernel *pointer_;
    int     counter_;
  public:
    Body() {
      counter_ = 1;
      pointer_ = new Kernel;
    }
    Body(Body const& b) {
      counter_ = 1;
      pointer_ = b.pointer_;
      pointer_->counter_++;
    }
    ~Body() {
      pointer_->counter_--;
      if (pointer_->counter_ <= 0) {
        delete pointer_;
      }
    }
    int attatch() { return ++counter_; }
    int detatch() { return --counter_; }
    Data const* access() const { return &(pointer_->data_); }
    Data      * modify() {
      if (pointer_->counter_ > 1) {
        pointer_->counter_--;
        pointer_ = new Kernel(pointer_->data_);
      }
      return &(pointer_->data_);
    }
  };
  Body*  body_;
  
  void clear(Body* body) {
    if (body != NULL) {
      if (body->detatch() <= 0) {
        delete body;
      }
    }
  }
public:
  /*!
   *@brief constructor
   *
   *@param [in] create_body 是否要new一個實體資料 (如果constructor完, 馬上就要
   *                        \c copyFrom() , 或是 \c referenceFrom() 的話
   *                        不太需要 new一個實體, 否則基本上都要
   */
  Self(bool create_body) {
    body_ = (create_body ? new Body() : NULL);
  }
  
  //! @brief 不允許copy constructor
  Self(Self const& b);
  
  //! @brief 解構子
  ~Self() {
    clear(body_);
  }
  
  //! @brief 回傳指向 Data const 的指標
  Data const* operator->() const {
    return body_->access();
  }
  
  //! @brief 回傳指向 Data 的指標, 如有需要, 這邊會做資料的duplicate
  Data* operator->() {
    return body_->modify();
  }
  
  //! @brief 回傳非const型態的自己
  Self& operator()() const {
    return *((Self*)this);
  }
  
  /*!
   *@brief 將給定的 \c Self 的資料複製到自己這裡
   *
   *@param [in] s 給定的\c Self
   *@return 無
   *
   *@note 與reference的差別是, copy之後若該給定的 \c Self 有資料修改, 
   *      this 這邊 \b 不會 被改到
   */
  void copyFrom(Self const& s) {
    Body* old = body_;
    body_ = new Body(*(s.body_));
    clear(old);
  }
  
  /*!
   *@brief 將自己reference 到給定的 \c Self
   *
   *@param [in] s 給定的\c Self
   *@return 無
   *
   *@note 把reference想像成指標會比較容易思考, 譬如 \c a.referenceFrom(b)
   *      \c b.referenceFrom(c) 相當於 \b a指向b原本指的記憶體位置,
   *      \b b指向c原本指的記憶體位置 , 之後更動c時, 只有b會被牽連
   *      
   */
  void referenceFrom(Self const& s) {
    if (body_ != s.body_) {
      clear(body_);
      body_ = s.body_;
      body_->attatch();
    }
  }
  
  /*!
   * @brief 比對兩個 \c Self 是否指向同一個reference
   *
   * @param [in] s 另一個 \c Self
   * @return \c true/false 表示是否為同一個reference
   */
  bool same(Self const& s) const {
    return (body_ == s.body_);
  }
  
  /*!
   * @brief 比對兩個 \c Self 的內容是否一樣
   * 
   * @param [in] s 另一個 \c Self
   * @return \c true/false 表示兩個內容是否一樣
   *
   * @note 需要用到 Data的equal()
   */
  bool equal(Self const& s) const {
    if (same(s) || body_->access() == s.body_->access()) return true;
    return (body_->access()->equal(*(s.body_->access())));
  }
  
  /*!
   * @brief 以reference作為判斷依據的小於判斷
   *
   * @param [in] s 另一個 \c Self
   * @return \c true/false 表示自己是否小於另一個 \c Self
   */
  bool referenceLess(Self const& s) const {
    return (body_ < s.body_);
  }
  
  //! @brief 將 \c operator= 給disable掉
  void operator=(Self const& a);
};

} // meow

#endif // Self_h__