optimize: intrusive list

This commit is contained in:
Haibo 2018-11-16 15:53:39 +08:00 committed by Nomango
parent eb59f7b245
commit 9221b46e1b
45 changed files with 613 additions and 547 deletions

View File

@ -19,9 +19,9 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "time.h"
#include "IntrusiveList.hpp"
#include "intrusive/List.hpp"
namespace easy2d
{
@ -29,7 +29,7 @@ namespace easy2d
class Action
: public RefCounter
, public IntrusiveItem<spAction>
, protected intrusive::ListItem<spAction>
{
E2D_DISABLE_COPY(Action);
@ -37,6 +37,7 @@ namespace easy2d
friend class Loop;
friend class Sequence;
friend class Spawn;
friend class intrusive::List<spAction>;
public:
Action() : running_(false), done_(false), initialized_(false) {}

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "ActionFiniteTime.h"
#include "base.h"
#include "base.hpp"
#include "Node.h"
#include <algorithm>

View File

@ -31,7 +31,7 @@ namespace easy2d
spAction next;
for (auto action = actions_.First(); action; action = next)
{
next = action->Next();
next = action->NextItem();
if (action->IsRunning())
action->Update(target, dt);
@ -49,7 +49,7 @@ namespace easy2d
if (action)
{
action->Start();
actions_.Append(action);
actions_.PushBack(Action::ItemType(action));
}
}
@ -58,7 +58,7 @@ namespace easy2d
if (actions_.IsEmpty())
return;
for (auto& action = actions_.First(); action; action = action->Next())
for (auto& action = actions_.First(); action; action = action->NextItem())
{
action->Resume();
}
@ -69,7 +69,7 @@ namespace easy2d
if (actions_.IsEmpty())
return;
for (auto& action = actions_.First(); action; action = action->Next())
for (auto& action = actions_.First(); action; action = action->NextItem())
{
action->Pause();
}
@ -80,7 +80,7 @@ namespace easy2d
if (actions_.IsEmpty())
return;
for (auto& action = actions_.First(); action; action = action->Next())
for (auto& action = actions_.First(); action; action = action->NextItem())
{
action->Stop();
}

View File

@ -25,7 +25,7 @@ namespace easy2d
{
class ActionManager
{
using Actions = IntrusiveList<spAction>;
using Actions = intrusive::List<spAction>;
public:
// 执行动作

View File

@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "base.h"
#include "base.hpp"
#include "Canvas.h"
#include "render.h"
#include "logs.h"

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "window.h"
#include "time.h"
#include "KeyEvent.h"

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "Resource.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "Singleton.hpp"
namespace easy2d

View File

@ -1,231 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include <functional>
namespace easy2d
{
template <typename T>
class IntrusiveList
{
T first_;
T last_;
int size_;
public:
IntrusiveList() : first_(), last_(), size_(0) {}
~IntrusiveList() { Clear(); }
T const& First() const { return first_; }
T& First() { return first_; }
T const& Last() const { return last_; }
T& Last() { return last_; }
bool IsEmpty() const { return size_ == 0; }
int Size() const { return size_; }
void Append(T child)
{
child->prev_ = last_;
child->next_ = nullptr;
if (first_)
{
last_->next_ = child;
}
else
{
first_ = child;
}
last_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Prepend(T child)
{
child->prev_ = nullptr;
child->next_ = first_;
if (first_)
{
first_->prev_ = child;
}
else
{
last_ = child;
}
first_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Remove(T child)
{
#ifdef E2D_DEBUG
T tmp = first_;
while (tmp != child)
{
if (tmp == last_)
throw std::logic_error("The node to be removed is not in this list");
tmp = tmp->next_;
}
#endif
if (child->next_)
{
child->next_->prev_ = child->prev_;
}
else
{
last_ = child->prev_;
}
if (child->prev_)
{
child->prev_->next_ = child->next_;
}
else
{
first_ = child->next_;
}
child->prev_ = nullptr;
child->next_ = nullptr;
--size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Insert(T child, T before)
{
if (before->prev_)
before->prev_->next_ = child;
else
first_ = child;
child->prev_ = before->prev_;
child->next_ = before;
before->prev_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Clear()
{
T p = first_;
while (p)
{
T tmp = p;
p = p->next_;
if (tmp)
{
tmp->next_ = nullptr;
tmp->prev_ = nullptr;
}
}
first_ = nullptr;
last_ = nullptr;
size_ = 0;
}
void Sort(std::function<bool(T const&, T const&)> func)
{
#ifdef E2D_DEBUG
Check();
#endif
}
#ifdef E2D_DEBUG
void Check()
{
if (!first_)
return;
int pos = 0;
T p = first_;
T tmp = p;
do
{
tmp = p;
p = p->next_;
++pos;
if (p)
{
if (p->prev_ != tmp)
throw std::logic_error("Check list failed");
}
else
{
if (tmp != last_)
throw std::logic_error("Check list failed");
}
} while (p);
if (pos != size_)
throw std::logic_error("Check list failed");
}
#endif
};
template <typename T>
class IntrusiveItem
{
T prev_;
T next_;
template <typename U>
friend class IntrusiveList;
public:
IntrusiveItem() : prev_(), next_() {}
T const& Prev() const { return prev_; }
T& Prev() { return prev_; }
T const& Next() const { return next_; }
T& Next() { return next_; }
};
}

View File

@ -1,184 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining lhs copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <utility>
namespace easy2d
{
template <typename T>
class IntrusivePtr
{
using ElemType = T;
ElemType* ptr_{ nullptr };
public:
IntrusivePtr() {}
IntrusivePtr(nullptr_t) {}
IntrusivePtr(ElemType* p) : ptr_(p)
{
IntrusivePtrAddRef(ptr_);
}
IntrusivePtr(const IntrusivePtr& other) : ptr_(other.ptr_)
{
IntrusivePtrAddRef(ptr_);
}
template <typename U>
IntrusivePtr(const IntrusivePtr<U>& other) : ptr_(other.Get())
{
IntrusivePtrAddRef(ptr_);
}
IntrusivePtr(IntrusivePtr&& other)
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
~IntrusivePtr()
{
IntrusivePtrRelease(ptr_);
}
inline ElemType* Get() const { return ptr_; }
inline void Swap(IntrusivePtr& other)
{
std::swap(ptr_, other.ptr_);
}
inline ElemType* operator ->() const
{
return ptr_;
}
inline ElemType& operator *() const
{
return *ptr_;
}
inline operator bool() const { return ptr_ != nullptr; }
inline bool operator !() const { return ptr_ == 0; }
inline IntrusivePtr& operator =(const IntrusivePtr& other)
{
IntrusivePtr(other).Swap(*this);
return *this;
}
inline IntrusivePtr& operator =(IntrusivePtr&& other)
{
IntrusivePtrRelease(ptr_);
ptr_ = other.ptr_;
other.ptr_ = nullptr;
return *this;
}
inline IntrusivePtr& operator =(ElemType* p)
{
IntrusivePtr(p).Swap(*this);
return *this;
}
inline IntrusivePtr& operator =(nullptr_t)
{
IntrusivePtr{}.Swap(*this);
return *this;
}
};
template<class T, class U>
inline bool operator==(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
{
return lhs.Get() == rhs.Get();
}
template<class T, class U>
inline bool operator!=(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
{
return lhs.Get() != rhs.Get();
}
template<class T, class U>
inline bool operator<(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
{
return lhs.Get() < rhs.Get();
}
template<class T>
inline bool operator==(IntrusivePtr<T> const& lhs, T* rhs)
{
return lhs.Get() == rhs;
}
template<class T>
inline bool operator!=(IntrusivePtr<T> const& lhs, T* rhs)
{
return lhs.Get() != rhs;
}
template<class T>
inline bool operator==(T* lhs, IntrusivePtr<T> const& rhs)
{
return lhs == rhs.Get();
}
template<class T>
inline bool operator!=(T* lhs, IntrusivePtr<T> const& rhs)
{
return lhs != rhs.Get();
}
template<class T>
inline bool operator==(IntrusivePtr<T> const& lhs, nullptr_t)
{
return !static_cast<bool>(lhs);
}
template<class T>
inline bool operator!=(IntrusivePtr<T> const& lhs, nullptr_t)
{
return static_cast<bool>(lhs);
}
template<class T>
inline bool operator==(nullptr_t, IntrusivePtr<T> const& rhs)
{
return !static_cast<bool>(rhs);
}
template<class T>
inline bool operator!=(nullptr_t, IntrusivePtr<T> const& rhs)
{
return static_cast<bool>(rhs);
}
template<class T>
inline IntrusivePtr<T> make_intrusive(T* ptr)
{
return IntrusivePtr<T>(ptr);
}
}

View File

@ -20,7 +20,7 @@
#pragma once
#include "macros.h"
#include "BaseTypes.h"
#include "BaseTypes.hpp"
namespace easy2d
{

View File

@ -20,7 +20,7 @@
#pragma once
#include "macros.h"
#include "BaseTypes.h"
#include "BaseTypes.hpp"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "audio.h"
#include "Resource.h"
#include <xaudio2.h>

View File

@ -97,7 +97,7 @@ namespace easy2d
spNode child = children_.First();
for (spNode next; child; child = next)
{
next = child->Next();
next = child->NextItem();
if (child->GetOrder() < 0)
{
child->Visit();
@ -113,7 +113,7 @@ namespace easy2d
for (spNode next; child; child = next)
{
next = child->Next();
next = child->NextItem();
child->Visit();
}
}
@ -141,7 +141,7 @@ namespace easy2d
{
if (child->GetOrder() < 0)
{
next = child->Next();
next = child->NextItem();
child->Update(dt);
}
else
@ -157,7 +157,7 @@ namespace easy2d
for (spNode next; child; child = next)
{
next = child->Next();
next = child->NextItem();
child->Update(dt);
}
}
@ -172,7 +172,7 @@ namespace easy2d
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.f, 1.5f);
}
for (auto& child = children_.First(); child; child = child->Next())
for (auto& child = children_.First(); child; child = child->NextItem())
{
child->DrawBorder();
}
@ -203,7 +203,7 @@ namespace easy2d
devices::Graphics::Instance()->CreateRectGeometry(final_matrix_, transform_.size, &border_)
);
for (auto& child = children_.First(); child; child = child->Next())
for (auto& child = children_.First(); child; child = child->NextItem())
{
child->dirty_transform_ = true;
}
@ -216,7 +216,7 @@ namespace easy2d
spNode prev;
for (auto& child = children_.Last(); child; child = prev)
{
prev = child->Prev();
prev = child->PrevItem();
handled = child->Dispatch(e, handled);
}
@ -235,7 +235,7 @@ namespace easy2d
spNode prev;
for (auto& child = children_.Last(); child; child = prev)
{
prev = child->Prev();
prev = child->PrevItem();
handled = child->Dispatch(e, handled);
}
@ -253,7 +253,7 @@ namespace easy2d
{
display_opacity_ = real_opacity_ * parent_->display_opacity_;
}
for (auto& child = children_.First(); child; child = child->Next())
for (auto& child = children_.First(); child; child = child->NextItem())
{
child->UpdateOpacity();
}
@ -543,28 +543,20 @@ namespace easy2d
if (child)
{
#ifdef E2D_DEBUG
if (child->parent_)
{
throw std::logic_error("节点已有父节点, 不能再添加到其他节点");
}
logs::Errorln("The node to be added already has a parent");
for (Node* parent = parent_; parent; parent = parent->parent_)
if (parent == child)
logs::Errorln("A node cannot be its own parent");
#endif // E2D_DEBUG
for (Node * parent = this; parent; parent = parent->GetParent().Get())
{
if (child == parent)
{
throw std::logic_error("一个节点不能同时是另一个节点的父节点和子节点");
}
}
children_.Append(child);
child->SetOrder(order);
children_.PushBack(Node::ItemType(child));
child->parent_ = this;
// 更新子节点透明度
child->UpdateOpacity();
// 更新节点转换
child->dirty_transform_ = true;
// 更新子节点排序
child->SetOrder(order);
child->UpdateOpacity();
dirty_sort_ = true;
}
}
@ -587,7 +579,7 @@ namespace easy2d
Nodes children;
size_t hash_code = std::hash<String>{}(name);
for (auto child = children_.First(); child != children_.Last(); child = child->Next())
for (auto child = children_.First(); child != children_.Last(); child = child->NextItem())
{
if (child->hash_name_ == hash_code && child->name_ == name)
{
@ -601,7 +593,7 @@ namespace easy2d
{
size_t hash_code = std::hash<String>{}(name);
for (auto child = children_.First(); child != children_.Last(); child = child->Next())
for (auto child = children_.First(); child != children_.Last(); child = child->NextItem())
{
if (child->hash_name_ == hash_code && child->name_ == name)
{
@ -618,7 +610,7 @@ namespace easy2d
int Node::GetChildrenCount() const
{
return children_.Size();
return static_cast<int>(children_.Size());
}
void Node::RemoveFromParent()
@ -641,7 +633,7 @@ namespace easy2d
if (child)
{
children_.Remove(child);
children_.Remove(Node::ItemType(child));
return true;
}
return false;
@ -658,7 +650,7 @@ namespace easy2d
spNode next;
for (auto& child = children_.First(); child; child = next)
{
next = child->Next();
next = child->NextItem();
if (child->hash_name_ == hash_code && child->name_ == child_name)
children_.Remove(child);

View File

@ -19,13 +19,13 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "time.h"
#include "KeyEvent.h"
#include "MouseEvent.h"
#include "ActionManager.h"
#include "TaskManager.h"
#include "IntrusiveList.hpp"
#include "intrusive/List.hpp"
#include "../math/Transform.hpp"
#include "../math/Matrix.hpp"
@ -38,16 +38,17 @@ namespace easy2d
: public RefCounter
, public ActionManager
, public TaskManager
, public IntrusiveItem<spNode>
, protected intrusive::ListItem<spNode>
{
friend class Game;
friend class Scene;
friend class Transition;
friend class intrusive::List<spNode>;
E2D_DISABLE_COPY(Node);
using Nodes = std::vector< spNode >;
using Children = IntrusiveList<spNode>;
using Nodes = std::vector<spNode>;
using Children = intrusive::List<spNode>;
public:
Node();

View File

@ -19,9 +19,9 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "time.h"
#include "IntrusiveList.hpp"
#include "intrusive/List.hpp"
#include <functional>
namespace easy2d
@ -31,11 +31,12 @@ namespace easy2d
// 定时任务
class Task
: public RefCounter
, public IntrusiveItem<spTask>
, protected intrusive::ListItem<spTask>
{
friend class TaskManager;
friend class intrusive::List<spTask>;
typedef std::function<void()> Callback;
using Callback = std::function<void()>;
public:
explicit Task(

View File

@ -31,7 +31,7 @@ namespace easy2d
spTask next;
for (auto task = tasks_.First(); task; task = next)
{
next = task->Next();
next = task->NextItem();
task->Update(dt);
@ -48,13 +48,13 @@ namespace easy2d
if (task)
{
task->Reset();
tasks_.Append(task);
tasks_.PushBack(Task::ItemType(task));
}
}
void TaskManager::StopTasks(const String& name)
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
if (task->GetName() == name)
{
@ -65,7 +65,7 @@ namespace easy2d
void TaskManager::StartTasks(const String& name)
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
if (task->GetName() == name)
{
@ -76,7 +76,7 @@ namespace easy2d
void TaskManager::RemoveTasks(const String& name)
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
if (task->GetName() == name)
{
@ -87,7 +87,7 @@ namespace easy2d
void TaskManager::StopAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
task->Stop();
}
@ -95,7 +95,7 @@ namespace easy2d
void TaskManager::StartAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
task->Start();
}
@ -103,7 +103,7 @@ namespace easy2d
void TaskManager::RemoveAllTasks()
{
for (auto& task = tasks_.First(); task; task = task->Next())
for (auto& task = tasks_.First(); task; task = task->NextItem())
{
task->stopped_ = true;
}

View File

@ -25,7 +25,7 @@ namespace easy2d
{
class TaskManager
{
using Tasks = IntrusiveList<spTask>;
using Tasks = intrusive::List<spTask>;
public:
// Ìí¼ÓÈÎÎñ

View File

@ -20,7 +20,7 @@
#include "Text.h"
#include "render.h"
#include "base.h"
#include "base.hpp"
#include "logs.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "TextRenderer.h"
#include "base.h"
#include "base.hpp"
#include "render.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "time.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "audio.h"
#include "base.h"
#include "base.hpp"
#include "modules.h"
#include "logs.h"
#include <mfapi.h>

View File

@ -19,21 +19,21 @@
// THE SOFTWARE.
#pragma once
#include "BaseTypes.h"
#include "IntrusivePtr.hpp"
#include "BaseTypes.hpp"
#include "intrusive/SmartPointer.hpp"
#include "RefCounter.hpp"
#ifndef E2D_DECLARE_SMART_PTR
#define E2D_DECLARE_SMART_PTR(class_name)\
class class_name;\
using sp##class_name = ::easy2d::IntrusivePtr< class_name >
using sp##class_name = ::easy2d::intrusive::SmartPointer< class_name >
#define E2D_DECLARE_NS_SMART_PTR(ns_name, class_name)\
namespace ns_name\
{\
class class_name; \
using sp##class_name = ::easy2d::IntrusivePtr< class_name >;\
using sp##class_name = ::easy2d::intrusive::SmartPointer< class_name >;\
}
#endif

View File

@ -0,0 +1,273 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <stdexcept>
#include <functional>
namespace easy2d
{
namespace intrusive
{
template <typename T> class List;
template <typename T>
class ListItem
{
T prev_;
T next_;
template <typename U>
friend class List;
public:
using ItemType = T;
ListItem() : prev_(), next_() {}
T const& PrevItem() const { return prev_; }
T& PrevItem() { return prev_; }
T const& NextItem() const { return next_; }
T& NextItem() { return next_; }
};
template <typename T>
class List
{
T first_;
T last_;
unsigned int size_;
public:
using ItemType = T;
List() : first_(), last_(), size_(0) {}
~List() { Clear(); }
T const& First() const { return first_; }
T& First() { return first_; }
T const& Last() const { return last_; }
T& Last() { return last_; }
bool IsEmpty() const { return size_ == 0; }
unsigned int Size() const { return size_; }
void PushBack(T& child)
{
child->prev_ = last_;
child->next_ = nullptr;
if (first_)
{
last_->next_ = child;
}
else
{
first_ = child;
}
last_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void PushFront(T& child)
{
child->prev_ = nullptr;
child->next_ = first_;
if (first_)
{
first_->prev_ = child;
}
else
{
last_ = child;
}
first_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Remove(T& child)
{
#ifdef E2D_DEBUG
T tmp = first_;
while (tmp != child)
{
if (tmp == last_)
throw std::logic_error("The node to be removed is not in this list");
tmp = tmp->next_;
}
#endif
if (child->next_)
{
child->next_->prev_ = child->prev_;
}
else
{
last_ = child->prev_;
}
if (child->prev_)
{
child->prev_->next_ = child->next_;
}
else
{
first_ = child->next_;
}
child->prev_ = nullptr;
child->next_ = nullptr;
--size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Insert(T& child, T& before)
{
if (before->prev_)
before->prev_->next_ = child;
else
first_ = child;
child->prev_ = before->prev_;
child->next_ = before;
before->prev_ = child;
++size_;
#ifdef E2D_DEBUG
Check();
#endif
}
void Clear()
{
T p = first_;
while (p)
{
T tmp = p;
p = p->next_;
if (tmp)
{
tmp->next_ = nullptr;
tmp->prev_ = nullptr;
}
}
first_ = nullptr;
last_ = nullptr;
size_ = 0;
}
void Sort(std::function<bool(T const&, T const&)> const& if_lt)
{
if (size_ < 2)
return;
std::vector<ItemType> temp_vec;
temp_vec.reserve(size_);
for (ItemType p = first_; p; p = p->NextItem())
{
temp_vec.push_back(p);
}
std::sort(temp_vec.begin(), temp_vec.end(), if_lt);
for (unsigned int i = 0; i < size_; ++i)
{
if (i == 0)
temp_vec[i]->prev_ = ItemType();
else
{
temp_vec[i]->prev_ = temp_vec[i - 1];
temp_vec[i - 1]->next_ = temp_vec[i];
}
if (i == size_ - 1)
temp_vec[i]->next_ = ItemType();
else
{
temp_vec[i]->next_ = temp_vec[i + 1];
temp_vec[i + 1]->prev_ = temp_vec[i];
}
}
first_ = *temp_vec.begin();
last_ = *temp_vec.rbegin();
#ifdef E2D_DEBUG
Check();
#endif
}
#ifdef E2D_DEBUG
private:
void Check()
{
if (!first_)
return;
int pos = 0;
T p = first_;
T tmp = p;
do
{
tmp = p;
p = p->next_;
++pos;
if (p)
{
if (p->prev_ != tmp)
throw std::logic_error("Check list failed");
}
else
{
if (tmp != last_)
throw std::logic_error("Check list failed");
}
} while (p);
if (pos != size_)
throw std::logic_error("Check list failed");
}
#endif
};
}
}

View File

@ -0,0 +1,195 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining lhs copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <utility>
namespace easy2d
{
namespace intrusive
{
template <typename T>
class SmartPointer
{
T* ptr_{ nullptr };
public:
using Type = T;
SmartPointer() {}
SmartPointer(nullptr_t) {}
SmartPointer(Type* p) : ptr_(p)
{
IntrusivePtrAddRef(ptr_);
}
SmartPointer(const SmartPointer& other) : ptr_(other.ptr_)
{
IntrusivePtrAddRef(ptr_);
}
template <typename U>
SmartPointer(const SmartPointer<U>& other) : ptr_(other.Get())
{
IntrusivePtrAddRef(ptr_);
}
SmartPointer(SmartPointer&& other)
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
~SmartPointer()
{
IntrusivePtrRelease(ptr_);
}
inline Type* Get() const { return ptr_; }
inline void Swap(SmartPointer& other)
{
std::swap(ptr_, other.ptr_);
}
inline Type* operator ->() const
{
return ptr_;
}
inline Type& operator *() const
{
return *ptr_;
}
inline operator bool() const { return ptr_ != nullptr; }
inline bool operator !() const { return ptr_ == 0; }
inline SmartPointer& operator =(const SmartPointer& other)
{
SmartPointer(other).Swap(*this);
return *this;
}
inline SmartPointer& operator =(SmartPointer&& other)
{
IntrusivePtrRelease(ptr_);
ptr_ = other.ptr_;
other.ptr_ = nullptr;
return *this;
}
inline SmartPointer& operator =(Type* p)
{
SmartPointer(p).Swap(*this);
return *this;
}
inline SmartPointer& operator =(nullptr_t)
{
SmartPointer{}.Swap(*this);
return *this;
}
};
template<class T, class U>
inline bool operator==(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs)
{
return lhs.Get() == rhs.Get();
}
template<class T, class U>
inline bool operator!=(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs)
{
return lhs.Get() != rhs.Get();
}
template<class T, class U>
inline bool operator<(SmartPointer<T> const& lhs, SmartPointer<U> const& rhs)
{
return lhs.Get() < rhs.Get();
}
template<class T>
inline bool operator==(SmartPointer<T> const& lhs, T* rhs)
{
return lhs.Get() == rhs;
}
template<class T>
inline bool operator!=(SmartPointer<T> const& lhs, T* rhs)
{
return lhs.Get() != rhs;
}
template<class T>
inline bool operator==(T* lhs, SmartPointer<T> const& rhs)
{
return lhs == rhs.Get();
}
template<class T>
inline bool operator!=(T* lhs, SmartPointer<T> const& rhs)
{
return lhs != rhs.Get();
}
template<class T>
inline bool operator==(SmartPointer<T> const& lhs, nullptr_t)
{
return !static_cast<bool>(lhs);
}
template<class T>
inline bool operator!=(SmartPointer<T> const& lhs, nullptr_t)
{
return static_cast<bool>(lhs);
}
template<class T>
inline bool operator==(nullptr_t, SmartPointer<T> const& rhs)
{
return !static_cast<bool>(rhs);
}
template<class T>
inline bool operator!=(nullptr_t, SmartPointer<T> const& rhs)
{
return static_cast<bool>(rhs);
}
template<class T>
inline SmartPointer<T> make_intrusive(T* ptr)
{
return SmartPointer<T>(ptr);
}
// template class cannot support std::swap,
// so implement a swap function in easy2d namespace
template<class T>
inline void swap(SmartPointer<T>& lhs, SmartPointer<T>& rhs)
{
lhs.Swap(rhs);
}
}
}

View File

@ -20,7 +20,7 @@
#include "render.h"
#include "time.h"
#include "base.h"
#include "base.hpp"
#include "logs.h"
#include "modules.h"
#include "Image.h"

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "Singleton.hpp"
#include "Font.hpp"
#include "Resource.h"

View File

@ -440,7 +440,11 @@ namespace easy2d
if (freq.QuadPart == 0LL)
{
if (QueryPerformanceFrequency(&freq) == 0)
throw std::runtime_error("QueryPerformanceFrequency not supported: " + std::to_string(GetLastError()));
{
const char* err = "QueryPerformanceFrequency not supported";
logs::Errorln(HRESULT_FROM_WIN32(GetLastError()), err);
throw std::runtime_error(err);
}
}
LARGE_INTEGER count;

View File

@ -117,7 +117,10 @@ namespace easy2d
if (handle == nullptr)
{
::UnregisterClass(REGISTER_CLASS, hinstance);
throw std::runtime_error("Create window failed!");
const char* err = "Create window failed!";
logs::Errorln(err);
throw std::runtime_error(err);
}
// 禁用输入法

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "base.h"
#include "base.hpp"
#include "Singleton.hpp"
namespace easy2d

View File

@ -31,7 +31,7 @@
//
#include "base/macros.h"
#include "base/base.h"
#include "base/base.hpp"
#include "base/modules.h"
#include "base/render.h"
#include "base/window.h"
@ -47,8 +47,10 @@
#include "base/Color.h"
#include "base/Resource.h"
#include "base/intrusive/SmartPointer.hpp"
#include "base/intrusive/List.hpp"
#include "base/RefCounter.hpp"
#include "base/IntrusivePtr.hpp"
#include "base/Image.h"
#include "base/Node.h"
#include "base/Scene.h"

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../base/BaseTypes.h"
#include "../base/BaseTypes.hpp"
#include "Matrix.hpp"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../base/base.h"
#include "../base/base.hpp"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../base/base.h"
#include "../base/base.hpp"
#include "../base/Resource.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../base/base.h"
#include "../base/base.hpp"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../base/base.h"
#include "../base/base.hpp"
#include "../base/Resource.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "Transcoder.h"
#include "../base/base.h"
#include "../base/base.hpp"
#include "../base/modules.h"
#include "../base/logs.h"
#include <shlwapi.h>

View File

@ -25,8 +25,8 @@
<ClInclude Include="..\..\core\base\ActionManager.h" />
<ClInclude Include="..\..\core\base\Animation.h" />
<ClInclude Include="..\..\core\base\audio.h" />
<ClInclude Include="..\..\core\base\base.h" />
<ClInclude Include="..\..\core\base\BaseTypes.h" />
<ClInclude Include="..\..\core\base\base.hpp" />
<ClInclude Include="..\..\core\base\BaseTypes.hpp" />
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
@ -34,8 +34,8 @@
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\IntrusiveList.hpp" />
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />

View File

@ -14,12 +14,6 @@
<ClInclude Include="..\..\core\base\audio.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\CallFunc.h">
<Filter>base</Filter>
</ClInclude>
@ -134,9 +128,6 @@
<ClInclude Include="..\..\core\base\RefCounter.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Action.hpp">
<Filter>base</Filter>
</ClInclude>
@ -155,7 +146,16 @@
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusiveList.hpp">
<ClInclude Include="..\..\core\base\intrusive\List.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
@ -172,6 +172,9 @@
<Filter Include="ui">
<UniqueIdentifier>{07b6d541-4a1b-472a-aae0-daf9d082fe84}</UniqueIdentifier>
</Filter>
<Filter Include="base\intrusive">
<UniqueIdentifier>{0f508149-735a-43da-ab16-36cc1e9ab63a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\core\base\ActionCombined.cpp">

View File

@ -25,8 +25,8 @@
<ClInclude Include="..\..\core\base\ActionManager.h" />
<ClInclude Include="..\..\core\base\Animation.h" />
<ClInclude Include="..\..\core\base\audio.h" />
<ClInclude Include="..\..\core\base\base.h" />
<ClInclude Include="..\..\core\base\BaseTypes.h" />
<ClInclude Include="..\..\core\base\base.hpp" />
<ClInclude Include="..\..\core\base\BaseTypes.hpp" />
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
@ -34,8 +34,8 @@
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\IntrusiveList.hpp" />
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />

View File

@ -14,12 +14,6 @@
<ClInclude Include="..\..\core\base\audio.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\CallFunc.h">
<Filter>base</Filter>
</ClInclude>
@ -134,9 +128,6 @@
<ClInclude Include="..\..\core\base\RefCounter.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Action.hpp">
<Filter>base</Filter>
</ClInclude>
@ -155,7 +146,16 @@
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusiveList.hpp">
<ClInclude Include="..\..\core\base\intrusive\List.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
@ -172,6 +172,9 @@
<Filter Include="ui">
<UniqueIdentifier>{07b6d541-4a1b-472a-aae0-daf9d082fe84}</UniqueIdentifier>
</Filter>
<Filter Include="base\intrusive">
<UniqueIdentifier>{0f508149-735a-43da-ab16-36cc1e9ab63a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\core\base\ActionCombined.cpp">

View File

@ -25,8 +25,8 @@
<ClInclude Include="..\..\core\base\ActionManager.h" />
<ClInclude Include="..\..\core\base\Animation.h" />
<ClInclude Include="..\..\core\base\audio.h" />
<ClInclude Include="..\..\core\base\base.h" />
<ClInclude Include="..\..\core\base\BaseTypes.h" />
<ClInclude Include="..\..\core\base\base.hpp" />
<ClInclude Include="..\..\core\base\BaseTypes.hpp" />
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
@ -34,8 +34,8 @@
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\IntrusiveList.hpp" />
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />
@ -201,7 +201,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DebugInformationFormat>None</DebugInformationFormat>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>

View File

@ -14,12 +14,6 @@
<ClInclude Include="..\..\core\base\audio.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\CallFunc.h">
<Filter>base</Filter>
</ClInclude>
@ -134,9 +128,6 @@
<ClInclude Include="..\..\core\base\RefCounter.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusivePtr.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Action.hpp">
<Filter>base</Filter>
</ClInclude>
@ -155,7 +146,16 @@
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\IntrusiveList.hpp">
<ClInclude Include="..\..\core\base\intrusive\List.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp">
<Filter>base\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\base.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\BaseTypes.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
@ -172,6 +172,9 @@
<Filter Include="ui">
<UniqueIdentifier>{07b6d541-4a1b-472a-aae0-daf9d082fe84}</UniqueIdentifier>
</Filter>
<Filter Include="base\intrusive">
<UniqueIdentifier>{0f508149-735a-43da-ab16-36cc1e9ab63a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\core\base\ActionCombined.cpp">