blob: 5a62984028a257467f547cb1ff40cb90d009b256 (
plain) (
tree)
|
|
#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__
|