aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/Self.h
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
commitd5052f1c296dddf51b3e83d59bf3e3c1952cb2d0 (patch)
tree16f7920c5079e0aefcf9509d2dbab59c464d42bd /meowpp/Self.h
parentbd58f63900410ec4764031f2e6de2d75e91434b3 (diff)
downloadmeow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.gz
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.zst
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.zip
big chnage
Diffstat (limited to 'meowpp/Self.h')
-rw-r--r--meowpp/Self.h230
1 files changed, 230 insertions, 0 deletions
diff --git a/meowpp/Self.h b/meowpp/Self.h
new file mode 100644
index 0000000..5a62984
--- /dev/null
+++ b/meowpp/Self.h
@@ -0,0 +1,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__