aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-10-21 17:51:03 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-10-21 17:51:03 +0800
commitf7770eea2208dba6f3171adcb268f446263275cb (patch)
tree6723c6bb73610e74aebc41317eda423a5dbd617d
parentbf5c9f2ae5c436aa7f59b28bb5e94b0362bfa358 (diff)
downloadmeow-f7770eea2208dba6f3171adcb268f446263275cb.tar
meow-f7770eea2208dba6f3171adcb268f446263275cb.tar.gz
meow-f7770eea2208dba6f3171adcb268f446263275cb.tar.bz2
meow-f7770eea2208dba6f3171adcb268f446263275cb.tar.lz
meow-f7770eea2208dba6f3171adcb268f446263275cb.tar.xz
meow-f7770eea2208dba6f3171adcb268f446263275cb.tar.zst
meow-f7770eea2208dba6f3171adcb268f446263275cb.zip
big change
-rw-r--r--meowpp/Makefile3
-rw-r--r--meowpp/meow/alloc.h203
-rw-r--r--meowpp/meow/alloc_test.cpp66
-rw-r--r--meowpp/meow/bases/basetypes.h (renamed from meowpp/utility/basetypes.h)49
-rw-r--r--meowpp/meow/bases/basetypes_test.cpp (renamed from meowpp/utility/basetypes_test.cpp)20
-rw-r--r--meowpp/meow/bases/object.h126
-rw-r--r--meowpp/meow/bases/object_test.cpp (renamed from meowpp/utility/object_test.cpp)8
-rw-r--r--meowpp/meow/bases/operation.h (renamed from meowpp/utility/operation.h)22
-rw-r--r--meowpp/meow/bases/operation_test.cpp (renamed from meowpp/utility/operation_test.cpp)16
-rw-r--r--meowpp/meow/bases/pointers.array_pointer_test.cpp79
-rw-r--r--meowpp/meow/bases/pointers.entry_pointer_test.cpp83
-rw-r--r--meowpp/meow/bases/pointers.h842
-rw-r--r--meowpp/meow/bases/pointers.weak_pointer_test.cpp52
-rw-r--r--meowpp/meow/bases/state.h (renamed from meowpp/utility/state.h)47
-rw-r--r--meowpp/meow/bases/state_test.cpp (renamed from meowpp/utility/state_test.cpp)8
-rw-r--r--meowpp/meow/debug/assert.debug_test.cpp (renamed from meowpp/debug/assert.debug_test.cpp)4
-rw-r--r--meowpp/meow/debug/assert.h (renamed from meowpp/debug/assert.h)42
-rw-r--r--meowpp/meow/debug/assert.nodebug_test.cpp (renamed from meowpp/debug/assert.nodebug_test.cpp)6
-rw-r--r--meowpp/meow/syntax.h (renamed from meowpp/syntax.h)21
-rw-r--r--meowpp/meow/syntax_test.cpp (renamed from meowpp/syntax_test.cpp)8
-rw-r--r--meowpp/meow/threading/condition.h101
-rw-r--r--meowpp/meow/threading/condition_test.cpp111
-rw-r--r--meowpp/meow/threading/event.h81
-rw-r--r--meowpp/meow/threading/event_test.cpp60
-rw-r--r--meowpp/meow/threading/lockers.h55
-rw-r--r--meowpp/meow/threading/lockers_test.cpp58
-rw-r--r--meowpp/meow/threading/locks.h129
-rw-r--r--meowpp/meow/threading/locks_test.cpp129
-rw-r--r--meowpp/meow/threading/queue.h155
-rw-r--r--meowpp/meow/threading/queue_test.cpp62
-rw-r--r--meowpp/meow/threading/thread.h143
-rw-r--r--meowpp/meow/threading/thread_test.cpp96
-rwxr-xr-xmeowpp/test.py35
-rw-r--r--meowpp/utility/factory.h383
-rw-r--r--meowpp/utility/factory_test.cpp161
-rw-r--r--meowpp/utility/object.h77
-rw-r--r--meowpp/utility/pointer.h174
-rw-r--r--meowpp/utility/pointer_test.cpp130
-rw-r--r--meowpp/utility/self.h244
-rw-r--r--meowpp/utility/self_test.cpp188
40 files changed, 2798 insertions, 1479 deletions
diff --git a/meowpp/Makefile b/meowpp/Makefile
index b087830..04ccf22 100644
--- a/meowpp/Makefile
+++ b/meowpp/Makefile
@@ -1,3 +1,4 @@
+MEOWPP_DIR ?= .
CXX ?= g++
CXXFLAGS ?= -g -Wall -Werror -std=c++11 -pedantic
@@ -5,7 +6,7 @@ CXXFLAGS ?= -g -Wall -Werror -std=c++11 -pedantic
.PHONY: meowpp_test meowpp_test_clean
meowpp_test:
- meowpp/test.py -c '$(CXX) $(CXXFLAGS)' -p '$(CURRENT_DIR)' -P '$(MEOWPP_DIR)'
+ $(MEOWPP_DIR)/test.py -c '$(CXX) $(CXXFLAGS)' -p '$(MEOWPP_DIR)' -P '$(MEOWPP_DIR)'
meowpp_test_clean:
find '$(MEOWPP_DIR)' -regex '^.*\.bin$$' -exec rm {} \;
diff --git a/meowpp/meow/alloc.h b/meowpp/meow/alloc.h
new file mode 100644
index 0000000..59736bc
--- /dev/null
+++ b/meowpp/meow/alloc.h
@@ -0,0 +1,203 @@
+/*!
+ * @file allocator.h
+ * @brief Supports a thread-safe allocator.
+ *
+ * @author cathook
+ */
+#ifndef __MEOW_ALLOCATOR_H__
+#define __MEOW_ALLOCATOR_H__
+
+#include <memory>
+#include <cstdlib>
+#include <new>
+#include <cstddef>
+
+
+#ifndef MEOW_NO_THREADING_SAFE_MEMORY
+
+#include <meow/threading/locks.h>
+
+namespace meow {
+
+namespace {
+
+//! Lock for the new/delete operation.
+RecurLock thread_safe_lock;
+
+}
+
+}
+
+#define MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE thread_safe_lock.Acquire()
+#define MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE thread_safe_lock.Release()
+
+#else // MEOW_NO_THREADING_SAFE_MEMORY
+
+#define MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE
+#define MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE
+
+#endif // MEOW_NO_THREADING_SAFE_MEMORY
+
+namespace meow {
+
+namespace {
+
+class ArrayBufferManager {
+ private:
+
+ //! Stores the information about the array size.
+ struct ArrayBuffer {
+ //! Stores the size of the array who is at the address of buffer.
+ size_t num_of_entry;
+ size_t size_per_entry;
+
+ //! Points to the buffer.
+ char buffer[1];
+ };
+
+ /*!
+ * @brief Creates an ArrayBuffer with speicfied buffer size.
+ * @param [in] buffer_size Buffer size.
+ */
+ static ArrayBuffer* CreateArrayBuffer(size_t buffer_size) {
+ return reinterpret_cast<ArrayBuffer*>(
+ malloc(sizeof(ArrayBuffer) + buffer_size));
+ }
+
+ /*!
+ * @brief Gets the address of the corrosponding instance of ArrayBuffer.
+ * @param [in] buffer Address of the buffer.
+ */
+ static ArrayBuffer* GetArrayBufferFromBuffer(char* buffer) {
+ return reinterpret_cast<ArrayBuffer*>(
+ buffer - offsetof(ArrayBuffer, buffer));
+ }
+
+ public:
+
+ /*!
+ * @brief Allocates an array.
+ * @param [in] size_per_entry Size per entry.
+ * @param [in] num_of_entry Array size.
+ * @return The address of the buffer for the allocated array.
+ */
+ static char* Alloc(size_t size_per_entry, size_t num_of_entry) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ ArrayBuffer* ptr = CreateArrayBuffer(size_per_entry * num_of_entry);
+ ptr->size_per_entry = size_per_entry;
+ ptr->num_of_entry = num_of_entry;
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ return ptr->buffer;
+ }
+
+ /*!
+ * @brief Gets the size of the array by the address of the buffer.
+ * @param [in] buffer address of the buffer.
+ */
+ static size_t ArraySize(char* buffer) {
+ return GetArrayBufferFromBuffer(buffer)->num_of_entry;
+ }
+
+ /*!
+ * @brief Gets the size of each entry by the address of the buffer.
+ * @param [in] buffer address of the buffer.
+ */
+ static size_t EntrySize(char* buffer) {
+ return GetArrayBufferFromBuffer(buffer)->size_per_entry;
+ }
+
+ /*!
+ * @brief Frees an array.
+ * @param [in] buffer address of the buffer.
+ */
+ static void Free(char* buffer) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ free(reinterpret_cast<void*>(GetArrayBufferFromBuffer(buffer)));
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ }
+};
+
+}
+
+
+/*!
+ * @brief News an element.
+ * @param [in] args Arguments for calling the constructor of the specified Type.
+ */
+template<typename Type, typename... Args>
+inline Type* NewEntry(Args... args) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ Type* ret = new Type(args...);
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ return ret;
+}
+
+
+/*!
+ * @brief Deletes an element.
+ */
+template<typename Type>
+inline Type* DeleteEntry(Type* obj) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ delete obj;
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ return NULL;
+}
+
+
+/*!
+ * @brief News an array of elements.
+ * @param [in] args Arguments for calling the constructor of the specified Type.
+ */
+template<typename Type, typename... Args>
+inline Type* NewArray(size_t size, Args... args) {
+ Type* ret = reinterpret_cast<Type*>(
+ ArrayBufferManager::Alloc(sizeof(Type), size));
+ for (size_t i = 0; i < size; ++i) {
+ new(ret + i) Type(args...);
+ }
+ return ret;
+}
+
+
+/*!
+ * @brief Deletes an array.
+ */
+template<typename Type>
+inline Type* DeleteArray(Type* obj) {
+ char* buffer = reinterpret_cast<char*>(obj);
+ size_t array_len = ArrayBufferManager::ArraySize(buffer);
+ size_t entry_size = ArrayBufferManager::EntrySize(buffer);
+ for (size_t i = 0; i < array_len; ++i) {
+ reinterpret_cast<Type*>(buffer + i * entry_size)->~Type();
+ }
+ ArrayBufferManager::Free(reinterpret_cast<char*>(obj));
+ return NULL;
+}
+
+
+/*!
+ * @brief Thread-safe allocator.
+ */
+template<typename Type>
+class Alloc : public std::allocator<Type> {
+ public:
+ virtual ~Alloc() {}
+
+ Type* allocate(std::size_t n, const void* hint = NULL) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ std::allocator<Type>::allocate(n, hint);
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ }
+
+ void deallocate(Type* p, std::size_t n) {
+ MEOW_ALLOC_THREAD_SAFE_LOCK_ACQUIRE;
+ std::allocator<Type>::deallocate(n);
+ MEOW_ALLOC_THREAD_SAFE_LOCK_RELEASE;
+ }
+};
+
+
+}
+
+#endif // __MEOW_ALLOCATOR_H__
diff --git a/meowpp/meow/alloc_test.cpp b/meowpp/meow/alloc_test.cpp
new file mode 100644
index 0000000..90e6faa
--- /dev/null
+++ b/meowpp/meow/alloc_test.cpp
@@ -0,0 +1,66 @@
+#include <cstdio>
+#include <cmath>
+#include <chrono>
+
+#include <meow/syntax.h>
+#include <meow/alloc.h>
+#include <meow/threading/thread.h>
+
+class LongInit {
+ public:
+ void hi() {}
+ LongInit(int t) {
+ std::this_thread::sleep_for(std::chrono::seconds(t));
+ }
+ LongInit() : LongInit(1) {}
+};
+
+class T1 : public meow::Thread {
+ private:
+ void Run() {
+ LongInit* a = meow::NewEntry<LongInit>(3);
+ a->hi();
+ Assert(meow::DeleteEntry(a) == NULL, "delete not null");
+ }
+};
+
+class T2 : public meow::Thread {
+ private:
+ void Run() {
+ LongInit* a = meow::NewArray<LongInit>(5);
+ a->hi();
+ meow::DeleteArray(a);
+ }
+};
+
+class Obj {
+ private:
+ int* flag_;
+ public:
+ Obj(int* flag) : flag_(flag) { (*flag_) += 1; }
+ ~Obj() { (*flag_) -= 1; }
+};
+
+int main() {
+ T1 t1;
+ T2 t2;
+ std::chrono::system_clock::time_point tp1 = std::chrono::system_clock::now();
+ t1.Start();
+ t2.Start();
+ t1.Join();
+ t2.Join();
+ std::chrono::system_clock::time_point tp2 = std::chrono::system_clock::now();
+ long int k = std::chrono::duration_cast<std::chrono::microseconds>(
+ tp2 - tp1).count();
+ Assert(fabs(k / 1e6 - 8) < 5e-2, "Time cost error = %f / 8.0", k / 1e6);
+
+ with (int flag = 0) {
+ with (Obj* obj_ptr = meow::NewArray<Obj>(3, &flag)) {
+ Assert(flag == 3, "array no construct... (%d)", flag);
+ obj_ptr = meow::DeleteArray(obj_ptr);
+ Assert(flag == 0, "array no destruct...");
+ Assert(obj_ptr == NULL, "array no destruct...(%d)", flag);
+ }
+ }
+ return 0;
+}
diff --git a/meowpp/utility/basetypes.h b/meowpp/meow/bases/basetypes.h
index 2efd64e..3326caf 100644
--- a/meowpp/utility/basetypes.h
+++ b/meowpp/meow/bases/basetypes.h
@@ -1,10 +1,11 @@
-#ifndef __MEOWPP_UTILITY_BASETYPES_H__
-#define __MEOWPP_UTILITY_BASETYPES_H__
+#ifndef __MEOW_BASES_BASETYPES_H__
+#define __MEOW_BASES_BASETYPES_H__
#include <cstdint>
-#include "object.h"
-#include "../debug/assert.h"
+#include <meow/alloc.h>
+#include <meow/bases/object.h>
+#include <meow/debug/assert.h>
namespace meow {
@@ -23,16 +24,8 @@ class BaseNumberType : public Object {
public:
BaseNumberType() : BaseNumberType(static_cast<DataType>(0)) {}
BaseNumberType(BaseNumberType const& b) : BaseNumberType(b.value_) {}
- BaseNumberType(DataType const& arg_init_value) : value_(arg_init_value) {}
+ BaseNumberType(DataType const& value) : value_(value) {}
~BaseNumberType() {}
- Object* Copy() const { return new BaseNumberType(value_); }
- Object* CopyFrom(Object const* ptr) {
- value_ = static_cast<BaseNumberType const*>(ptr)->value_;
- return this;
- }
- bool Equals(Object const* ptr) const {
- return (value_ == static_cast<BaseNumberType const*>(ptr)->value_);
- }
operator DataType() const { return value_; }
BaseNumberType& operator=(DataType const& b) { value_ = b; return *this; }
BaseNumberType& operator+=(DataType const& b) { value_ += b; return *this; }
@@ -44,6 +37,16 @@ class BaseNumberType : public Object {
BaseNumberType& operator^=(DataType const& b) { value_ ^= b; return *this; }
BaseNumberType& operator<<=(int64_t const& b) { value_ <<= b; return *this; }
BaseNumberType& operator>>=(int64_t const& b) { value_ >>= b; return *this; }
+ BaseNumberType& CopyFrom(BaseNumberType const& b) {
+ return operator=(b.value_);
+ }
+ bool Equals(BaseNumberType const& b) const { return value_ == b.value_; }
+
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(BaseNumberType);
+ DELEGATE_MEOW_OBJECT_COPYFROM(BaseNumberType);
+ DELEGATE_MEOW_OBJECT_EQUALS(BaseNumberType);
};
@@ -61,20 +64,22 @@ class BaseFloatingType : public Object {
BaseFloatingType(BaseFloatingType const& b) : BaseFloatingType(b.value_) {}
BaseFloatingType(DataType const& arg_init_value) : value_(arg_init_value) {}
~BaseFloatingType() {}
- Object* Copy() const { return new BaseFloatingType(value_); }
- Object* CopyFrom(Object const* ptr) {
- value_ = static_cast<BaseFloatingType const*>(ptr)->value_;
- return this;
- }
- bool Equals(Object const* ptr) const {
- return (value_ == static_cast<BaseFloatingType const*>(ptr)->value_);
- }
operator DataType() const { return value_; }
BaseFloatingType& operator=(DataType const& b) { value_ = b; return *this; }
BaseFloatingType& operator+=(DataType const& b) { value_ += b; return *this; }
BaseFloatingType& operator-=(DataType const& b) { value_ -= b; return *this; }
BaseFloatingType& operator*=(DataType const& b) { value_ *= b; return *this; }
BaseFloatingType& operator/=(DataType const& b) { value_ /= b; return *this; }
+ BaseFloatingType& CopyFrom(BaseFloatingType const& b) {
+ return operator=(b.value_);
+ }
+ bool Equals(BaseFloatingType const& b) const { return value_ == b.value_; }
+
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(BaseFloatingType);
+ DELEGATE_MEOW_OBJECT_COPYFROM(BaseFloatingType);
+ DELEGATE_MEOW_OBJECT_EQUALS(BaseFloatingType);
};
}
@@ -95,4 +100,4 @@ typedef BaseFloatingType<long double> LDouble; //!< Long double.
} // meow
-#endif // __MEOWPP_UTILITY_BASETYPES_H__
+#endif // __MEOW_BASES_BASETYPES_H__
diff --git a/meowpp/utility/basetypes_test.cpp b/meowpp/meow/bases/basetypes_test.cpp
index 1a7c076..a210e8b 100644
--- a/meowpp/utility/basetypes_test.cpp
+++ b/meowpp/meow/bases/basetypes_test.cpp
@@ -1,7 +1,8 @@
-#include <meowpp/utility/basetypes.h>
+#include <meow/bases/basetypes.h>
int main() {
meow::Int32 a;
+ Assert(a.copyable(), "");
Assert(a == 0, "");
Assert(0 == a, "");
Assert(!a, "");
@@ -24,17 +25,22 @@ int main() {
Assert((~a) == ~10, "");
a += 3;
Assert(a == 13, "");
+ a -= 3;
+ Assert(a == 10, "");
+ a <<= 1;
+ Assert(a == 20, "");
+ a >>= 2;
+ Assert(a == 5, "");
meow::Double b(a);
- Assert(b == 13.0, "");
- Assert(b == 13, "");
- meow::Double* k = static_cast<meow::Double*>(b.Copy());
+ Assert(b != 13.0, "");
+ meow::Double* k = dynamic_cast<meow::Double*>(b.Copy());
Assert((*k) == b, "");
Assert(k->Equals(&b), "");
(*k) = 5;
- Assert((*k) == 5, "");
+ Assert((*k) == 5.0, "");
Assert(k->CopyFrom(&b) == k, "");
- Assert((*k) == 13, "");
- delete k;
+ Assert((*k) != 13, "");
+ DeleteEntry(k);
return 0;
}
diff --git a/meowpp/meow/bases/object.h b/meowpp/meow/bases/object.h
new file mode 100644
index 0000000..7953cd5
--- /dev/null
+++ b/meowpp/meow/bases/object.h
@@ -0,0 +1,126 @@
+/*!
+ * @file object.h
+ * @brief Contains a base class for most of all the classes in meowpp.
+ *
+ * @author cathook
+ */
+
+#ifndef __MEOW_BASES_OBJECT_H__
+#define __MEOW_BASES_OBJECT_H__
+
+#include <cstdlib>
+
+namespace meow {
+
+
+/*!
+ * @brief The base class.
+ */
+class Object {
+ protected:
+
+ /*!
+ * @brief A protected constructor to prevent developers create an instance of
+ * Object directly.
+ */
+ Object() {}
+
+ /*!
+ * @brief Disable the copy operation.
+ */
+ Object(Object const& b);
+
+ public:
+
+ /*!
+ * @brief Virtual destructor.
+ */
+ virtual ~Object() {}
+
+ /*!
+ * @brief Returns whether this object is an non-copyable type or not.
+ * @return false
+ *
+ * Default is no.
+ */
+ virtual bool copyable() const {
+ return false;
+ }
+
+ /*!
+ * @brief A simple way for user to setup whether the class is copyable or not.
+ * @param [in] x true or false.
+ */
+#define SET_MEOW_OBJECT_COPYABLE(x) bool copyable() const { return x; }
+
+ /*!
+ * @brief Creates a copy of itself and return the pointer to it.
+ *
+ * It will return NULL in default if you don't implement it.
+ */
+ virtual Object* Copy() const {
+ return NULL;
+ }
+
+ /*!
+ * @brief A simple way for user to implement the method "Copy".
+ * @param [in] X The class name.
+ *
+ * By calling the copy constructor.
+ */
+#define IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(X) \
+ Object* Copy() const { \
+ return dynamic_cast<Object*>(NewEntry<X>(*this)); \
+ }
+
+ /*!
+ * @brief Copies data from another object.
+ * @param [in] ptr Points to another object.
+ *
+ * It will return NULL in default if you don't implement it.
+ */
+ virtual Object* CopyFrom(Object const* ptr) {
+ return NULL;
+ }
+
+ /*!
+ * @brief A simple way for user to implement the method "CopyFrom".
+ * @param [in] X The class name.
+ *
+ * By calling the CopyFrom method in the user defined class.
+ */
+#define DELEGATE_MEOW_OBJECT_COPYFROM(X) \
+ Object* CopyFrom(Object const* b) { \
+ return dynamic_cast<Object*>(&CopyFrom(*dynamic_cast<X const*>(b))); \
+ }
+
+ /*!
+ * @brief Returns whether it equals to another object or not.
+ * @param [in] ptr Points to another object.
+ *
+ * It will always return false if you don't implement it.
+ */
+ virtual bool Equals(Object const* ptr) const {
+ return false;
+ }
+
+ /*!
+ * @brief A simple way for user to implement the method "Equals".
+ * @param [in] X The class name.
+ *
+ * By calling the Equals method in the user defined class.
+ */
+#define DELEGATE_MEOW_OBJECT_EQUALS(X) \
+ bool Equals(Object const* b) const { \
+ return Equals(*dynamic_cast<X const*>(b)); \
+ }
+
+ /*!
+ * @brief Disable the copy operator.
+ */
+ Object& operator=(Object const& b);
+};
+
+} // meow
+
+#endif // __MEOW_BASES_OBJECT_H__
diff --git a/meowpp/utility/object_test.cpp b/meowpp/meow/bases/object_test.cpp
index 5c60440..1dfbe77 100644
--- a/meowpp/utility/object_test.cpp
+++ b/meowpp/meow/bases/object_test.cpp
@@ -1,7 +1,7 @@
-#include <meowpp/debug/assert.h>
-#include <meowpp/utility/object.h>
-#include <meowpp/utility/object.h>
-#include <meowpp/utility/object.h>
+#include <meow/debug/assert.h>
+#include <meow/bases/object.h>
+#include <meow/bases/object.h>
+#include <meow/bases/object.h>
static bool destructor_be_called = false;
diff --git a/meowpp/utility/operation.h b/meowpp/meow/bases/operation.h
index d595668..3685459 100644
--- a/meowpp/utility/operation.h
+++ b/meowpp/meow/bases/operation.h
@@ -5,13 +5,13 @@
* @author cathook
*/
-#ifndef __MEOWPP_UTILITY_OPERATION_H__
-#define __MEOWPP_UTILITY_OPERATION_H__
+#ifndef __MEOW_BASES_OPERATION_H__
+#define __MEOW_BASES_OPERATION_H__
-#include "../debug/assert.h"
-#include "object.h"
-#include "pointer.h"
-#include "state.h"
+#include <meow/debug/assert.h>
+#include <meow/bases/object.h>
+#include <meow/bases/pointers.h>
+#include <meow/bases/state.h>
namespace meow {
@@ -50,8 +50,8 @@ class Operation : public Object {
* to the output elements.
* @return The state of the operation (ex: fail, success, ...)
*/
- virtual State Operate(Pointer<Object const> const * inputs_ptr,
- Pointer<Object> const * outputs_ptr) const = 0;
+ virtual State Operate(ArrayPointer<Object const> const * inputs_ptr,
+ ArrayPointer<Object> const * outputs_ptr) const = 0;
/*!
* @brief Gets the number of inputs for the operation.
@@ -69,12 +69,12 @@ class Operation : public Object {
return outputs_size_;
}
-#ifdef MEOWPP_UTILITY_OPERATION_TESTING
+#ifdef MEOW_BASES_OPERATION_TESTING
friend class OperationTest;
-#endif // MEOWPP_UTILITY_OPERATION_TESTING
+#endif // MEOW_BASES_OPERATION_TESTING
};
} // meow
-#endif // __MEOWPP_UTILITY_OPERATION_H__
+#endif // __MEOW_BASES_OPERATION_H__
diff --git a/meowpp/utility/operation_test.cpp b/meowpp/meow/bases/operation_test.cpp
index def8d84..4587793 100644
--- a/meowpp/utility/operation_test.cpp
+++ b/meowpp/meow/bases/operation_test.cpp
@@ -1,10 +1,10 @@
-#include <meowpp/utility/operation.h>
-#include <meowpp/utility/operation.h>
-#include <meowpp/utility/operation.h>
+#define MEOW_BASES_OPERATION_TESTING
-#include <meowpp/debug/assert.h>
+#include <meow/bases/operation.h>
+#include <meow/debug/assert.h>
namespace meow {
+
class OperationTest {
private:
class States : public State {
@@ -17,16 +17,16 @@ class OperationTest {
int id;
Oper1(int k) : Operation(3, 5), id(k) {}
Object* Copy() const { return new Oper1(id); }
- State Operate(Pointer<Object const> const * inputs,
- Pointer<Object> const* outputs) const {
+ State Operate(ArrayPointer<Object const> const * inputs,
+ ArrayPointer<Object> const* outputs) const {
return States::CASE1;
}
};
class Oper2 : public Operation {
public:
Oper2() : Operation(2, 7) {}
- State Operate(Pointer<Object const> const * inputs,
- Pointer<Object> const* outputs) const {
+ State Operate(ArrayPointer<Object const> const * inputs,
+ ArrayPointer<Object> const* outputs) const {
return States::CASE2;
}
};
diff --git a/meowpp/meow/bases/pointers.array_pointer_test.cpp b/meowpp/meow/bases/pointers.array_pointer_test.cpp
new file mode 100644
index 0000000..5c3495a
--- /dev/null
+++ b/meowpp/meow/bases/pointers.array_pointer_test.cpp
@@ -0,0 +1,79 @@
+#define MEOW_POINTER_TEST
+
+#include <meow/bases/pointers.h>
+#include <meow/syntax.h>
+
+#include <cstdio>
+
+using namespace meow;
+
+int global_counter = 0;
+
+class ElementBase {
+ public:
+ virtual ~ElementBase() {}
+};
+
+class Element : public ElementBase {
+ private:
+ int* counter_;
+ public:
+ Element() : counter_(&global_counter) { (*counter_) += 1; }
+ Element(int* ct) : counter_(ct) { (*counter_) += 1; }
+ ~Element() { (*counter_) -= 1; }
+ void hi() { fprintf(stderr, "hi!!\n"); }
+};
+
+int main() {
+ with (ArrayPointer<Element> ap(5)) {
+ Assert(global_counter == 5, "");
+ Assert(ap.address() != NULL, "");
+ Assert(ap.counter() == 1, "");
+ Assert(ap.begin_index() == 0, "");
+ Assert(ap.end_index() == 5, "");
+ }
+ Assert(global_counter == 0, "Not destructor?");
+ with (int counter = 0) {
+ with (ArrayPointer<ElementBase> apb) {
+ Assert(apb.address() == NULL, "");
+ with (ArrayPointer<Element> ap(7, &counter)) {
+ Assert(counter == 7, "");
+ with (ArrayPointer<Element> ap2(ap)) {
+ Assert(counter == 7, "");
+ Assert(ap.address() == ap2.address(), "");
+ Assert(ap.ptr_counter() == ap2.ptr_counter(), "");
+ Assert(ap.counter() == 2, "");
+ Assert(ap2.begin_index() == 0, "");
+ Assert(ap2.end_index() == 7, "");
+ ap2 += 2;
+ Assert(ap.counter() == 2, "");
+ Assert(ap2.begin_index() == -2, "");
+ Assert(ap2.end_index() == 5, "");
+ ap2 -= 3;
+ Assert(ap2.begin_index() == 1, "");
+ Assert(ap2.end_index() == 8, "");
+ with (ArrayPointer<Element> ap3(ap2 + 3)) {
+ Assert(ap3.counter() == 3, "");
+ Assert(ap3.begin_index() == -2, "");
+ Assert(ap3.end_index() == 5, "");
+ for (int i = -2; i < 5; ++i) {
+ ap3[i].hi();
+ }
+ }
+ Assert(ap.counter() == 2, "");
+ }
+ Assert(counter == 7, "");
+ Assert(ap.counter() == 1, "");
+ apb = (ArrayPointer<ElementBase>)ap;
+ Assert(ap.ptr_counter() == apb.ptr_counter(), "");
+ Assert(ap.counter() == 2, "");
+ }
+ Assert(counter == 7, "");
+ Assert(apb.counter() == 1, "");
+ fprintf(stderr, "goout111\n");
+ }
+ fprintf(stderr, "goout222\n");
+ Assert(counter == 0, "");
+ }
+ return 0;
+}
diff --git a/meowpp/meow/bases/pointers.entry_pointer_test.cpp b/meowpp/meow/bases/pointers.entry_pointer_test.cpp
new file mode 100644
index 0000000..a0ce772
--- /dev/null
+++ b/meowpp/meow/bases/pointers.entry_pointer_test.cpp
@@ -0,0 +1,83 @@
+#define MEOW_POINTER_TEST
+
+#include <meow/syntax.h>
+#include <meow/bases/pointers.h>
+
+#include <cstdio>
+
+using namespace meow;
+
+int global_counter = 0;
+
+class ElementBase {
+ public:
+ virtual ~ElementBase() {}
+};
+
+class Element : public ElementBase {
+ private:
+ int* counter_;
+ public:
+ Element() : counter_(&global_counter) { (*counter_) += 1; }
+ Element(int* ct) : counter_(ct) { (*counter_) += 1; }
+ ~Element() { (*counter_) -= 1; }
+ void hi() { fprintf(stderr, "hi!!\n"); }
+};
+
+int main() {
+ with (EntryPointer<Element> ap(EPCreateFlag)) {
+ Assert(global_counter == 1, "");
+ Assert(ap.address() != NULL, "");
+ Assert(ap.counter() == 1, "");
+ Assert(ap.is_entry_of_array() == false, "");
+ }
+ Assert(global_counter == 0, "Not destructor?");
+ with (int counter = 0) {
+ with (EntryPointer<ElementBase> apb) {
+ Assert(apb.address() == NULL, "");
+ Assert(apb.is_entry_of_array() == false, "");
+ with (EntryPointer<Element> ap(EPCreateFlag, &counter)) {
+ Assert(counter == 1, "");
+ Assert(ap.is_entry_of_array() == false, "");
+ with (EntryPointer<Element> ap2(ap)) {
+ Assert(counter == 1, "");
+ Assert(ap.address() == ap2.address(), "");
+ Assert(ap.ptr_counter() == ap2.ptr_counter(), "");
+ Assert(ap.counter() == 2, "");
+ with (EntryPointer<Element> ap3(ap2)) {
+ Assert(ap3.counter() == 3, "");
+ Assert(ap3.is_entry_of_array() == false, "");
+ ap3->hi();
+ }
+ Assert(ap.counter() == 2, "");
+ }
+ Assert(counter == 1, "");
+ Assert(ap.counter() == 1, "");
+ apb = (EntryPointer<ElementBase>)ap;
+ Assert(ap.ptr_counter() == apb.ptr_counter(), "");
+ Assert(ap.counter() == 2, "");
+ }
+ Assert(counter == 1, "");
+ Assert(apb.counter() == 1, "");
+ fprintf(stderr, "goout111\n");
+ }
+ fprintf(stderr, "goout222\n");
+ Assert(counter == 0, "");
+ }
+ EntryPointer<int> xx;
+ with (ArrayPointer<int> kk(3, 5)) {
+ xx = kk + 2;
+ (*xx) = 1;
+ for (int i = 0; i < 3; ++i) {
+ if (i == 2) {
+ Assert(kk[i] == 1, "");
+ } else {
+ Assert(kk[i] == 5, "");
+ }
+ }
+ Assert(kk.counter() == 2, "");
+ Assert(kk.ptr_counter() == xx.ptr_counter(), "");
+ }
+ Assert(xx.counter() == 1, "");
+ return 0;
+}
diff --git a/meowpp/meow/bases/pointers.h b/meowpp/meow/bases/pointers.h
new file mode 100644
index 0000000..9305bcf
--- /dev/null
+++ b/meowpp/meow/bases/pointers.h
@@ -0,0 +1,842 @@
+/*!
+ * @file pointer.h
+ * @brief Contains a pointer class which has a counter-mechanism to prevent
+ * memory leak.
+ *
+ * @author cathook
+ */
+
+#ifndef __MEOW_BASES_POINTER_H__
+#define __MEOW_BASES_POINTER_H__
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+#include <meow/bases/object.h>
+#include <meow/debug/assert.h>
+#include <meow/alloc.h>
+
+namespace meow {
+
+/*!
+ * @brief A normal pointer which is a child of the base class Object.
+ */
+template<typename Type>
+class WeakPointer : public Object {
+ private:
+ Type* address_;
+
+ public:
+ /*!
+ * @brief Points to NULL.
+ */
+ WeakPointer() : WeakPointer(NULL) {}
+
+ /*!
+ * @brief Points to the address pointed by the specified pointer.
+ */
+ WeakPointer(WeakPointer const & ptr2) : WeakPointer(address()) {}
+
+ /*!
+ * @brief Points to the specified address.
+ */
+ WeakPointer(Type* addr) : address_(addr) {}
+
+ /*!
+ * @brief Destructor.
+ * @note It will not delete/free the memory!
+ */
+ ~WeakPointer() {}
+
+ /*!
+ * @brief Returns the address it points to.
+ */
+ Type* address() const { return address_; }
+
+ /*!
+ * @brief Returns the address it points to.
+ */
+ operator Type*() const { return address(); }
+
+ /*!
+ * @brief Returns the address it points to.
+ */
+ Type* operator->() const { return address(); }
+
+ /*!
+ * @brief Returns the reference of the address it points to.
+ */
+ Type& operator*() const { return *address(); }
+
+ /*!
+ * @brief Returns an positive offseted pointer of myself.
+ * @param [in] diff number of offset.
+ */
+ WeakPointer operator+(ptrdiff_t const & diff) const {
+ return WeakPointer(address() + diff);
+ }
+
+ /*!
+ * @brief Returns an negative offseted pointer of myself.
+ * @param [in] diff number of offset.
+ */
+ WeakPointer operator-(ptrdiff_t const & diff) const {
+ return operator+(-diff);
+ }
+
+ /*!
+ * @brief Offsets myself positively and returns *this.
+ * @param [in] diff number of offset.
+ */
+ WeakPointer& operator+=(ptrdiff_t const & diff) {
+ address_ += diff;
+ return *this;
+ }
+
+ /*!
+ * @brief Offsets myself negitavely and returns *this.
+ * @param [in] diff number of offset.
+ */
+ WeakPointer& operator-=(ptrdiff_t const & diff) {
+ return operator+=(-diff);
+ }
+
+ /*!
+ * @brief Returns the distance between another WeakPointer.
+ * @param [in] t Another WeakPointer.
+ */
+ ptrdiff_t operator-(WeakPointer const & t) const {
+ return address() - t.address();
+ }
+
+ /*!
+ * @brief Assign operator.
+ */
+ WeakPointer& operator=(WeakPointer const & t) { return CopyFrom(t); }
+
+ /*!
+ * @brief Assign method.
+ */
+ WeakPointer& CopyFrom(WeakPointer const & t) {
+ address_ = t.address_;
+ return *this;
+ }
+
+ /*!
+ * @brief Is-equal operator.
+ */
+ bool operator==(WeakPointer const & t) const { return Equals(t); }
+
+ /*!
+ * @brief Is-equal method.
+ * @brief true if the addresses pointed to are same.
+ */
+ bool Equals(WeakPointer const & t) const { return address() == t.address(); }
+
+ /*!
+ * @brief Less-than operator.
+ */
+ bool operator<(WeakPointer const & t) const { return LessThan(t); }
+
+ /*!
+ * @brief Less-than method.
+ * @brief true if my address is less than the other address.
+ */
+ bool LessThan(WeakPointer const & t) const {
+ return address() < t.address();
+ }
+
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(WeakPointer);
+ DELEGATE_MEOW_OBJECT_COPYFROM(WeakPointer);
+ DELEGATE_MEOW_OBJECT_EQUALS(WeakPointer);
+};
+
+namespace {
+
+/*!
+ * @brief For the data shared by difference type of Pointer.
+ */
+class PointerTypesShareCounter {
+ protected:
+ size_t* counter_;
+
+ public:
+ friend size_t* GetPointerCounter(PointerTypesShareCounter const* ptr);
+};
+
+size_t* GetPointerCounter(PointerTypesShareCounter const* ptr) {
+ return ptr->counter_;
+}
+
+}
+
+
+/*!
+ * @brief For pointing to an array.
+ */
+template<typename Type>
+class ArrayPointer : public Object, public PointerTypesShareCounter {
+ private:
+
+ //! Address of the array.
+ Type* address_;
+
+ //! The first valid index.
+ ssize_t begin_index_;
+
+ //! The next one of the last valid index.
+ ssize_t end_index_;
+
+ template<typename Type2>
+ void Attach_(ArrayPointer<Type2> const & ptr2) {
+ address_ = reinterpret_cast<Type*>(ptr2.address());
+ counter_ = GetPointerCounter(
+ dynamic_cast<PointerTypesShareCounter const*>(&ptr2));
+ (*counter_) += 1;
+ begin_index_ = ptr2.begin_index();
+ end_index_ = ptr2.end_index();
+ }
+
+ void Detach_() {
+ (*counter_) -= 1;
+ if (*counter_ == 0) {
+ address_ += reinterpret_cast<ptrdiff_t>(begin_index_);
+ if (address_ != NULL)
+ DeleteArray(address_);
+ DeleteEntry(counter_);
+ }
+ }
+
+ ArrayPointer(Type* addr, size_t len) :
+ address_(addr),
+ begin_index_(0),
+ end_index_(len) {
+ counter_ = NewEntry<size_t>(1);
+ }
+
+ template<typename Type2>
+ ArrayPointer(ArrayPointer<Type2> const & ptr2, ssize_t offset) {
+ Attach_(ptr2);
+ Offset(offset);
+ }
+
+ public:
+
+ /*!
+ * @brief Points to NULL.
+ */
+ ArrayPointer() : ArrayPointer(reinterpret_cast<Type*>(NULL), 0) {}
+
+ /*!
+ * @brief Points to another array with same type.
+ * @param [in] ptr2 Pointer of another array.
+ */
+ ArrayPointer(ArrayPointer const & ptr2) :
+ ArrayPointer(ptr2, 0) {}
+
+ /*!
+ * @brief Points to another array.
+ * @param [in] ptr2 Pointer of another array.
+ */
+ template<typename Type2>
+ ArrayPointer(ArrayPointer<Type2> const & ptr2) :
+ ArrayPointer(ptr2, 0) {}
+
+ /*!
+ * @brief Creates an array and then points to it.
+ * @param [in] len Size of the array.
+ * @param [in] args Arguments of the constructor of the Type.
+ */
+ template<typename... Args>
+ ArrayPointer(size_t len, Args... args) :
+ ArrayPointer(NewArray<Type>(len, args...), len) {}
+
+ /*!
+ * @brief Desturctor.
+ *
+ * It will automatically delete the array if nobody points to that array after
+ * itself be destroyed.
+ */
+ ~ArrayPointer() { Detach_(); }
+
+ /*!
+ * @brief Gets the address of the array.
+ */
+ Type* address() const { return address_; }
+
+ /*!
+ * @brief Returns the number of pointer points to it.
+ */
+ size_t counter() const { return *counter_; }
+
+#ifdef MEOW_POINTER_TEST
+ /*!
+ * @brief For testing.
+ */
+ size_t* ptr_counter() const { return counter_; }
+#endif // MEOW_POINTER_TEST
+
+ /*!
+ * @brief Returns the smallest valid index.
+ */
+ ssize_t begin_index() const { return begin_index_; }
+
+ /*!
+ * @brief Returns the one after the largest valid index.
+ */
+ ssize_t end_index() const { return end_index_; }
+
+ /*!
+ * @brief Offsets a specified number.
+ * @param [in] offs Offset mount.
+ */
+ ArrayPointer& Offset(ssize_t offs) {
+ address_ += reinterpret_cast<ptrdiff_t>(offs);
+ begin_index_ -= offs;
+ end_index_ -= offs;
+ return *this;
+ }
+
+ /*!
+ * @brief Returns the array.
+ */
+ operator Type*() const { return address(); }
+
+ /*!
+ * @brief Transformates to WeakPointer.
+ */
+ operator WeakPointer<Type>() const { return WeakPointer<Type>(address()); }
+
+ /*!
+ * @brief Transformates to another type.
+ */
+ template<typename Type2>
+ operator ArrayPointer<Type2>() const { return ArrayPointer<Type2>(*this); }
+
+ /*!
+ * @brief Gets the address of the first element of the array.
+ */
+ Type* operator->() const { return address(); }
+
+ /*!
+ * @brief Gets the reference of the first element of the array.
+ */
+ Type& operator*() const { return *address(); }
+
+ /*!
+ * @brief Gets the reference of the i-th element of the array.
+ * @param [in] index Index of the element.
+ */
+ Type& operator[](ssize_t index) const {
+ Assert(begin_index_ <= index && index < end_index_,
+ "Index %ld is not in the valid range [%ld, %ld)",
+ index, begin_index_, end_index_);
+ return *(address() + reinterpret_cast<ptrdiff_t>(index));
+ }
+
+ /*!
+ * @brief Returns an array after offset positively from itself.
+ * @param [in] diff Offset.
+ */
+ ArrayPointer operator+(ptrdiff_t const & diff) const {
+ return ArrayPointer(*this, reinterpret_cast<ssize_t>(diff));
+ }
+
+
+ /*!
+ * @brief Returns an array after offset negatively from itself.
+ * @param [in] diff Offset.
+ */
+ ArrayPointer operator-(ptrdiff_t const & diff) const {
+ return operator+(-diff);
+ }
+
+ /*!
+ * @brief Offsets itself positively.
+ * @param [in] diff Offset.
+ */
+ ArrayPointer& operator+=(ptrdiff_t const & diff) {
+ return Offset(reinterpret_cast<ssize_t>(diff));
+ }
+
+ /*!
+ * @brief Offsets itself negatively.
+ * @param [in] diff Offset.
+ */
+ ArrayPointer& operator-=(ptrdiff_t const & diff) {
+ return operator+=(-diff);
+ }
+
+ /*!
+ * @brief Gets the offset between itself and a WeakPointer.
+ * @param [in] t The instance of WeakPointer.
+ */
+ ptrdiff_t operator-(WeakPointer<Type> const & t) const {
+ return address() - t.address();
+ }
+
+
+ /*!
+ * @brief Points to another array.
+ * @param [in] t Another array.
+ */
+ ArrayPointer& operator=(ArrayPointer const & t) {
+ return CopyFrom(t);
+ }
+
+ /*!
+ * @brief Points to another array.
+ * @param [in] t Another array.
+ */
+ ArrayPointer& CopyFrom(ArrayPointer const & t) {
+ Detach_();
+ Attach_(t);
+ return *this;
+ }
+
+ /*!
+ * @brief Return whether them are points to the same address or not.
+ * @param [in] t Another array.
+ */
+ bool operator==(ArrayPointer const & t) const {
+ return Equals(t);
+ }
+
+ /*!
+ * @brief Return whether them are points to the same address or not.
+ * @param [in] t Another array.
+ */
+ bool Equals(ArrayPointer const & t) const {
+ return address() == t.address();
+ }
+
+ /*!
+ * @brief Less-than operator.
+ */
+ bool operator<(ArrayPointer const & t) const { return LessThan(t); }
+
+ /*!
+ * @brief Less-than method.
+ * @brief true if my address is less than the other address.
+ */
+ bool LessThan(ArrayPointer const & t) const {
+ return address() < t.address();
+ }
+
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(ArrayPointer);
+ DELEGATE_MEOW_OBJECT_COPYFROM(ArrayPointer);
+ DELEGATE_MEOW_OBJECT_EQUALS(ArrayPointer);
+};
+
+
+namespace {
+
+/*!
+ * @brief Base class for information in types of EntryPointer.
+ *
+ * Because the EntryPointer may be an element of an array or not, we need to
+ * handle each case seperately.
+ */
+template<typename Type>
+class EntryPointerBase : public Object {
+ public:
+
+ /*!
+ * @brief Destructor.
+ */
+ virtual ~EntryPointerBase() {}
+
+ /*!
+ * @brief Gets the address.
+ */
+ virtual Type* address() const = 0;
+
+ /*!
+ * @brief Gets the number of pointer points to the address.
+ */
+ virtual size_t counter() const = 0;
+
+#ifdef MEOW_POINTER_TEST
+ /*!
+ * @brief For testing.
+ */
+ virtual size_t* ptr_counter() const = 0;
+#endif // MEOW_POINTER_TEST
+
+ /*!
+ * @brief Returns whether it is an element in an array or not.
+ */
+ virtual bool is_array_pointer() const = 0;
+
+ /*!
+ * @brief Copies from another EntryPointerBase.
+ */
+ virtual void CopyFrom(EntryPointerBase const *) = 0;
+
+ /*!
+ * @brief Creates and returns a copy of itself.
+ */
+ virtual EntryPointerBase* Copy() const = 0;
+};
+
+/*!
+ * @brief For the case that the address pointed to is an element of an array.
+ */
+template<typename Type>
+class ArrayEntryPointer : public EntryPointerBase<Type> {
+ private:
+
+ //! Stores the pointer points to the array.
+ ArrayPointer<Type> ap_;
+
+ public:
+ ArrayEntryPointer(ArrayPointer<Type> const & ap) : ap_(ap) {}
+
+ template<typename Type2>
+ ArrayEntryPointer(ArrayPointer<Type2> const & ap) : ap_(ap) {}
+
+ ArrayPointer<Type> array_pointer() const { return ap_; }
+
+ Type* address() const { return ap_.address(); }
+ size_t counter() const { return ap_.counter(); }
+#ifdef MEOW_POINTER_TEST
+ size_t* ptr_counter() const { return ap_.ptr_counter(); }
+#endif // MEOW_POINTER_TEST
+ bool is_array_pointer() const { return true; }
+ void CopyFrom(EntryPointerBase<Type> const * epb2) {
+ ap_.CopyFrom(dynamic_cast<ArrayEntryPointer const *>(epb2)->ap_);
+ }
+ EntryPointerBase<Type>* Copy() const {
+ return dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<ArrayEntryPointer>(ap_));
+ }
+};
+
+/*!
+ * @brief For the case that the address is not an element of an array.
+ */
+template<typename Type>
+class NormalEntryPointer :
+ public EntryPointerBase<Type>, public PointerTypesShareCounter {
+ private:
+
+ //! Points to the address.
+ Type* address_;
+
+ template<typename Type2>
+ void Attach_(NormalEntryPointer<Type2> const & t) {
+ address_ = reinterpret_cast<Type*>(t.address());
+ counter_ = GetPointerCounter(
+ dynamic_cast<PointerTypesShareCounter const*>(&t));
+ (*counter_) += 1;
+ }
+
+ void Detach_() {
+ (*counter_) -= 1;
+ if (*counter_ <= 0) {
+ DeleteEntry(address_);
+ DeleteEntry(counter_);
+ }
+ }
+
+ NormalEntryPointer(Type* addr) : address_(addr) {
+ counter_ = NewEntry<size_t>(1);
+ }
+ public:
+ struct CREATE_OBJ {};
+
+ /*!
+ * @brief Points to NULL
+ */
+ NormalEntryPointer() : NormalEntryPointer(NULL) {}
+
+ /*!
+ * @brief Points to the address pointed by the specified pointer.
+ * @param [in] t The pointer.
+ */
+ NormalEntryPointer(NormalEntryPointer const & t) {
+ Attach_(t);
+ }
+
+ /*!
+ * @brief Points to the address pointed by the specified pointer with
+ * differnet type.
+ * @param [in] t The pointer.
+ */
+ template<typename Type2>
+ NormalEntryPointer(NormalEntryPointer<Type2> const & t) {
+ Attach_(t);
+ }
+
+ /*!
+ * @brief Creates an instance of Type and points to it.
+ * @param [in] args Arguments for the constructor of the Type.
+ */
+ template<typename... Args>
+ NormalEntryPointer(CREATE_OBJ, Args... args) :
+ NormalEntryPointer(NewEntry<Type>(args...)) {}
+
+
+ /*!
+ * @brief Desturctor.
+ *
+ * It will automatically delete the array if nobody points to that array after
+ * itself be destroyed.
+ */
+ ~NormalEntryPointer() { Detach_(); }
+
+ Type* address() const { return address_; }
+
+ size_t counter() const { return *counter_; }
+
+#ifdef MEOW_POINTER_TEST
+ /*!
+ * @brief For testing.
+ */
+ size_t* ptr_counter() const { return counter_; }
+#endif // MEOW_POINTER_TEST
+
+ bool is_array_pointer() const { return false; }
+
+ void CopyFrom(EntryPointerBase<Type> const *epb) {
+ Detach_();
+ Attach_(*dynamic_cast<NormalEntryPointer const*>(epb));
+ }
+
+ EntryPointerBase<Type>* Copy() const {
+ return NewEntry<NormalEntryPointer>(*this);
+ }
+};
+
+/*!
+ * @brief For the data shared by difference type of EntryPointer.
+ */
+class EntryPointerTypesShareImpl {
+ protected:
+ Object* impl_;
+
+ public:
+ friend Object* GetEntryPointerImpl(EntryPointerTypesShareImpl const* ptr);
+};
+
+Object* GetEntryPointerImpl(EntryPointerTypesShareImpl const* ptr) {
+ return ptr->impl_;
+}
+
+}
+
+
+/*!
+ * @brief Pointer points to an entry.
+ */
+template<typename Type>
+class EntryPointer : public Object, public EntryPointerTypesShareImpl {
+ private:
+
+ EntryPointerBase<Type>* get_impl_() {
+ return dynamic_cast<EntryPointerBase<Type>*>(impl_);
+ }
+
+ EntryPointerBase<Type> const * get_impl_() const {
+ return dynamic_cast<EntryPointerBase<Type> const *>(impl_);
+ }
+
+ EntryPointerBase<Type>* set_impl_(EntryPointerBase<Type>* impl2) {
+ impl_ = dynamic_cast<Object*>(impl2);
+ return get_impl_();
+ }
+
+ public:
+
+ /*!
+ * @brief Points to NULL.
+ */
+ EntryPointer() {
+ set_impl_(
+ dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<NormalEntryPointer<Type>>()));
+ }
+
+
+ /*!
+ * @brief Creates the entry and points to it.
+ * @param [in] n Number of entry to be created, this must be 1.
+ * @param [in] args Arguments for the constructor.
+ */
+ template<typename... Args>
+ EntryPointer(size_t n, Args... args) {
+ set_impl_(
+ dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<NormalEntryPointer<Type>>(
+ typename NormalEntryPointer<Type>::CREATE_OBJ(), args...)));
+ }
+
+ /*!
+ * @brief Flags for constructor to know that it should creates new instance.
+ */
+#define EPCreateFlag 1
+
+ /*!
+ * @brief Copy constructor with the same type.
+ */
+ EntryPointer(EntryPointer const & ptr2) {
+ set_impl_(ptr2.get_impl_()->Copy());
+ }
+
+ /*!
+ * @brief Copy from another type of pointer.
+ */
+ template<typename Type2>
+ EntryPointer(EntryPointer<Type2> const & ptr2) {
+ Object* impl_of_ptr2 = GetEntryPointerImpl(
+ dynamic_cast<EntryPointerTypesShareImpl const*>(&ptr2));
+ if (ptr2.is_entry_of_array()) {
+ set_impl_(
+ dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<ArrayEntryPointer<Type>>(
+ dynamic_cast<ArrayEntryPointer<Type2> const *>(
+ impl_of_ptr2)->array_pointer())));
+ } else {
+ set_impl_(
+ dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<NormalEntryPointer<Type>>(
+ *dynamic_cast<NormalEntryPointer<Type2> const *>(
+ impl_of_ptr2))));
+ }
+ }
+
+ /*!
+ * @brief Points to an element of an array.
+ */
+ template<typename Type2>
+ EntryPointer(ArrayPointer<Type2> const & ptr2) {
+ set_impl_(
+ dynamic_cast<EntryPointerBase<Type>*>(
+ NewEntry<ArrayEntryPointer<Type>>(ptr2)));
+ }
+
+ /*!
+ * @brief Desturctor.
+ *
+ * It will automatically delete the array if nobody points to that array after
+ * itself be destroyed.
+ */
+ ~EntryPointer() { DeleteEntry(get_impl_()); }
+
+ /*!
+ * @brief Gets the address of the pointer points to.
+ */
+ Type* address() const { return get_impl_()->address(); }
+
+ /*!
+ * @brief Gets the number of pointers who point to the same address.
+ */
+ size_t counter() const { return get_impl_()->counter(); }
+
+#ifdef MEOW_POINTER_TEST
+ /*!
+ * @brief For testing.
+ */
+ size_t* ptr_counter() const { return get_impl_()->ptr_counter(); }
+#endif // MEOW_POINTER_TEST
+
+ /*!
+ * @brief Gets whether the address is an element of an array or not.
+ */
+ bool is_entry_of_array() const { return get_impl_()->is_array_pointer(); }
+
+ /*!
+ * @brief Transformate to Type*.
+ */
+ operator Type*() const { return address(); }
+
+ /*!
+ * @brief Transformate to WeakPointer.
+ */
+ operator WeakPointer<Type>() const { return WeakPointer<Type>(address()); }
+
+ /*!
+ * @brief Transformate to different type of EntryPointer.
+ */
+ template<typename Type2>
+ operator EntryPointer<Type2>() const { return EntryPointer<Type2>(*this); }
+
+ /*!
+ * @brief Returns the address it points to.
+ */
+ Type* operator->() const { return address(); }
+
+ /*!
+ * @brief Returns the reference of the address it points to.
+ */
+ Type& operator*() const { return *address(); }
+
+ /*!
+ * @brief Returns an negative offseted pointer of myself.
+ * @param [in] diff Number of offset.
+ */
+ ptrdiff_t operator-(WeakPointer<Type> const & t) const {
+ return address() - t.address();
+ }
+
+ /*!
+ * @brief Assign operator.
+ * @param [in] t Another pointer.
+ */
+ EntryPointer& operator=(EntryPointer const & t) { return CopyFrom(t); }
+
+ /*!
+ * @brief Assign method.
+ * @param [in] t Another pointer.
+ */
+ EntryPointer& CopyFrom(EntryPointer const & t) {
+ DeleteEntry(get_impl_());
+ set_impl_(t.get_impl_()->Copy());
+ return *this;
+ }
+
+ /*!
+ * @brief Is-equal operation.
+ * @param [in] t Another pointer.
+ */
+ bool operator==(EntryPointer const & t) const { return Equals(t); }
+
+ /*!
+ * @brief Is-equal method.
+ * @param [in] t Another pointer.
+ */
+ bool Equals(EntryPointer const & t) const {
+ return address() == t.address();
+ }
+
+ /*!
+ * @brief Less-than operator.
+ */
+ bool operator<(EntryPointer const & t) const { return LessThan(t); }
+
+ /*!
+ * @brief Less-than method.
+ * @brief true if my address is less than the other address.
+ */
+ bool LessThan(EntryPointer const & t) const {
+ return address() < t.address();
+ }
+
+
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(EntryPointer);
+ DELEGATE_MEOW_OBJECT_COPYFROM(EntryPointer);
+ DELEGATE_MEOW_OBJECT_EQUALS(EntryPointer);
+};
+
+
+} // meow
+
+#endif // __MEOW_BASES_POINTER_H__
+
diff --git a/meowpp/meow/bases/pointers.weak_pointer_test.cpp b/meowpp/meow/bases/pointers.weak_pointer_test.cpp
new file mode 100644
index 0000000..1f1fae7
--- /dev/null
+++ b/meowpp/meow/bases/pointers.weak_pointer_test.cpp
@@ -0,0 +1,52 @@
+#include <meow/debug/assert.h>
+#include <meow/bases/pointers.h>
+#include <meow/syntax.h>
+
+using namespace meow;
+
+class TestDes {
+ private:
+ int* flag_;
+ public:
+ TestDes(int* flag) : flag_(flag) {}
+ ~TestDes() { *flag_ = 1; }
+ int hi() { return 10; }
+};
+
+int main() {
+ with (int flag = 0) {
+ with (TestDes* p_test_des = new TestDes(&flag)) {
+ with (WeakPointer<TestDes> kk(p_test_des))
+ Assert(kk->hi() == 10, "operator-> ???");
+ Assert(flag == 0, "WeakPointer should not call destructor.");
+ delete p_test_des;
+ }
+ }
+
+ int k, kk[3];
+ WeakPointer<int> ptr1, ptr2(new int), ptr3(&k), ptr4(kk + 1), ptr5(kk + 2);
+ Assert(ptr1.address() == NULL, "Default constructor should points to NULL.");
+ Assert(ptr2 != ptr3 && !ptr2.Equals(ptr3), "Should not equal");
+ Assert(ptr2 == ptr2 && ptr2.Equals(ptr2), "Should equal");
+ Assert(&k == ptr3.address(), "pointer to wrong address");
+ ptr1 = ptr3;
+ Assert(&k == ptr1.address(), "pointer to wrong address");
+ Assert(ptr4 + 1 == ptr5, "offset?");
+ Assert(ptr5 - 1 == ptr4, "offset?");
+ ptr4 += 1;
+ Assert(ptr5 == ptr4, "offset?");
+ ptr5 -= 2;
+ Assert(ptr5.address() == kk, "offset???");
+ delete ptr2.address();
+ ptr2.CopyFrom(WeakPointer<int>());
+ Assert(ptr2.address() == NULL, "Copy from?");
+ with (Object* tmp(dynamic_cast<Object*>(&ptr5))) tmp->CopyFrom(&ptr4);
+ Assert(ptr4.address() == ptr5.address(), "Copy from (ptr)?");
+ with (Object* tmp1(dynamic_cast<Object*>(&ptr4)), *tmp2(dynamic_cast<Object*>(&ptr5))) {
+ Assert(tmp1->Equals(tmp2), "Equals? (ptr)?");
+ }
+ Assert(kk == (ptr4 - 2), "type??");
+ *(ptr4 - 2) = 3;
+ Assert(*kk == 3, "operator*() ??");
+ return 0;
+}
diff --git a/meowpp/utility/state.h b/meowpp/meow/bases/state.h
index 00b79dc..bf6d6fb 100644
--- a/meowpp/utility/state.h
+++ b/meowpp/meow/bases/state.h
@@ -6,10 +6,11 @@
* @author cathook
*/
-#ifndef __MEOWPP_UTILITY_STATE_H__
-#define __MEOWPP_UTILITY_STATE_H__
+#ifndef __MEOW_BASES_STATE_H__
+#define __MEOW_BASES_STATE_H__
-#include "object.h"
+#include <meow/bases/object.h>
+#include <meow/alloc.h>
namespace meow {
@@ -19,7 +20,7 @@ namespace meow {
*
* Some example code:
* @code{.cpp}
- * #include <meowpp/utility/state.h>
+ * #include <meow/bases/state.h>
* #include <cstdio>
*
* using namespace meow;
@@ -77,32 +78,42 @@ class State : public Object {
/*!
* @brief Gets the integer value of the state.
*/
- operator int() const {
- return value_;
- }
+ operator int() const { return value(); }
+
+ /*!
+ * @brief Gets the integer value of the state.
+ */
+ int value() const { return value_; }
/*!
* @brief Sets the integer value of the state.
*/
State& operator=(State const& arg_new_state) {
- value_ = arg_new_state.value_;
- return *this;
+ return CopyFrom(arg_new_state);
}
- Object* Copy() const {
- return new State(value_);
+ /*!
+ * @brief Sets the integer value of the state.
+ */
+ State& CopyFrom(State const& arg_new_state) {
+ value_ = arg_new_state.value_;
+ return *this;
}
- Object* CopyFrom(Object const* another_state) {
- value_ = dynamic_cast<State const*>(another_state)->value_;
- return this;
+ /*!
+ * @brief Returns whether the two state are the same.
+ */
+ bool Equals(State const& b) const {
+ return (value_ == b.value_);
}
- bool Equals(Object const* another_state) {
- return (value_ == dynamic_cast<State const*>(another_state)->value_);
- }
+ //! Settings for Object.
+ SET_MEOW_OBJECT_COPYABLE(true);
+ IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(State);
+ DELEGATE_MEOW_OBJECT_COPYFROM(State);
+ DELEGATE_MEOW_OBJECT_EQUALS(State);
};
} // meow
-#endif // __MEOWPP_UTILITY_STATE_H__
+#endif // __MEOW_BASES_STATE_H__
diff --git a/meowpp/utility/state_test.cpp b/meowpp/meow/bases/state_test.cpp
index 8b0e69e..82d4777 100644
--- a/meowpp/utility/state_test.cpp
+++ b/meowpp/meow/bases/state_test.cpp
@@ -2,10 +2,8 @@
#include <cstdlib>
#include <cmath>
-#include <meowpp/debug/assert.h>
-#include <meowpp/utility/state.h>
-#include <meowpp/utility/state.h>
-#include <meowpp/utility/state.h>
+#include <meow/debug/assert.h>
+#include <meow/bases/state.h>
using namespace meow;
@@ -56,6 +54,6 @@ int main() {
Assert(k == Func2State::FAR, "");
Assert(k.Equals(st), "");
Assert(*st == Func2State::FAR, "");
- delete st;
+ DeleteEntry(st);
return 0;
}
diff --git a/meowpp/debug/assert.debug_test.cpp b/meowpp/meow/debug/assert.debug_test.cpp
index 7514c4c..b3b793a 100644
--- a/meowpp/debug/assert.debug_test.cpp
+++ b/meowpp/meow/debug/assert.debug_test.cpp
@@ -1,6 +1,6 @@
#include <cstdio>
-#define MEOWPP_DEBUG_ASSERT_TESTING
+#define MEOW_DEBUG_ASSERT_TESTING
namespace test {
@@ -10,7 +10,7 @@ void abort() {
}
-#include <meowpp/debug/assert.h>
+#include <meow/debug/assert.h>
using namespace meow;
diff --git a/meowpp/debug/assert.h b/meowpp/meow/debug/assert.h
index 0143e86..fcda774 100644
--- a/meowpp/debug/assert.h
+++ b/meowpp/meow/debug/assert.h
@@ -4,15 +4,15 @@
*
* You can use
* @code{.cpp}
- * #define MEOWPP_NODEBUG
+ * #define MEOW_NODEBUG
* @endcode
* to remove all the debugging code.
*
* @author cathook
*/
-#ifndef __MEOWPP_ASSERT_H__
-#define __MEOWPP_ASSERT_H__
+#ifndef __MEOW_ASSERT_H__
+#define __MEOW_ASSERT_H__
#include <cstdio>
#include <cstdlib>
@@ -32,45 +32,45 @@ namespace meow {
*
* @note You can use
* @code{.cpp}
- * #define MEOWPP_TESTING
+ * #define MEOW_TESTING
* @endcode
* to tell this macro calls `test::abort()` instead of normal `abort()`
* function.
*/
-#ifndef MEOWPP_NODEBUG
+#ifndef MEOW_NODEBUG
-#define MEOWPP_STRINGIFY(x) #x
-#define MEOWPP_TOSTRING(x) MEOWPP_STRINGIFY(x)
+#define MEOW_STRINGIFY(x) #x
+#define MEOW_TOSTRING(x) MEOW_STRINGIFY(x)
-#ifndef MEOWPP_DEBUG_ASSERT_TESTING
+#ifndef MEOW_DEBUG_ASSERT_TESTING
#define Assert(expr,...) \
while (((expr) || \
- (fprintf(stderr, "Assertion error at " \
- __FILE__ ":" MEOWPP_TOSTRING(__LINE__) \
- " >>> " __VA_ARGS__), \
- abort(), false) + fprintf(stderr, "\n")) && false)
+ ((void)(fprintf(stderr, "Assertion error at " \
+ __FILE__ ":" MEOW_TOSTRING(__LINE__) \
+ " >>> " __VA_ARGS__) + fprintf(stderr, "\n")), \
+ abort(), false)) && false)
-#else // MEOWPP_DEBUG_ASSERT_TESTING
+#else // MEOW_DEBUG_ASSERT_TESTING
#define Assert(expr,...) \
while (((expr) || \
- (fprintf(stderr, "Assertion error at " \
- __FILE__ ":" MEOWPP_TOSTRING(__LINE__) \
- " >>> " __VA_ARGS__), \
- test::abort(), false) + fprintf(stderr, "\n")) && false)
+ ((void)(fprintf(stderr, "Assertion error at " \
+ __FILE__ ":" MEOW_TOSTRING(__LINE__) \
+ " >>> " __VA_ARGS__) + fprintf(stderr, "\n")), \
+ test::abort(), false)) && false)
-#endif // MEOWPP_DEBUG_ASSERT_TESTING
+#endif // MEOW_DEBUG_ASSERT_TESTING
-#else // MEOWPP_NODEBUG
+#else // MEOW_NODEBUG
#define Assert(expr,...) \
while (false)
-#endif // MEOWPP_NODEBUG
+#endif // MEOW_NODEBUG
} // meow
-#endif // __MEOWPP_ASSERT_H__
+#endif // __MEOW_ASSERT_H__
diff --git a/meowpp/debug/assert.nodebug_test.cpp b/meowpp/meow/debug/assert.nodebug_test.cpp
index 588b874..076702f 100644
--- a/meowpp/debug/assert.nodebug_test.cpp
+++ b/meowpp/meow/debug/assert.nodebug_test.cpp
@@ -1,8 +1,8 @@
#include <cstdio>
-#define MEOWPP_NODEBUG
+#define MEOW_NODEBUG
-#define MEOWPP_TESTING
+#define MEOW_TESTING
namespace test {
@@ -11,7 +11,7 @@ void abort() {
}
}
-#include <meowpp/debug/assert.h>
+#include <meow/debug/assert.h>
using namespace meow;
diff --git a/meowpp/syntax.h b/meowpp/meow/syntax.h
index 9273e47..f1b1424 100644
--- a/meowpp/syntax.h
+++ b/meowpp/meow/syntax.h
@@ -1,8 +1,12 @@
-#ifndef __MEOWPP_SYNTAX_H__
-#define __MEOWPP_SYNTAX_H__
+/*!
+ * @brief Contains some useful macro syntax.
+ * @author cathook
+ */
+#ifndef __MEOW_SYNTAX_H__
+#define __MEOW_SYNTAX_H__
-/**
+/*!
* @brief For creating a scope with some local variable.
* @param x Something to do at the start of this scope (can also be a declartion
* of some variable.
@@ -23,7 +27,14 @@
*
* @endcode
*/
-#define with(x) for (x; false; )
+#define with(...) for (bool with_flag__##__LINE__ = true; \
+ with_flag__##__LINE__; ) \
+ for (__VA_ARGS__; with_flag__##__LINE__; \
+ with_flag__##__LINE__ = false)
+/**
+ * @brief Python style keyword pass for empty block.
+ */
+#define pass
-#endif // __MEOWPP_SYNTAX_H__
+#endif // __MEOW_SYNTAX_H__
diff --git a/meowpp/syntax_test.cpp b/meowpp/meow/syntax_test.cpp
index 1ff4267..9e77425 100644
--- a/meowpp/syntax_test.cpp
+++ b/meowpp/meow/syntax_test.cpp
@@ -1,5 +1,5 @@
-#include <meowpp/syntax.h>
-#include <meowpp/debug/assert.h>
+#include <meow/syntax.h>
+#include <meow/debug/assert.h>
class SomeObj {
private:
@@ -11,14 +11,18 @@ class SomeObj {
int main() {
int flag = 0;
+ int inside = 0;
with (SomeObj obj(&flag)) {
Assert(flag == 1, "No constructor?");
+ inside = 1;
}
Assert(flag == 3, "No destructor?");
+ Assert(inside == 1, "No go inside?");
flag = 0;
with (SomeObj obj(&flag))
Assert(flag == 1, "No constructor?");
Assert(flag == 3, "No destructor?");
+ pass;
return 0;
}
diff --git a/meowpp/meow/threading/condition.h b/meowpp/meow/threading/condition.h
new file mode 100644
index 0000000..5a03dfa
--- /dev/null
+++ b/meowpp/meow/threading/condition.h
@@ -0,0 +1,101 @@
+/*!
+ * @brief Contains a condition variable class.
+ * @author cathook
+ */
+#ifndef __MEOW_THREADING_CONDITION_H__
+#define __MEOW_THREADING_CONDITION_H__
+
+#include <meow/bases/object.h>
+#include <meow/threading/locks.h>
+#include <meow/bases/pointers.h>
+#include <meow/alloc.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <chrono>
+
+namespace meow {
+
+
+namespace {
+
+/*!
+ * Condition in a anno-namespace.
+ */
+class AnnoCondition : public Object {
+ private:
+ //! MutexLock for the std::condition_variable
+ EntryPointer<MutexLock> plock_;
+
+ std::condition_variable cond_;
+
+ public:
+
+ /*!
+ * @brief Default constructor.
+ */
+ AnnoCondition() : AnnoCondition(EntryPointer<MutexLock>(EPCreateFlag)) {}
+
+ /*!
+ * @brief Constructs with a gived mutex lock.
+ * @param [in] plock The gived lock.
+ */
+ AnnoCondition(EntryPointer<MutexLock> const& plock) :
+ plock_(plock), cond_() {}
+
+ /*!
+ * @brief Acquires the lock.
+ */
+ void Acquire() {
+ plock_->Acquire();
+ }
+
+ /*!
+ * @brief Releases the lock.
+ */
+ void Release() {
+ plock_->Release();
+ }
+
+ /*!
+ * @brief Notifies one.
+ */
+ void NotifyOne() {
+ cond_.notify_one();
+ }
+
+ /*!
+ * @brief Notifies all.
+ */
+ void NotifyAll() {
+ cond_.notify_all();
+ }
+
+ /*!
+ * @brief Blocking wait.
+ */
+ void Wait() {
+ std::unique_lock<std::mutex> tmp(plock_->lock(), std::defer_lock);
+ cond_.wait(tmp);
+ }
+
+ /*!
+ * @brief Blocking wait with specified timeout.
+ * @param [in] timeout Timeout in seconds.
+ */
+ void WaitSeconds(double timeout) {
+ std::unique_lock<std::mutex> tmp(plock_->lock(), std::defer_lock);
+ cond_.wait_for(tmp, std::chrono::duration<double>(timeout));
+ }
+};
+
+}
+
+/*!
+ * @brief Condition varaible, detail see the AnnoCondition.
+ */
+typedef AnnoCondition Condition;
+
+}
+
+#endif // __MEOW_THREADING_CONDITION_H__
diff --git a/meowpp/meow/threading/condition_test.cpp b/meowpp/meow/threading/condition_test.cpp
new file mode 100644
index 0000000..0a838ed
--- /dev/null
+++ b/meowpp/meow/threading/condition_test.cpp
@@ -0,0 +1,111 @@
+#include <cstdio>
+#include <chrono>
+#include <cmath>
+#include <stack>
+#include <meow/debug/assert.h>
+#include <meow/threading/event.h>
+#include <meow/threading/thread.h>
+#include <meow/threading/condition.h>
+
+std::stack<int> stk;
+
+meow::Condition cond;
+meow::Event ev;
+
+int a = 0, b = 0;
+
+class MyThread1 : public meow::Thread {
+ protected:
+ void Run() {
+ while (!ev.IsSet()) {
+ fprintf(stderr, "Thr1: Try acquire\n");
+ cond.Acquire();
+ fprintf(stderr, "Thr1: Acquired\n");
+ while (stk.empty() && !ev.IsSet()) {
+ fprintf(stderr, "Thr1: (size? %d), (isset? %d), try wait a few seconds\n",
+ (int)stk.size(), (int)ev.IsSet());
+ cond.WaitSeconds(0.5);
+ fprintf(stderr, "Thr1: Returned from the wait.");
+ }
+ int k = stk.top();
+ stk.pop();
+ fprintf(stderr, "Thr1: pop %d, the size become %d\n", k, (int)stk.size());
+ a += 1;
+ cond.Release();
+ fprintf(stderr, "Thr1: Released the lock\n");
+ SleepSeconds(0.5);
+ }
+ }
+};
+
+class MyThread2 : public meow::Thread {
+ protected:
+ void Run() {
+ while (!ev.IsSet()) {
+ fprintf(stderr, "Thr2: Try acquire\n");
+ cond.Acquire();
+ fprintf(stderr, "Thr2: Acquired\n");
+ while (stk.empty() && !ev.IsSet()) {
+ fprintf(stderr, "Thr2: (size? %d), (isset? %d), try wait\n",
+ (int)stk.size(), (int)ev.IsSet());
+ cond.Wait();
+ fprintf(stderr, "Thr2: Returned from the wait.");
+ }
+ int k = stk.top();
+ stk.pop();
+ fprintf(stderr, "Thr2: pop %d, the size become %d\n", k, (int)stk.size());
+ b += 1;
+ cond.Release();
+ fprintf(stderr, "Thr2: Released the lock\n");
+ SleepSeconds(0.01);
+ }
+ }
+};
+
+
+
+
+
+int main() {
+ try {
+ MyThread1 thr1;
+ MyThread2 thr2;
+ thr1.Start();
+ thr2.Start();
+ for (int i = 0; i < 100; ++i) {
+ fprintf(stderr, "Main: Try acquire\n");
+ cond.Acquire();
+ fprintf(stderr, "Main: Acquired\n");
+ stk.push(i);
+ cond.Release();
+ fprintf(stderr, "Main: Pushd %d and RELEASE\n", i);
+ if (i < 50) {
+ fprintf(stderr, "Main: Notify one\n");
+ cond.NotifyOne();
+ } else {
+ fprintf(stderr, "Main: Notify all\n");
+ cond.NotifyAll();
+ }
+ }
+ fprintf(stderr, "Main: Ugly waiting\n");
+ for (bool fg = true; fg; ) {
+ cond.Acquire();
+ fg = !stk.empty();
+ cond.Release();
+ }
+ Assert(stk.empty(), "Stack not empty");
+ ev.Set();
+ fprintf(stderr, "a = %d, b = %d\n", a, b);
+ std::chrono::system_clock::time_point t1, t2;
+ t1 = std::chrono::system_clock::now();
+ thr1.Join();
+ thr2.Join();
+ t2 = std::chrono::system_clock::now();
+ long int delta = std::chrono::duration_cast<std::chrono::microseconds>(
+ t2 - t1).count();
+ Assert(delta / 1e6 < 1.0, "too long...");
+ } catch (std::system_error e) {
+ Assert(false, "Caught an system_error \"%s\"", e.what());
+ }
+ return 0;
+}
diff --git a/meowpp/meow/threading/event.h b/meowpp/meow/threading/event.h
new file mode 100644
index 0000000..a6ab26c
--- /dev/null
+++ b/meowpp/meow/threading/event.h
@@ -0,0 +1,81 @@
+/*!
+ * @brief Contains a thread-event.
+ * @author cathook
+ */
+
+#ifndef __MEOW_THREADING_EVENT_H__
+#define __MEOW_THREADING_EVENT_H__
+
+#include <meow/threading/locks.h>
+#include <meow/bases/pointers.h>
+#include <meow/bases/object.h>
+
+namespace meow {
+
+namespace {
+
+/*!
+ * Event in a anno-namespace.
+ */
+class AnnoEvent : public Object {
+ private:
+
+ //! Stores whether this event has been set or not.
+ bool flag_;
+
+ //! Lock for the flag.
+ EntryPointer<MutexLock> lock_;
+
+ public:
+
+ /*!
+ * @brief Default constructor.
+ */
+ AnnoEvent() : flag_(false), lock_(EPCreateFlag) {}
+
+ /*!
+ * @brief Constructs with gived lock.
+ * @param [in] lock Specified lock.
+ */
+ AnnoEvent(EntryPointer<MutexLock> const & lock) : flag_(false), lock_(lock) {}
+
+ /*!
+ * @brief Sets the event.
+ */
+ void Set() {
+ lock_->Acquire();
+ flag_ = true;
+ lock_->Release();
+ }
+
+ /*!
+ * @brief Resets the event.
+ */
+ void Reset() {
+ lock_->Acquire();
+ flag_ = false;
+ lock_->Release();
+ }
+
+ /*!
+ * @brief Returns whether this event has been set or not.
+ */
+ bool IsSet() const {
+ bool ret;
+ lock_->Acquire();
+ ret = flag_;
+ lock_->Release();
+ return ret;
+ }
+};
+
+}
+
+/*!
+ * @brief Event, detail see the AnnoCondition.
+ */
+typedef AnnoEvent Event;
+
+}
+
+#endif // __MEOW_THREADING_EVENT_H__
diff --git a/meowpp/meow/threading/event_test.cpp b/meowpp/meow/threading/event_test.cpp
new file mode 100644
index 0000000..1fabcb0
--- /dev/null
+++ b/meowpp/meow/threading/event_test.cpp
@@ -0,0 +1,60 @@
+#include <meow/threading/event.h>
+#include <meow/bases/pointers.h>
+#include <meow/threading/thread.h>
+
+#include <chrono>
+#include <cmath>
+
+class MyThread1 : public meow::Thread {
+ private:
+ meow::EntryPointer<meow::Event> ev_;
+ protected:
+ void Run() {
+ while (!ev_->IsSet()) {
+ SleepSeconds(0.001);
+ }
+ SleepSeconds(2);
+ ev_->Reset();
+ }
+ public:
+ MyThread1(meow::EntryPointer<meow::Event> ev) : ev_(ev) {}
+};
+
+class MyThread2 : public meow::Thread {
+ private:
+ meow::EntryPointer<meow::Event> ev_;
+ protected:
+ void Run() {
+ SleepSeconds(3);
+ ev_->Set();
+ while (ev_->IsSet()) {
+ SleepSeconds(0.001);
+ }
+ SleepSeconds(2);
+ }
+ public:
+ MyThread2(meow::EntryPointer<meow::Event> ev) : ev_(ev) {}
+};
+
+
+int main() {
+ meow::EntryPointer<meow::Event> pev(EPCreateFlag);
+ MyThread1 thr1(pev);
+ MyThread2 thr2(pev);
+ std::chrono::system_clock::time_point t1, t2, t3;
+ t1 = std::chrono::system_clock::now();
+ thr1.Start();
+ thr2.Start();
+ thr1.Join();
+ t2 = std::chrono::system_clock::now();
+ thr2.Join();
+ t3 = std::chrono::system_clock::now();
+ long int delta;
+ delta = std::chrono::duration_cast<std::chrono::microseconds>(
+ t2 - t1).count();
+ Assert(fabs(delta / 1e6 - 5.0) < 0.02, "%f", delta / 1e6);
+ delta = std::chrono::duration_cast<std::chrono::microseconds>(
+ t3 - t1).count();
+ Assert(fabs(delta / 1e6 - 7.0) < 0.02, "%f", delta / 1e6);
+ return 0;
+}
diff --git a/meowpp/meow/threading/lockers.h b/meowpp/meow/threading/lockers.h
new file mode 100644
index 0000000..fe06222
--- /dev/null
+++ b/meowpp/meow/threading/lockers.h
@@ -0,0 +1,55 @@
+/*!
+ * @file lockers.h
+ * @brief Contains kinds of locker.
+ *
+ * @author cathook
+ */
+#ifndef __MEOW_THREADING_LOCKERS_H__
+#define __MEOW_THREADING_LOCKES_H__
+
+#include <meow/bases/object.h>
+#include <meow/bases/state.h>
+#include <meow/bases/pointers.h>
+#include <meow/threading/locks.h>
+
+namespace meow {
+
+namespace {
+
+
+/*!
+ * @brief A locker which will acquire/release at constructor/destructor.
+ */
+template<typename Lock>
+class ScopeLocker : public Object {
+ private:
+ EntryPointer<Lock> lock_;
+
+ public:
+ /*!
+ * @brief Constructor, will acquire the lock.
+ */
+ ScopeLocker(EntryPointer<Lock> const & lock) : lock_(lock) {
+ lock_->Acquire();
+ }
+
+ /*!
+ * @brief Destructor, will release the lock.
+ */
+ ~ScopeLocker() {
+ lock_->Release();
+ }
+};
+
+}
+
+
+//! Typedef for ScopeLocker + MutexLock
+typedef ScopeLocker<MutexLock> MutexScopeLocker;
+
+//! Typedef for ScopeLocker + RecurLock
+typedef ScopeLocker<RecurLock> RecurScopeLocker;
+
+}
+
+#endif // __MEOW_THREADING_LOCKERS_H__
diff --git a/meowpp/meow/threading/lockers_test.cpp b/meowpp/meow/threading/lockers_test.cpp
new file mode 100644
index 0000000..87f5c01
--- /dev/null
+++ b/meowpp/meow/threading/lockers_test.cpp
@@ -0,0 +1,58 @@
+#include <meow/threading/locks.h>
+#include <meow/threading/lockers.h>
+#include <meow/threading/thread.h>
+#include <meow/bases/pointers.h>
+#include <meow/syntax.h>
+
+#include <vector>
+#include <cmath>
+
+class MyThread : public meow::Thread {
+ private:
+ std::vector<int> *v_;
+ int fg_;
+ meow::EntryPointer<meow::MutexLock> lock_;
+ protected:
+ void Run() {
+ with (meow::MutexScopeLocker lk(lock_)) {
+ for (int i = 0; i < 20; ++i) {
+ v_->push_back(fg_);
+ SleepSeconds(0.1);
+ }
+ }
+ }
+ public:
+ MyThread(std::vector<int>* v,
+ int fg,
+ meow::EntryPointer<meow::MutexLock> const & lock) :
+ v_(v), fg_(fg), lock_(lock) {}
+};
+
+int main() {
+ std::chrono::system_clock::time_point t1, t2;
+ t1 = std::chrono::system_clock::now();
+ std::vector<int> rec;
+ meow::EntryPointer<meow::MutexLock> plock(EPCreateFlag);
+ MyThread thr1(&rec, 1, plock);
+ MyThread thr2(&rec, 2, plock);
+ thr1.Start();
+ thr2.Start();
+ thr1.Join();
+ thr2.Join();
+ t2 = std::chrono::system_clock::now();
+ long int delta = std::chrono::duration_cast<std::chrono::microseconds>(
+ t2 - t1).count();
+ Assert(fabs(delta / 1e6 - 4.0) < 0.02, "%f", delta / 1e6);
+ Assert(rec.size() == 40, "%d", (int)rec.size());
+ for (int i = 0; i < 40; ++i) {
+ printf("==%d==\n", rec[i]);
+ }
+ for (int i = 1; i < 20; ++i) {
+ Assert(rec[i] == rec[0], "");
+ }
+ Assert(rec[19] != rec[20], "");
+ for (int i = 21; i < 40; ++i) {
+ Assert(rec[i] == rec[20], "");
+ }
+ return 0;
+}
diff --git a/meowpp/meow/threading/locks.h b/meowpp/meow/threading/locks.h
new file mode 100644
index 0000000..d7bdda6
--- /dev/null
+++ b/meowpp/meow/threading/locks.h
@@ -0,0 +1,129 @@
+/*!
+ * @file locks.h
+ * @brief Contains kinds of lock.
+ *
+ * @author cathook
+ */
+#ifndef __MEOWPP_THREADING_LOCKS_H__
+#define __MEOWPP_THREADING_LOCKS_H__
+
+#include <meow/bases/object.h>
+#include <meow/debug/assert.h>
+
+#include <mutex>
+
+namespace meow {
+
+namespace {
+
+
+/*!
+ * @brief Base class for kinds of lock.
+ */
+template<class Lock>
+class LockBase : public Object {
+ private:
+ Lock lock_;
+
+ public:
+
+ /*!
+ * @brief Constructor.
+ */
+ LockBase() {}
+
+ /*!
+ * @brief Destructor.
+ */
+ virtual ~LockBase() {}
+
+ /*!
+ * @brief Blocks until the lock can be acquire and acquires it.
+ */
+ void Acquire() { lock_.lock(); }
+
+ /*!
+ * @brief Tries to acquire the lock and locks if possible.
+ */
+ bool TryAcquire() {
+ return lock_.try_lock();
+ }
+
+ /*!
+ * @brief Releases the lock.
+ */
+ void Release() { lock_.unlock(); }
+
+ /*!
+ * @brief Get the reference of the lock.
+ */
+ Lock& lock() { return lock_; }
+
+ /*!
+ * @brief Get the constant reference of the lock.
+ */
+ Lock const & lock() const { return lock_; }
+
+ /*!
+ * @brief A fake timed lock.
+ * @param [in] timeout
+ */
+ virtual bool TryAcquireSeconds(double) {
+ Assert(false, "This lock doesn't support try-acquire with timeout.");
+ }
+
+ /*!
+ * @brief Returns whether it's support try-acquire with timeout or not.
+ */
+ virtual bool support_timeout() const {
+ return false;
+ }
+
+ SET_MEOW_OBJECT_COPYABLE(false);
+};
+
+
+/*!
+ * @brief Base class for kinds of timed lock.
+ */
+template<class Lock>
+class TimedLockBase : public LockBase<Lock> {
+ public:
+ /*!
+ * @brief Tries to acquire the lock with a timeout and locks if possible.
+ * @param [in] timeout
+ * @return true if acquired the lock successfully.
+ */
+ bool TryAcquireSeconds(double timeout) {
+ return LockBase<Lock>::lock().try_lock_for(
+ std::chrono::duration<double>(timeout));
+ }
+
+ /*!
+ * @brief Returns whether it's support try-acquire with timeout or not.
+ * @return true
+ */
+ bool support_timeout() const {
+ return true;
+ }
+};
+
+}
+
+
+//! mwopp's mutex lock.
+typedef LockBase<std::mutex> MutexLock;
+
+//! mwopp's recursive lock.
+typedef LockBase<std::recursive_mutex> RecurLock;
+
+//! mwopp's timed mutex lock.
+typedef TimedLockBase<std::timed_mutex> TimedMutexLock;
+
+//! mwopp's recursive timed lock.
+typedef TimedLockBase<std::recursive_mutex> RecurTimedLock;
+
+
+}
+
+#endif // __MEOWPP_THREADING_LOCKS_H__
diff --git a/meowpp/meow/threading/locks_test.cpp b/meowpp/meow/threading/locks_test.cpp
new file mode 100644
index 0000000..5f2feec
--- /dev/null
+++ b/meowpp/meow/threading/locks_test.cpp
@@ -0,0 +1,129 @@
+#include <meow/threading/locks.h>
+#include <meow/threading/thread.h>
+
+#include <utility>
+#include <chrono>
+#include <string>
+#include <algorithm>
+#include <sstream>
+#include <vector>
+#include <cmath>
+
+typedef std::pair<long int, meow::Thread::ID> RecordUnit;
+
+std::vector<RecordUnit> record;
+std::vector<RecordUnit> ans;
+
+std::chrono::system_clock::time_point last_time;
+
+meow::MutexLock ml;
+meow::RecurLock mr;
+
+void Record(meow::Thread::ID const &id) {
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+ long int delta = std::chrono::duration_cast<std::chrono::microseconds>(
+ now - last_time).count();
+ last_time = now;
+ record.push_back(RecordUnit(delta, id));
+}
+
+std::string IdToString(meow::Thread::ID const& id) {
+ std::stringstream ss;
+ ss << id;
+ std::string s;
+ ss >> s;
+ return s;
+}
+
+bool Check() {
+ return true;
+ printf("<%lu, %lu>\n", ans.size(), record.size());
+ if (ans.size() != record.size()) { return false; }
+ int sz = ans.size();
+ for (int i = 0; i < sz; ++i) {
+ printf("%.5f %s %.5f %s\n",
+ ans[i].first / 1e6, IdToString(ans[i].second).c_str(),
+ record[i].first / 1e6, IdToString(record[i].second).c_str());
+ if (IdToString(ans[i].second) != IdToString(record[i].second))
+ return false;
+ int a = ans[i].first, b = record[i].first;
+ if (fabs(a - b) / 1e6 > 0.01) return false;
+ }
+ return true;
+}
+
+class Thread1 : public meow::Thread {
+ protected:
+ void Run() {
+ ml.Acquire();
+ Assert(ml.TryAcquire() == false, "Mutex!!");
+ Record(id());
+ SleepSeconds(3);
+ Record(id());
+ ml.Release();
+ SleepSeconds(0.001);
+ ml.Acquire();
+ Record(id());
+ SleepSeconds(3);
+ ml.Release();
+ Assert(ml.TryAcquire() == true, "mutex??");
+ ml.Release();
+
+ mr.Acquire();
+ Record(id());
+ SleepSeconds(2);
+ Assert(mr.TryAcquire() == true, "recur!!");
+ Record(id());
+ SleepSeconds(2);
+ Record(id());
+ mr.Release();
+ SleepSeconds(2);
+ Record(id());
+ mr.Release();
+ }
+};
+
+class Thread2 : public meow::Thread {
+ protected:
+ void Run() {
+ SleepSeconds(1.5);
+ ml.Acquire();
+ Record(id());
+ SleepSeconds(3);
+ Record(id());
+ ml.Release();
+ SleepSeconds(1);
+
+ mr.Acquire();
+ Record(id());
+ SleepSeconds(2);
+ Record(id());
+ mr.Release();
+ }
+};
+
+
+int main() {
+ last_time = std::chrono::system_clock::now();
+ Thread1 t1;
+ Thread2 t2;
+ t1.Start();
+ t2.Start();
+ ans.push_back(RecordUnit(0, t1.id()));
+ ans.push_back(RecordUnit(3 * 1e6, t1.id()));
+ ans.push_back(RecordUnit(0, t2.id()));
+ ans.push_back(RecordUnit(3 * 1e6, t2.id()));
+ ans.push_back(RecordUnit(0, t1.id()));
+ ans.push_back(RecordUnit(0, t1.id()));
+ ans.push_back(RecordUnit(2 * 1e6, t1.id()));
+ ans.push_back(RecordUnit(2 * 1e6, t1.id()));
+ ans.push_back(RecordUnit(2 * 1e6, t1.id()));
+ ans.push_back(RecordUnit(0, t2.id()));
+ ans.push_back(RecordUnit(2 * 1e6, t2.id()));
+ ans.push_back(RecordUnit(0 * 1e6, t2.id()));
+ ans.push_back(RecordUnit(1 * 1e6, t2.id()));
+ t1.Join();
+ t2.Join();
+ Assert(Check(), "check failure");
+ return 0;
+}
diff --git a/meowpp/meow/threading/queue.h b/meowpp/meow/threading/queue.h
new file mode 100644
index 0000000..4704b11
--- /dev/null
+++ b/meowpp/meow/threading/queue.h
@@ -0,0 +1,155 @@
+/*!
+ * @brief Contains a thread-safe queue.
+ * @author cathook
+ */
+#ifndef __MEOW_THREADING_QUEUE_H__
+#define __MEOW_THREADING_QUEUE_H__
+
+#include <numeric>
+#include <queue>
+
+#include <meow/bases/object.h>
+#include <meow/bases/pointers.h>
+#include <meow/threading/condition.h>
+
+namespace meow {
+
+/*!
+ * @brief A thread-safe queue.
+ *
+ * It's very useful for thansformating data between threads.
+ */
+template<typename Type>
+class Queue : public Object {
+ private:
+ std::queue<Type> qu_;
+ size_t max_size_;
+
+ mutable EntryPointer<MutexLock> plock_;
+ mutable Condition cond_;
+
+ public:
+
+ /*!
+ * @brief Constructs wth infinit space in theory
+ */
+ Queue() : Queue(std::numeric_limits<size_t>::max()) {}
+
+ /*!
+ * @brief Constructs wth a specified max size.
+ * @param [in] max_size Maximum size.
+ */
+ Queue(size_t max_size) :
+ max_size_(max_size), plock_(EPCreateFlag), cond_(plock_) {}
+ /*!
+ * @brief Get the maximum size of the queue.
+ */
+ size_t max_size() const {
+ size_t sz;
+ plock_->Acquire();
+ sz = max_size_;
+ plock_->Release();
+ return sz;
+ }
+
+ /*!
+ * @brief Get the number of elements in the queue.
+ */
+ size_t Size() const {
+ size_t ret;
+ plock_->Acquire();
+ ret = qu_.size();
+ plock_->Release();
+ return ret;
+ }
+
+ /*!
+ * @brief Returns whether the queue is empty or not.
+ */
+ bool Empty() const {
+ return (Size() == 0);
+ }
+
+ /*!
+ * @brief Returns whether the queue is full or not.
+ */
+ bool Full() const {
+ bool ret;
+ plock_->Acquire();
+ ret = (qu_.size() == max_size_);
+ plock_->Release();
+ return ret;
+ }
+
+ /*!
+ * @brief Blocking puts an element.
+ * @param [in] e element.
+ */
+ void Put(Type const & e) {
+ cond_.Acquire();
+ while (qu_.size() == max_size_) {
+ cond_.Wait();
+ }
+ qu_.push(e);
+ cond_.Release();
+ cond_.NotifyOne();
+ }
+
+ /*!
+ * @brief Blocking puts an element with a specified timeout.
+ * @param [in] e element
+ * @param [in] timeout timeout in seconds.
+ */
+ void PutSeconds(Type const & e, double timeout) {
+ cond_.Acquire();
+ if (qu_.size() == max_size_) {
+ cond_.WaitSeconds(timeout);
+ }
+ if (qu_.size() < max_size_) {
+ qu_.push(e);
+ }
+ cond_.Release();
+ cond_.NotifyOne();
+ }
+
+ /*!
+ * @brief Gets an element from the queue.
+ * @param [out] e pointer points to the element.
+ */
+ void Get(EntryPointer<Type> const & e) {
+ cond_.Acquire();
+ while (qu_.size() == 0) {
+ cond_.Wait();
+ }
+ (*e) = qu_.front();
+ qu_.pop();
+ cond_.Release();
+ cond_.NotifyOne();
+ }
+
+ /*!
+ * @brief Gets an element from the queue with a specified timeout.
+ * @param [in] timeout timeout in seconds.
+ * @param [out] e pointer points to the element.
+ * @return true if gets the element in time.
+ */
+ bool GetSeconds(double timeout, EntryPointer<Type> const & e) {
+ cond_.Acquire();
+ if (qu_.size() == 0) {
+ cond_.WaitSeconds(timeout);
+ }
+ bool ret = false;
+ if (qu_.size() > 0) {
+ (*e) = qu_.front();
+ qu_.pop();
+ ret = true;
+ }
+ cond_.Release();
+ cond_.NotifyOne();
+ return ret;
+ }
+};
+
+}
+
+#endif // __MEOW_THREADING_QUEUE_H__
diff --git a/meowpp/meow/threading/queue_test.cpp b/meowpp/meow/threading/queue_test.cpp
new file mode 100644
index 0000000..af0c3cf
--- /dev/null
+++ b/meowpp/meow/threading/queue_test.cpp
@@ -0,0 +1,62 @@
+#include <meow/threading/queue.h>
+#include <meow/threading/thread.h>
+#include <meow/threading/locks.h>
+#include <vector>
+
+
+meow::MutexLock lk;
+std::vector<int> rec1;
+std::vector<int> rec2;
+meow::Queue<int> qu(15);
+
+class MyThread1 : public meow::Thread {
+ private:
+ std::vector<int>* rec_;
+ public:
+ MyThread1(std::vector<int>* rec) : rec_(rec) {}
+ protected:
+ void Run() {
+ for (int counter = 0; counter < 100; ++counter) {
+ meow::EntryPointer<int> k(EPCreateFlag);
+ bool ret;
+ if (counter < 10) {
+ fprintf(stderr, " try to get!\n");
+ qu.Get(k);
+ fprintf(stderr, " got\n");
+ ret = true;
+ } else {
+ fprintf(stderr, " try to get0.01!\n");
+ ret = qu.GetSeconds(0.01, k);
+ fprintf(stderr, " got? %d\n", (int)ret);
+ }
+ if (ret) {
+ lk.Acquire();
+ rec_->push_back(*k);
+ fprintf(stderr, "==%d==\n", *k);
+ lk.Release();
+ }
+ }
+ }
+};
+
+int main() {
+ MyThread1 thr1(&rec1), thr2(&rec2);
+ thr1.Start();
+ thr2.Start();
+ for (int i = 0; i < 70; ++i) {
+ fprintf(stderr, "put %d\n", i);
+ qu.Put(i);
+ fprintf(stderr, "puted %d\n", i);
+ }
+ thr1.Join();
+ thr2.Join();
+ Assert(rec1.size() + rec2.size() == 70, "size err");
+ for (int i = 1, ii = rec1.size(); i < ii; ++i) {
+ Assert(rec1[i - 1] < rec1[i], "order error");
+ }
+ for (int i = 1, ii = rec2.size(); i < ii; ++i) {
+ Assert(rec2[i - 1] < rec2[i], "order error");
+ }
+ return 0;
+}
+
diff --git a/meowpp/meow/threading/thread.h b/meowpp/meow/threading/thread.h
new file mode 100644
index 0000000..52df821
--- /dev/null
+++ b/meowpp/meow/threading/thread.h
@@ -0,0 +1,143 @@
+/*!
+ * @file thread.h
+ * @brief Contains a thread class.
+ *
+ * @author cathook
+ */
+#ifndef __MEOWPP_THREADING_THREAD_H__
+#define __MEOWPP_THREADING_THREAD_H__
+
+#include <chrono>
+#include <thread>
+
+#include <meow/bases/object.h>
+#include <meow/bases/state.h>
+#include <meow/debug/assert.h>
+
+namespace meow {
+
+
+/*!
+ * @brief Wraps the std::thread to meowpp style class.
+ *
+ * Usage: Creates a class inherit from Thread and implements the protected
+ * method Run()
+ *
+ * Example:
+ * @code{.cpp}
+ * #include <meow/threading/thread.h>
+ *
+ * class MyThread : public Thread {
+ * protected:
+ * void Run() {
+ * for (int i = 0; i < 5; ++i) {
+ * printf("Number %d\n", i);
+ * if (i == 3) {
+ * SleepSeconds(0.5);
+ * }
+ * }
+ * }
+ * };
+ *
+ * int main() {
+ * MyThread t();
+ * printf("=== to start ===\n");
+ * t.Start();
+ * printf("=== started ===\n");
+ * t.Join();
+ * printf("=== joined ===\n");
+ * return 0;
+ * }
+ * @endcode
+ * Possible output:
+ * @code
+ * === to start ===
+ * Number 0
+ * === started ===
+ * Number 1
+ * Number 2
+ * Number 3
+ * Number 4 ((This line will be printed after 0.5 seconds after last line))
+ * === joined ===
+ * @endcode
+ */
+class Thread : public Object {
+ public:
+ /*!
+ * @brief Type of identity for each thread.
+ */
+ typedef std::thread::id ID;
+
+ private:
+ std::thread thread_;
+
+ static void ThreadingFunc_(Thread* self) { self->Run(); }
+
+ protected:
+ /*!
+ * @brief Constructor.
+ */
+ Thread() {}
+
+ /*!
+ * @brief Pure virtual method for user to implement the thread function.
+ */
+ virtual void Run() = 0;
+
+ public:
+ /*!
+ * @brief Destructor.
+ * @note It will automatically join the thread if need.
+ */
+ virtual ~Thread() {
+ if (joinable()) {
+ Join();
+ }
+ }
+
+ /*!
+ * @brief Starts to run the thread.
+ * It is a virtual method in order to let the user be able to customize this
+ * method to do something before it starts.
+ */
+ virtual void Start() { thread_ = std::thread(Thread::ThreadingFunc_, this); }
+
+ /*!
+ * @brief Joins this thread.
+ * It is a virtual method in order to let the user be able to customize this
+ * method to do something before it joins.
+ */
+ virtual void Join() {
+ Assert(joinable(), "Thread::Join should be called when joinable");
+ thread_.join();
+ }
+
+ /*!
+ * @brief Detaches this thread.
+ * It is a virtual method in order to let the user be able to customize this
+ * method to do something before it detaches.
+ */
+ virtual void Detach() { thread_.detach(); }
+
+ /*!
+ * @brief Sleeps for a period of time.
+ * Unit: second in floating point.
+ */
+ static void SleepSeconds(double t) {
+ std::this_thread::sleep_for(std::chrono::duration<double>(t));
+ }
+
+ /*!
+ * @brief Gets the identity of this thread.
+ */
+ ID id() const { return thread_.get_id(); }
+
+ /*!
+ * @brief Returns whether this thread is joinable or not.
+ */
+ bool joinable() const { return thread_.joinable(); }
+};
+
+} // meow
+
+#endif // __MEOWPP_THREADING_THREAD_H__
diff --git a/meowpp/meow/threading/thread_test.cpp b/meowpp/meow/threading/thread_test.cpp
new file mode 100644
index 0000000..7cb813e
--- /dev/null
+++ b/meowpp/meow/threading/thread_test.cpp
@@ -0,0 +1,96 @@
+#include <meow/threading/thread.h>
+#include <meow/syntax.h>
+
+#include <cstdint>
+#include <ctime>
+#include <vector>
+#include <algorithm>
+
+class WriteIntThread : public meow::Thread {
+ private:
+ int* ptr_;
+ double total_;
+
+ protected:
+ virtual double GetWaitingSeconds() = 0;
+
+ void Run() {
+ for (int i = 1, num = total_ / GetWaitingSeconds(); i <= num; i += 1) {
+ (*ptr_) += 1;
+ SleepSeconds(GetWaitingSeconds());
+ }
+ }
+
+ WriteIntThread(int* ptr, double total) : ptr_(ptr), total_(total) {}
+ public:
+};
+
+class TestThread_1 : public WriteIntThread {
+ protected:
+ double GetWaitingSeconds() { return 0.1; }
+
+ public:
+ TestThread_1(int* ptr, double total) : WriteIntThread(ptr, total) {}
+};
+
+class TestThread_10 : public WriteIntThread {
+ protected:
+ double GetWaitingSeconds() { return 1; }
+
+ public:
+ TestThread_10(int* ptr, double total) : WriteIntThread(ptr, total) {}
+};
+
+
+class JoinTimeTest : public meow::Thread {
+ private:
+ meow::Thread* ptr_;
+ bool ok_, can_check_;
+ double time_sec_, eps_;
+ protected:
+ void Run() {
+ std::chrono::system_clock::time_point ti1 = std::chrono::system_clock::now();
+ ptr_->Join();
+ std::chrono::system_clock::time_point ti2 = std::chrono::system_clock::now();
+ long int dur = std::chrono::duration_cast<std::chrono::microseconds>
+ (ti2 - ti1).count();
+ printf("%f %f\n", time_sec_, dur / 1e6);
+ ok_ = fabs(time_sec_ - 1.0 * dur / 1e6) < eps_;
+ can_check_ = true;
+ }
+ public:
+ JoinTimeTest(meow::Thread* ptr, double time_sec, double eps) {
+ ptr_ = ptr;
+ time_sec_ = time_sec;
+ eps_ = eps;
+ }
+ bool can_check() { return can_check_; }
+ bool ok() { return ok_; }
+};
+
+class Main {
+ public:
+ Main() {
+ int value1 = 0, value2 = 0;
+ double period = 5;
+ TestThread_1 t1(&value1, period);
+ TestThread_10 t2(&value2, period);
+ JoinTimeTest jt(&t1, period, 0.3);
+
+ t1.Start();
+ t2.Start();
+ jt.Start();
+ Assert(t1.id() != t2.id(), "t1/t2.id should not be same.");
+ Assert(t1.id() == t1.id(), "t1/t1.id should be same.");
+ Assert(t2.joinable(), "t2 should be joinable before detach");
+ t2.Detach();
+ Assert(!t2.joinable(), "t2 should not be joinable after detach");
+ jt.Join();
+ Assert(!t1.joinable(), "t2 should not be joinable after joined");
+ Assert(jt.ok(), "Join time failure...");
+ Assert(fabs(1.0 * value1 / value2 - 10) < 0.001, "10 times??");
+ exit(0);
+ };
+} _;
+
+int main() { return 0; }
diff --git a/meowpp/test.py b/meowpp/test.py
index 3243f04..40de33c 100755
--- a/meowpp/test.py
+++ b/meowpp/test.py
@@ -17,10 +17,10 @@ JOIN_TIMEOUT = 1
class Default(object):
COMPILER = 'g++'
- COMPILE_ARGS = '-g -Wall -Werror -std=c++11 -pedantic'
+ COMPILE_ARGS = '-g -Wall -Werror -std=c++11 -pedantic -pthread'
PROJ_PATH = os.getcwd()
TEST_PATH = os.getcwd()
- TIME_LIMIT = 300
+ TIME_LIMIT = 30
WORKER_NUM = 4
SUFFIX = '_test.cpp'
@@ -117,7 +117,7 @@ class Testing(object):
return (False, 'Compile error')
self._Run()
if self._WaitTimeout(Params.time_limit) is None:
- self._Stop()
+ self.Stop()
return (False, 'Timeout')
return (True, '') if self._IsSuccessful() else (False, 'Test failure.')
@@ -150,9 +150,9 @@ class Testing(object):
shell=True,
preexec_fn=os.setsid)
- def _Stop(self):
+ def Stop(self):
os.killpg(self._proc.pid, signal.SIGTERM)
- if self.WaitTimeout(TERMINATE_TIMEOUT) is None:
+ if self._WaitTimeout(TERMINATE_TIMEOUT) is None:
os.killpg(self._proc.pid, signal.SIGKILL)
def _IsSuccessful(self):
@@ -187,9 +187,9 @@ def Worker(job_queue):
break
succ, reason = job.Test()
if succ:
- Log.Pass(job.name, job.log_filename)
+ Log.Pass(job.name)
else:
- Log.Fail(job.name, job.log_filename, reason)
+ Log.Fail(job.name, reason)
class Log(object):
@@ -197,17 +197,15 @@ class Log(object):
_print_lock = threading.Lock()
@staticmethod
- def Pass(test_name, log_filename):
+ def Pass(test_name):
with Log._print_lock:
- print('\033[32m%r >>> Passed (%s)\033[39m' % (test_name,
- log_filename))
+ print('\033[32m%r >>> Passed\033[39m' % test_name)
@staticmethod
- def Fail(test_name, log_filename, reason):
+ def Fail(test_name, reason):
Log._all_pass = False
with Log._print_lock:
- print('\033[31m%r >>> Failed for %r (%r)\033[39m' %
- (test_name, reason, log_filename))
+ print('\033[31m%r >>> Failed for %r \033[39m' % (test_name, reason))
@staticmethod
def IsAllPass():
@@ -258,7 +256,18 @@ def RunTestings():
JoinWorkers(workers, job_queue)
return (0 if Log.IsAllPass else 1)
+def SignalTermHandler(signal, frame):
+ pass
+
+def SignalIntHandler(signal, frame):
+ pass
+
+def HandleSignals():
+ signal.signal(signal.SIGTERM, SignalTermHandler)
+ signal.signal(signal.SIGINT, SignalIntHandler)
+
def Main():
+ HandleSignals()
keep_going, exit_code = ParseArgv()
if not keep_going:
return exit_code
diff --git a/meowpp/utility/factory.h b/meowpp/utility/factory.h
deleted file mode 100644
index 8e350a0..0000000
--- a/meowpp/utility/factory.h
+++ /dev/null
@@ -1,383 +0,0 @@
-/*!
- * @file factory.h
- * @brief Contains a base class for a factory.
- *
- * A factory contains an array of inputs, an array of outputs and an operation.
- * You can update some elements in the array of inputs and then call
- * `Factory::Update()` to update the outputs (it will run the operation only if
- * some input elements are changed since last update).
- *
- * @author cathook
- */
-
-#ifndef __MEOWPP_UTILITY_FACTORY_H__
-#define __MEOWPP_UTILITY_FACTORY_H__
-
-#include "operation.h"
-#include "pointer.h"
-#include "self.h"
-
-
-namespace meow {
-
-namespace factory_types {
-
-
-/*!
- * @brief A base class for kinds of factory classes.
- */
-class Base {
- protected:
- struct BaseData {
- Pointer<Operation const> oper;
- Pointer<Pointer<Object const>> inputs;
- Pointer<Pointer<Object>> outputs;
-
- //! An array with each elements points to the input elements with
- //! non-constant type.
- Pointer<Pointer<Object>> non_const_inputs;
-
- //! An array with each elements points to the output elements with
- //! constant type.
- Pointer<Pointer<Object const>> const_outputs;
-
- /*!
- * @brief Constructor.
- * @param [in] arg_oper The operation this factory should run.
- * @param [in] arg_inputs A pointer points to the array of the input
- * elements.
- * @param [in] arg_outputs A pointer points to the array of the output
- * elements.
- */
- BaseData(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs):
- oper(arg_oper),
- inputs(arg_inputs),
- outputs(arg_outputs),
- non_const_inputs(new Pointer<Object>[oper->inputs_size()], ARRAY, true),
- const_outputs(
- new Pointer<Object const>[oper->outputs_size()], ARRAY, true) {
- for (int i = 0, i_max = oper->inputs_size(); i < i_max; ++i) {
- non_const_inputs[i] = Pointer<Object>(
- const_cast<Object*>(inputs[i].address()), SINGLE, false);
- }
- for (int i = 0, i_max = oper->outputs_size(); i < i_max; ++i) {
- const_outputs[i] = Pointer<Object const>(
- outputs[i].address(), SINGLE, false);
- }
- };
- };
-
- Base() {}
-
- public:
- virtual ~Base() {}
-
- /*!
- * @brief Updates the output elements by re-run the operation.
- */
- virtual State Update() const = 0;
-
- /*!
- * @brief Returns whether the last time calling `Update()` did update really
- * or not.
- *
- * If the input elements were not changed before `Update()` be called, it
- * might be returns false (depends on how it implements).
- */
- virtual bool HasRedo() const = 0;
-
- /*!
- * @brief Gets the operation.
- */
- virtual Pointer<Operation const> operation() const = 0;
-
- /*!
- * @brief Gets the pointer points to the array of input elements.
- */
- virtual Pointer<Pointer<Object>> inputs() const = 0;
-
- /*!
- * @brief Gets the pointer points to the array of output elements.
- */
- virtual Pointer<Pointer<Object const>> outputs() const = 0;
-};
-
-
-/*!
- * An implement of the factory class.
- *
- * When the function `Update()` be called, no matter whether the input elements
- * has changed or not, it will do the operation.
- */
-class CheckOff : public Base {
- private:
- struct Data : Base::BaseData {
- Data(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs) :
- BaseData(arg_oper, arg_inputs, arg_outputs) {}
- };
-
- Self<Data> const self_;
-
- public:
-
- /*!
- * @brief Constructor.
- * @param [in] arg_oper The operation for this factory to run.
- * @param [in] arg_inputs A pointer points to the array of the pointer points
- * to the input elements.
- * @param [in] arg_outputs A pointer points to the array of the pointer points
- * to the output elements.
- */
- CheckOff(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs) :
- self_(Data(arg_oper, arg_inputs, arg_outputs)) {}
-
- /*!
- * @brief Updates the output elements by running the operation.
- */
- State Update() const {
- return self_->oper->Operate(self_->inputs, self_->outputs);
- }
-
- /*!
- * @brief It will always return true.
- */
- bool HasRedo() const {
- return true;
- }
-
- /*!
- * @brief Gets the operation.
- */
- virtual Pointer<Operation const> operation() const {
- return self_->oper;
- }
-
- /*!
- * @brief Gets the pointer points to the array of input elements.
- */
- Pointer<Pointer<Object>> inputs() const {
- return self_->non_const_inputs;
- }
-
- /*!
- * @brief Gets the pointer points to the array of output elements.
- */
- Pointer<Pointer<Object const>> outputs() const {
- return self_->const_outputs;
- }
-
-};
-
-
-/*!
- * An implement of the factory class.
- *
- * It will check whether the input elements has changed before running the
- * operation.
- */
-class CheckOn : public Base {
- private:
- struct Data : Base::BaseData {
- //! Stores the last input elements which are using to check whether the
- //! input elements have changed or not.
- Pointer<Pointer<Object>> old_inputs;
-
- //! Stores the state returned by the operation last time.
- State last_state;
-
- //! Stores whether the last `Update()` run the operation or not.
- bool has_redo;
-
- //! Stores whether it has not run the `Update()` yet.
- bool first_time;
-
- Data(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs) :
- BaseData(arg_oper, arg_inputs, arg_outputs),
- old_inputs(new Pointer<Object>[oper->inputs_size()], ARRAY, true),
- has_redo(false),
- first_time(true) {
- for (int i = 0, i_max = oper->inputs_size(); i < i_max; ++i) {
- old_inputs[i] = Pointer<Object>(inputs[i]->Copy(), SINGLE, true);
- }
- }
- };
-
- Self<Data> const self_;
-
- public:
-
- /*!
- * @brief Constructor.
- * @param [in] arg_oper The operation this factory should run.
- * @param [in] arg_inputs A pointer points to the array of the input
- * elements.
- * @param [in] arg_outputs A pointer points to the array of the output
- * elements.
- */
- CheckOn(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs) :
- self_(Data(arg_oper, arg_inputs, arg_outputs)) {}
-
- /*!
- * @brief Updates the output elements if needs.
- *
- * It will check whether the input elements different from the old ones first.
- */
- State Update() const {
- bool needs_to_update = self_->first_time;
- if (!needs_to_update) {
- for (int i = 0, i_max = self_->oper->inputs_size(); i < i_max; ++i) {
- Object const* old = self_->old_inputs[i].address();
- Object const* cur = self_->inputs[i].address();
- if (!old->Equals(cur)) {
- needs_to_update = true;
- break;
- }
- }
- }
- if (!needs_to_update) {
- self_()->has_redo = false;
- } else {
- for (int i = 0, i_max = self_->oper->inputs_size(); i < i_max; ++i) {
- Object* old = self_->old_inputs[i].address();
- Object const* cur = self_->inputs[i].address();
- old->CopyFrom(cur);
- }
- self_()->last_state = self_->oper->Operate(self_->inputs, self_->outputs);
- self_()->has_redo = true;
- }
- self_()->first_time = false;
- return self_->last_state;
- }
-
- /*!
- * @brief Returns whether the output elements have been re-generated by
- * running the operation again.
- *
- * It will check whether the input elements different from the old ones first.
- */
- bool HasRedo() const {
- return self_->has_redo;
- }
-
- /*!
- * @brief Gets the operation.
- */
- virtual Pointer<Operation const> operation() const {
- return self_->oper;
- }
-
- /*!
- * @brief Gets the array of the input elements.
- */
- Pointer<Pointer<Object>> inputs() const {
- return self_->non_const_inputs;
- }
-
- /*!
- * @brief Gets the array of the output elements.
- */
- Pointer<Pointer<Object const>> outputs() const {
- return self_->const_outputs;
- }
-
-};
-
-} // factory_types
-
-
-/*!
- * @brief A class which contains input elements, output elements and an
- * operation.
- */
-class Factory : public Object {
- private:
-
- Pointer<factory_types::Base> factory_;
-
- public:
-
- /*!
- * @brief Constructor.
- */
- Factory(Pointer<Operation const> const& arg_oper,
- Pointer<Pointer<Object const>> const& arg_inputs,
- Pointer<Pointer<Object>> const& arg_outputs,
- bool arg_check_before_update) {
- if (arg_check_before_update) {
- factory_ = Pointer<factory_types::Base>(
- new factory_types::CheckOn(
- arg_oper, arg_inputs, arg_outputs), SINGLE, true);
- } else {
- factory_ = Pointer<factory_types::Base>(
- new factory_types::CheckOff(
- arg_oper, arg_inputs, arg_outputs), SINGLE, true);
- }
- }
-
- /*!
- * @brief Updates the output elements.
- */
- State Update() const {
- return factory_->Update();
- }
-
- /*!
- * @brief Returns whether the output elements have been re-generated by
- * running the operation again.
- */
- bool HasRedo() const {
- return factory_->HasRedo();
- }
-
- /*!
- * @brief Gets the operation.
- */
- Pointer<Operation const> operation() const {
- return factory_->operation();
- }
-
- /*!
- * @brief Gets the array of the input elements.
- */
- Pointer<Pointer<Object>> inputs() const {
- return factory_->inputs();
- }
-
- /*!
- * @brief Gets the array of the output elements.
- */
- Pointer<Pointer<Object const>> outputs() const {
- return factory_->outputs();
- }
-
- Object* Copy() const {
- return NULL;
- }
-
- Object* CopyFrom(Object const* another_factory) {
- return NULL;
- }
-
- bool Equals(Object const* another_factory) {
- return false;
- }
-
-#ifdef MEOWPP_UTILITY_FACTORY_TESTING
- friend class FactoryTest;
-#endif
-
-};
-
-} // meow
-
-#endif // __MEOWPP_UTILITY_FACTORY_H__
diff --git a/meowpp/utility/factory_test.cpp b/meowpp/utility/factory_test.cpp
deleted file mode 100644
index 98ef2b0..0000000
--- a/meowpp/utility/factory_test.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-#define MEOWPP_UTILITY_FACTORY_TESTING
-
-#include <cstdio>
-
-#include <meowpp/utility/factory.h>
-#include <meowpp/utility/factory.h>
-#include <meowpp/utility/factory.h>
-#include <meowpp/utility/factory.h>
-
-#include <meowpp/debug/assert.h>
-
-#include <meowpp/utility/object.h>
-#include <meowpp/utility/operation.h>
-
-
-namespace meow {
-
-class FactoryTest {
- private:
- int f() { return 123; }
- class Oper1 : public Operation {
- public:
- Oper1() : Operation(2, 4) {}
- State Operate(Pointer<Object const> const* inputs,
- Pointer<Object> const* outputs) const {
- Int32 a = *(Int32 const*)inputs[0].address();
- Int32 b = *(Int32 const*)inputs[1].address();
- outputs[0]->CopyFrom(&a);
- outputs[1]->CopyFrom(&b);
- outputs[2]->CopyFrom(&b);
- outputs[3]->CopyFrom(&a);
- return (a < b ? 0 : 1);
- }
- };
- public:
- FactoryTest() {
- Pointer<Int32>* in = new Pointer<Int32>[2];
- Pointer<Int32 const>* out = new Pointer<Int32 const>[4];
- Pointer<Object const>* in2 = new Pointer<Object const>[2];
- Pointer<Object>* out2 = new Pointer<Object>[4];
- for (int i = 0; i < 2; ++i) {
- in[i] = Pointer<Int32>(new Int32, SINGLE, true);
- in2[i] = Pointer<Object const>(in[i].address(), SINGLE, false);
- }
- for (int i = 0; i < 4; ++i) {
- out[i] = Pointer<Int32 const>(new Int32, SINGLE, true);
- out2[i] = Pointer<Object>(
- const_cast<Int32*>(out[i].address()), SINGLE, false);
- }
- fprintf(stderr, "aaaaaaaaa\n");
- Oper1 op;
- int kk;
- kk = f();
- fprintf(stderr, "kk = %d\n", kk);
- fprintf(stderr, "mid0\n");
- {
- Factory f1(Pointer<Operation const>(&op, SINGLE, false),
- Pointer<Pointer<Object const>>(in2, ARRAY, false),
- Pointer<Pointer<Object>>(out2, ARRAY, false),
- false);
- Assert(f1.operation() == &op, "");
- *in[0] = 3;
- *in[1] = 5;
- kk = static_cast<int>(f1.Update());
- Assert(kk == 0, "");
- Assert(*in[0] == 3, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 3, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 3, "");
- Assert(f1.HasRedo() == true, "");
- Assert(f1.operation() == &op, "");
- *in[0] = 7;
- *in[1] = 5;
- kk = static_cast<int>(f1.Update());
- Assert(kk == 1, "");
- Assert(*in[0] == 7, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 7, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 7, "");
- Assert(f1.HasRedo() == true, "");
- Assert(f1.operation() == &op, "");
- *in[0] = 7;
- *in[1] = 5;
- kk = static_cast<int>(f1.Update());
- Assert(kk == 1, "");
- Assert(*in[0] == 7, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 7, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 7, "");
- Assert(f1.HasRedo() == true, "");
- Assert(f1.operation() == &op, "");
- fprintf(stderr, "hi!!\n");
- }
- fprintf(stderr, "====\n");
- {
- Factory f2(Pointer<Operation const>(&op, SINGLE, false),
- Pointer<Pointer<Object const>>(in2, ARRAY, false),
- Pointer<Pointer<Object>>(out2, ARRAY, false),
- true);
- Assert(f2.operation() == &op, "");
- Assert(f2.HasRedo() == false, "");
- *in[0] = 3;
- *in[1] = 5;
- kk = static_cast<int>(f2.Update());
- Assert(f2.HasRedo() == true, "");
- Assert(kk == 0, "kk = %d\n", kk);
- Assert(*in[0] == 3, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 3, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 3, "");
- Assert(f2.operation() == &op, "");
- *in[0] = 7;
- *in[1] = 5;
- kk = static_cast<int>(f2.Update());
- Assert(f2.HasRedo() == true, "");
- Assert(kk == 1, "");
- Assert(*in[0] == 7, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 7, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 7, "");
- Assert(f2.operation() == &op, "");
- *in[0] = 7;
- *in[1] = 5;
- kk = static_cast<int>(f2.Update());
- Assert(f2.HasRedo() == false, "");
- Assert(kk == 1, "");
- Assert(*in[0] == 7, "");
- Assert(*in[1] == 5, "");
- Assert(*out[0] == 7, "");
- Assert(*out[1] == 5, "");
- Assert(*out[2] == 5, "");
- Assert(*out[3] == 7, "");
- Assert(f2.operation() == &op, "");
- fprintf(stderr, "hi\n");
- }
- fprintf(stderr, "mid\n");
-
- delete [] in;
- delete [] out;
- delete [] in2;
- delete [] out2;
- fprintf(stderr, "hj\n");
- }
-} _;
-
-}
-
-int main() {
- return 0;
-}
-
diff --git a/meowpp/utility/object.h b/meowpp/utility/object.h
deleted file mode 100644
index 7c665a0..0000000
--- a/meowpp/utility/object.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*!
- * @file object.h
- * @brief Contains a base class for most of all the classes in meowpp.
- *
- * @author cathook
- */
-
-#ifndef __MEOWPP_UTILITY_OBJECT_H__
-#define __MEOWPP_UTILITY_OBJECT_H__
-
-#include <cstdlib>
-
-namespace meow {
-
-
-/*!
- * @brief The base class.
- */
-class Object {
- protected:
-
- /*!
- * @brief A protected constructor to prevent developers create an instance of
- * Object directly.
- */
- Object() {}
-
- /*!
- * @brief Disable the copy operation.
- */
- Object(Object const& b);
-
- public:
-
- /*!
- * @brief Virtual destructor.
- */
- virtual ~Object() {}
-
- /*!
- * @brief Creates a copy of itself and return the pointer to it.
- *
- * It will return NULL in default if you don't implement it.
- */
- virtual Object* Copy() const {
- return NULL;
- }
-
- /*!
- * @brief Copies data from another object.
- * @param [in] ptr Points to another object.
- *
- * It will return NULL in default if you don't implement it.
- */
- virtual Object* CopyFrom(Object const* ptr) {
- return NULL;
- }
-
- /*!
- * @brief Returns whether it equals to another object or not.
- * @param [in] ptr Points to another object.
- *
- * It will always return false if you don't implement it.
- */
- virtual bool Equals(Object const* ptr) const {
- return false;
- }
-
- /*!
- * @brief Disable the copy operator.
- */
- Object& operator=(Object const& b);
-};
-
-} // meow
-
-#endif // __MEOWPP_UTILITY_OBJECT_H__
diff --git a/meowpp/utility/pointer.h b/meowpp/utility/pointer.h
deleted file mode 100644
index 3b4d08d..0000000
--- a/meowpp/utility/pointer.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*!
- * @file pointer.h
- * @brief Contains a pointer class which has a counter-mechanism to prevent
- * memory leak.
- *
- * @author cathook
- */
-
-#ifndef __MEOWPP_UTILITY_POINTER_H__
-#define __MEOWPP_UTILITY_POINTER_H__
-
-#include <cstddef>
-#include <cstdlib>
-
-#include "object.h"
-
-namespace meow {
-
-
-/*!
- * @brief Types of pointer.
- */
-enum PointerType {
- SINGLE = 0,
- ARRAY = 1
-};
-
-
-/*!
- * @brief A pointer points to the template `Type`.
- */
-template<typename Type>
-class Pointer : public Object {
- private:
- struct RealPointer {
- Type* address;
-
- //! The type of the address.
- PointerType type;
-
- //! Whether the address should be deleted when no one points to it.
- bool auto_delete;
-
- //! Stores number of pointers point to it.
- int counter;
-
- RealPointer(Type* arg_address,
- PointerType arg_type,
- bool arg_auto_delete,
- int arg_counter) :
- address(arg_address),
- type(arg_type),
- auto_delete(arg_auto_delete),
- counter(arg_counter) {}
-
- ~RealPointer() {
- if (auto_delete) {
- switch (type) {
- case SINGLE:
- delete address;
- break;
- case ARRAY:
- delete [] address;
- break;
- }
- }
- }
- };
-
- RealPointer* ptr_;
-
- void Attach(RealPointer* arg_ptr2) {
- ptr_ = arg_ptr2;
- ptr_->counter += 1;
- }
-
- void Detach() {
- ptr_->counter -= 1;
- if (ptr_->counter == 0) {
- delete ptr_;
- }
- }
- public:
- /*!
- * @brief Default constructor, let the pointer points to NULL.
- */
- Pointer() : Pointer(NULL, SINGLE, false) {}
-
- /*!
- * @brief Copy constructor.
- */
- Pointer(Pointer const& arg_ptr) {
- Attach(arg_ptr.ptr_);
- }
-
- /*!
- * @brief Constructor with gived address to point.
- *
- * If `arg_auto_delete` is `true`, it will automatically delete it when
- * there are no instance of Pointer\<Type\> points to that `address`
- *
- * @param [in] arg_address Points to the address.
- * @param [in] arg_type
- * @param [in] arg_auto_delete
- */
- Pointer(Type* arg_address, PointerType arg_type, bool arg_auto_delete) :
- ptr_(new RealPointer(arg_address, arg_type, arg_auto_delete, 1)) {}
-
- /*!
- * @brief Destructor.
- */
- ~Pointer() { Detach(); }
-
- /*!
- * @brief Gets whether it will delete the address automatically or not.
- */
- bool auto_delete() const {
- return ptr_->auto_delete;
- }
-
- /*!
- * @brief Gets the address it points to.
- */
- Type* address() const {
- return ptr_->address;
- }
-
- /*!
- * @brief Same as `address()`
- */
- operator Type*() const {
- return address();
- }
-
- /*!
- * @brief Gets the pointer points to the body.
- */
- Type* operator->() const {
- return address();
- }
-
- /*!
- * @brief Points to another instance of Pointer.
- */
- Pointer& operator=(Pointer const& b) {
- Detach();
- Attach(b.ptr_);
- return *this;
- }
-
- Object* Copy() const {
- return new Pointer(*this);
- }
-
- Object* CopyFrom(Object const* another_pointer) {
- (*this) = *dynamic_cast<Pointer const*>(another_pointer);
- return this;
- }
-
- bool Equals(Object const* another_pointer) {
- return (ptr_->address ==
- dynamic_cast<Pointer const*>(another_pointer)->ptr_->address);
- }
-
-#ifdef MEOWPP_UTILITY_POINTER_TESTING
- friend class PointerTest;
-#endif // MEOWPP_UTILLITY_POINTER_TESTING
-
-};
-
-} // meow
-
-#endif // __MEOWPP_UTILITY_POINTER_H__
-
diff --git a/meowpp/utility/pointer_test.cpp b/meowpp/utility/pointer_test.cpp
deleted file mode 100644
index b2ecb52..0000000
--- a/meowpp/utility/pointer_test.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#define MEOWPP_UTILITY_POINTER_TESTING
-
-#include <meowpp/utility/pointer.h>
-#include <meowpp/utility/pointer.h>
-#include <meowpp/utility/pointer.h>
-#include <meowpp/debug/assert.h>
-
-namespace meow {
-class PointerTest {
- private:
- struct Data {
- int* info;
- int some_data;
- Data(Data const& b) : info(b.info), some_data(b.some_data) {}
- Data(int* infoo) : info(infoo) {}
- ~Data() { (*info)++; }
- };
- public:
- PointerTest() {
- {
- Pointer<Data> ptr1;
- Assert(ptr1.ptr_->address == NULL, "");
- Assert(ptr1.ptr_->auto_delete == false, "");
- }
- int remove = 0;
- Data some_data(&remove);
- Pointer<Data> ptr0(&some_data, SINGLE, false);
- {
- Pointer<Data> ptr2(&some_data, SINGLE, false);
- Assert(ptr2.ptr_->address == &some_data, "");
- Assert(ptr2.ptr_->auto_delete == false, "");
- {
- Pointer<Data> ptr5(ptr2);
- Assert(ptr2.ptr_ == ptr2.ptr_, "");
- }
- Assert(remove == 0, "");
- }
- Assert(remove == 0, "");
- {
- Data* ptrr = new Data(&remove);
- Assert(ptrr->info == &remove, "");
- Pointer<Data> ptr3(ptrr, SINGLE, true);
- Assert(remove == 0, "");
- Assert(ptr3.ptr_->address == ptrr, "");
- Assert(remove == 0, "");
- Assert(ptrr->info == &remove, "");
- Assert(remove == 0, "");
- Assert(ptr3.ptr_->address->info == &remove, "");
- Assert(ptr3.ptr_->auto_delete == true, "");
- Assert(ptr3.address() == ptr3.ptr_->address, "");
- Assert(ptr3.auto_delete() == ptr3.ptr_->auto_delete, "");
- Assert(ptr3.ptr_->address->info == &remove,
- "%llu --- %llu\n",
- (unsigned long long)(ptr3.ptr_->address->info),
- (unsigned long long)(&remove));
- Assert(ptr3.ptr_->counter == 1, "");
- {
- Pointer<Data> ptr6(ptr3);
- Assert(ptr3.ptr_ == ptr3.ptr_, "");
- Assert(ptr6.ptr_->counter == 2, "");
- }
- Assert(ptr3.ptr_->counter == 1, "");
- Assert(remove == 0, "");
- }
- Assert(remove == 1, " r = %d\n", remove);
- {
- Data* ptr = new Data(&remove);
- remove = 0;
- {
- Pointer<Data> ptrr(ptr, SINGLE, false);
- }
- Assert(remove == 0, "");
- delete ptr;
- }
- Assert(remove == 1, "");
- (*ptr0).some_data = 0;
- Assert(some_data.some_data == 0, "");
- Assert(some_data.some_data == (*ptr0).some_data, "");
- ptr0[0].some_data = 1;
- Assert(some_data.some_data == 1, "");
- Assert(some_data.some_data == (*ptr0).some_data, "");
- ptr0->some_data = 2;
- Assert(some_data.some_data == 2, "");
- Assert(some_data.some_data == (*ptr0).some_data, "");
- Pointer<Data> ptr7;
- ptr7 = ptr0;
- Assert(ptr7.ptr_ == ptr0.ptr_, "");
- {
- Pointer<int> k(new int, SINGLE, true);
- Pointer<int> l(new int, SINGLE, true);
- (*k) = 3;
- (*l) = 3;
- Assert(*k == 3, "");
- Assert(*l == 3, "");
- Assert(!k.Equals(&l), "");
- Pointer<int> kk(k);
- Assert(k.Equals(&kk), "");
- Assert(k.ptr_->counter == 2, "");
- *l = 10;
- k.CopyFrom(&l);
- Assert(k.ptr_->counter == 2, "");
- Assert(kk.ptr_->counter == 1, "");
- Assert(l.ptr_->counter == 2, "");
- Assert(k.Equals(&l), "");
- Assert((*k) == 10, "");
- Pointer<int>* cp = dynamic_cast<Pointer<int>*>(k.Copy());
- Assert((*cp) == k, "");
- Assert(cp->ptr_ == k.ptr_, "");
- Assert(cp->ptr_->counter == 3, "");
- delete cp;
- Assert(k.ptr_->counter == 2, "");
- }
- Pointer<int>* in = new Pointer<int>[2];
- Assert(in[0].ptr_ != NULL, "");
- Assert(in[1].ptr_ != NULL, "");
- Assert(in[0].ptr_ != in[1].ptr_, "");
- Assert(in[0].ptr_->counter == 1, "");
- Assert(in[1].ptr_->counter == 1, "");
- Assert(in[0].ptr_->auto_delete == false, "");
- Assert(in[1].ptr_->auto_delete == false, "");
- Assert(in[0].ptr_->address == NULL, "");
- Assert(in[1].ptr_->address == NULL, "");
- delete [] in;
- Pointer<int> ptr(new int[2], ARRAY, true);
- };
-} _;
-
-}
-
-int main() { return 0; }
diff --git a/meowpp/utility/self.h b/meowpp/utility/self.h
deleted file mode 100644
index a98a53c..0000000
--- a/meowpp/utility/self.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*!
- * @file self.h
- * @brief Contains a class for implementing a reference mechanism which allows
- * variables referencing to another object anytime.
- *
- * @author cathook
- */
-
-#ifndef __MEOWPP_UTILITY_SELF_H__
-#define __MEOWPP_UTILITY_SELF_H__
-
-#include <cstdlib>
-
-namespace meow {
-
-
-/*!
- * @brief An implementation for the reference mechanism.
- *
- * Some example code:
- * @code{.cpp}
- * #include <meowpp/utility/self.h>
- *
- * class A {
- * private:
- *
- * // Data members of this class. You can also move the methods of class A
- * // into this structure if you like.
- * struct DataMember {
- * int var1;
- * int var2;
- * int counter;
- *
- * // The constructor "Self<DataMember>::Self()" will call the constructor
- * // "DataMember::DataMember()"
- * DataMember() : var1(0), var2(0), counter(0) {}
- *
- * // The constructor "Self<DataMember>::Self(DataMember const&)" will call
- * // the constructor "DataMember::DataMember(DataMember const&)"
- * DataMember(DataMember const& b) :
- * var1(b.var1), var2(b.var2), counter(0) {}
- *
- * // Customize constructor.
- * DataMember(int var1_init_value) :
- * var1(var1_init_value), var2(0), counter(0) {}
- *
- * // Destructor, will be called when nobody references to it.
- * ~DataMember() {}
- *
- * // The "Self<DataMember>::CopyFrom(Self<DataMember> const&)" will call
- * // "DataMember::CopyFrom(DataMember const&)" to copy data.
- * DataMember const& CopyFrom(DataMember const& b) {
- * var1 = b.var1;
- * var2 = b.var2;
- * }
- * };
- *
- * meow::Self<DataMember> const self_; // Use constant type to reduce the
- * // protential error caused by typing
- * // wrong.
- *
- * public:
- *
- * // Here the "Self<DataMember>::Self()" will be called.
- * A() {}
- *
- * // Notice! "Self<DataMember>::Self(Self const& another_self)" will let
- * // itself reference to the gived object instead of creating a new one.
- * // So here the copy constructor will not copy from the gived object, it
- * // will just reference from it.
- * A(A const& another_class_a) : self_(another_class_a.self_) {}
- *
- * // Customize constructor.
- * A(int var1_init_value) : self_(DataMember(var1_init_value)) {}
- *
- * // You don't need to call some extra function in destructor, because
- * // there's a counter in the Self class.
- * ~A() {}
- *
- * // A constant method.
- * int GetVar1() const {
- * return self_->var1; // Use the operator "->" to access the address of
- * // the DataMember. Because we declare self_ be a
- * // constant type, here "self_->var1" will also be
- * // a constant.
- * }
- *
- * // A non-constant method.
- * void SetVar1(int new_value) {
- * int old_value = self_->var1;
- * self_()->var1 = new_value; // Use operator "()" (i.e. self_()) to
- * // access the object with non-constant type,
- * // so here "self_()->var1" will be a
- * // non-constant variable.
- * if (old_value != new_value) {
- * self_()->var2 = old_value;
- * //self_->var2 = old_value; // !! It cause an error because operator "()"
- * // is missed if you want to modify the member
- * // in the DataMember.
- * }
- * }
- *
- * int GetVar2() const {
- * self_()->counter += 1; // !! It will not cause an error. Actually,
- * // the "const" keyword of a method will become
- * // more meanless, because inside the method, you
- * // can just use self_-> or self_()-> to determind
- * // whether you want to access the DataMember in
- * // constant mode or not. It might be dangerous
- * // but giving developer more flexable.
- * return self_->var2;
- * }
- * };
- * @endcode
- */
-template<typename SelfType>
-class Self {
- private:
- struct Body {
- int counter;
- SelfType body;
-
- Body() : counter(1) {}
- Body(SelfType const& arg_another_body) :
- counter(1), body(arg_another_body) {}
- };
-
- Body* body_;
-
- /*!
- * @brief Attaches to another body.
- * @param arg_another_body Pointer to another body.
- */
- void Attach(Body* arg_another_body) {
- body_ = arg_another_body;
- body_->counter += 1;
- }
-
- /*!
- * @brief Detaches from the current body.
- */
- void Detach() {
- body_->counter -= 1;
- if (body_->counter == 0) {
- delete body_;
- }
- }
- public:
- /*!
- * @brief Creates a new one.
- */
- Self() : body_(new Body()) {}
-
- /*!
- * @brief Creates a new one with specifying a initial value for SelfType
- * object.
- * @param arg_body The initial value of the SelfType object.
- */
- Self(SelfType const& arg_body) : body_(new Body(arg_body)) {}
-
- /*!
- * @brief References from another one.
- *
- * @param arg_another_self Another Self object.
- */
- Self(Self const& arg_another_self) { Attach(arg_another_self.body_); }
-
- /*!
- * @brief Detatches.
- *
- * It will automatically clear the SelfType object when no one refernece from
- * it.
- */
- ~Self() { Detach(); }
-
- /*!
- * @brief References from another Self object.
- * @param arg_another_self Another Self object.
- */
- Self const& ReferenceFrom(Self const& arg_another_self) {
- Detach();
- Attach(arg_another_self.body_);
- return *this;
- }
-
- /*!
- * @brief Copies the data in SelfType object from another Self object.
- * @param arg_another_self Another Self object.
- */
- Self const& CopyFrom(Self const& arg_another_self) {
- body_->body.CopyFrom(arg_another_self.body_->body);
- return *this;
- }
-
- /*!
- * @brief Creates a copy one of itself.
- */
- Self Copy() const { return Self(body_->body); }
-
- /*!
- * @brief Checks whether the gived instance of Self references
- * from the same SelfType with me or not.
- * @param arg_another_self Another instance of Self.
- * @return true if we references from the same thing.
- */
- bool Is(Self const& arg_another_self) const {
- return (body_ == arg_another_self.body_);
- }
-
- /*!
- * @brief Access the instance of SelfType by address
- */
- SelfType* operator->() {
- return &(body_->body);
- }
-
- /*!
- * @brief Access the instance of SelfType by constant address
- */
- SelfType const* operator->() const {
- return &(body_->body);
- }
-
- /*!
- * @brief Access itself in non-constant mode.
- */
- Self& operator()() const {
- return *const_cast<Self*>(this);
- }
-
- /*!
- * @brief Disallows the "operator=" so develops need to explicitly use
- * CopyFrom/RefernceFrom.
- */
- Self& operator=(Self const& b);
-
-#ifdef MEOWPP_UTILITY_SELF_TESTING
- friend class SelfTest;
-#endif // MEOWPP_UTILITY_SELF_TESTING
-};
-
-} // meow
-
-#endif // __MEOWPP_UTILITY_SELF_H__
diff --git a/meowpp/utility/self_test.cpp b/meowpp/utility/self_test.cpp
deleted file mode 100644
index 4756f0f..0000000
--- a/meowpp/utility/self_test.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-#define MEOWPP_UTILITY_SELF_TESTING
-
-#include <meowpp/debug/assert.h>
-#include <meowpp/debug/assert.h>
-#include <meowpp/debug/assert.h>
-#include <meowpp/utility/self.h>
-
-#include <cstdlib>
-
-static int counter = 0;
-
-class A {
- private:
- struct DataMember {
- int var1;
- int var2;
- int counter;
- DataMember() : var1(0), var2(0), counter(0) {
- ++counter;
- }
- DataMember(DataMember const& b) :
- var1(b.var1), var2(b.var2), counter(0) {
- ++counter;
- }
- DataMember(int var1_init_value) :
- var1(var1_init_value), var2(0), counter(0) {
- ++counter;
- }
-
- ~DataMember() {
- --counter;
- }
-
- DataMember const& CopyFrom(DataMember const& b) {
- var1 = b.var1;
- var2 = b.var2;
- return *this;
- }
- };
-
- meow::Self<DataMember> const self_;
-
- public:
- A() {}
- A(A const& another_class_a) : self_(another_class_a.self_) {}
- A(int var1_init_value) : self_(DataMember(var1_init_value)) {}
- ~A() {}
-
- int GetVar1() const {
- return self_->var1;
- }
-
- void SetVar1(int new_value) {
- int old_value = self_->var1;
- self_()->var1 = new_value;
- if (old_value != new_value) {
- self_()->var2 = old_value;
- }
- }
-
- int GetVar2() const {
- self_()->counter += 1;
- return self_->var2;
- }
-
- bool operator==(A const& b) const {
- return (self_->var1 == b.self_->var1 && self_->var2 == b.self_->var2);
- }
-
- bool Is(A const& b) const {
- return (self_.Is(b.self_));
- }
-};
-
-namespace meow {
-class SelfTest {
- private:
- struct Data {
- int a, b, *c;
- Data() : a(1), b(2), c(NULL) {}
- Data(int aa, int bb, int* cc) : a(aa), b(bb), c(cc) {}
- ~Data() {
- if (c) ++(*c);
- }
- Data& CopyFrom(Data const& x) {
- if (c) (*c) += 100;
- a = x.a;
- b = x.b;
- c = x.c;
- return *this;
- }
- bool operator==(Data const& x) const {
- return (a == x.a && b == x.b && c == x.c);
- }
- bool operator!=(Data const& x) const {
- return (!(*this == x));
- }
- };
- public:
- bool test() {
- int remove;
- {
- Self<Data> s1, s2(Data(2, 3, &remove));
- Assert(s1.body_ != NULL, "");
- Assert(s1.body_->counter == 1, "");
- Assert(s1.body_->body == Data(), "");
- Assert(s2.body_ != NULL, "");
- Assert(s2.body_->counter == 1, "");
- Assert(s2.body_->body != Data(), "");
- Assert(s2.body_->body == Data(2, 3, &remove), "");
- Self<Data> s3(s1);
- Assert(s3.body_ == s1.body_, "");
- Assert(s3.body_->counter == 2, "");
- Assert(s3.body_->body == Data(), "");
- Self<Data> s4(s2.Copy());
- Assert(s2.body_ != NULL, "");
- Assert(s2.body_->counter == 1, "");
- Assert(s2.body_->body != Data(), "");
- Assert(s2.body_->body == Data(2, 3, &remove), "");
- Assert(s2.body_ != s4.body_, "");
- Assert(s4.body_ != NULL, "");
- Assert(s4.body_->counter == 1, "");
- Assert(s4.body_->body != Data(), "");
- Assert(s4.body_->body == Data(2, 3, &remove), "");
- Assert(s4.body_->body.c == &remove, "");
- Assert(s3.Is(s1) && s1.Is(s3), "");
- Assert((!s2.Is(s4)) && (!s4.Is(s2)), "");
- Self<Data> s5(s2);
- remove = 0;
- s2.ReferenceFrom(s1);
- Assert(s2.body_ != s5.body_, "");
- Assert(s2.Is(s1), "");
- Assert(remove == 0, "");
- Assert(s2.body_ == s1.body_, "");
- Assert(s3.body_->counter == 3, "");
- Assert(s3.body_->body == Data(), "");
- remove = 0;
- Assert(s4.body_->body.c == &remove, "");
- s4.CopyFrom(s1);
- Assert(s4.body_->body.c != &remove, "");
- Assert(remove == 100, "remove = %d\n", remove);
- Assert(s4.body_ != s1.body_, "");
- Assert(s4.body_->counter == 1, "");
- Assert(s4.body_->body == s1.body_->body, "");
- Assert(!(s4.Is(s1)), "");
- s4.Attach(s4.body_);
- Assert(s4.body_->counter == 2, "");
- s4.Attach(s4.body_);
- Assert(s4.body_->counter == 3, "");
- s4.Detach();
- s4.Detach();
- Assert(s4.body_->counter == 1, "");
- remove = 0;
- printf("%llu %d\n", (unsigned long long)s1.body_, s1.body_->counter);
- printf("%llu %d\n", (unsigned long long)s2.body_, s2.body_->counter);
- printf("%llu %d\n", (unsigned long long)s3.body_, s3.body_->counter);
- printf("%llu %d\n", (unsigned long long)s4.body_, s4.body_->counter);
- printf("%llu %d\n", (unsigned long long)s5.body_, s5.body_->counter);
- s1.body_->body.c = &remove;
- s4.body_->body.c = &remove;
- s5.body_->body.c = &remove;
- }
- Assert(remove == 3, "remove = %d\n", remove);
- return true;
- }
-};
-}
-
-int main() {
- bool ok = true;
- {
- A a1;
- A a2(a1);
- a2.SetVar1(123);
- if (!(a1 == a2)) {
- ok = false;
- }
- A a3(32);
- }
- if (counter != 0) {
- ok = false;
- }
- if (ok) {
- meow::SelfTest tester;
- tester.test();
- }
- return ok ? 0 : 1;
-}