optimize template class to reduce generated binary size
This commit is contained in:
parent
2dd9283782
commit
0ed51a7a21
@ -24,6 +24,9 @@ namespace nana
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
void events_operation_register(event_handle);
|
||||||
|
void events_operation_cancel(event_handle);
|
||||||
|
|
||||||
class event_interface
|
class event_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -38,8 +41,50 @@ namespace nana
|
|||||||
virtual event_interface* get_event() const = 0;
|
virtual event_interface* get_event() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void events_operation_register(event_handle);
|
|
||||||
void events_operation_cancel(event_handle);
|
struct docker_base
|
||||||
|
: public docker_interface
|
||||||
|
{
|
||||||
|
event_interface * event_ptr;
|
||||||
|
bool flag_deleted{ false };
|
||||||
|
const bool unignorable;
|
||||||
|
|
||||||
|
docker_base(event_interface*, bool unignorable_flag);
|
||||||
|
|
||||||
|
detail::event_interface * get_event() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class event_base
|
||||||
|
: public detail::event_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~event_base();
|
||||||
|
|
||||||
|
std::size_t length() const;
|
||||||
|
void clear() noexcept;
|
||||||
|
|
||||||
|
void remove(event_handle evt) override;
|
||||||
|
protected:
|
||||||
|
//class emit_counter is a RAII helper for emitting count
|
||||||
|
//It is used for avoiding a try{}catch block which is required for some finial works when
|
||||||
|
//event handlers throw exceptions.
|
||||||
|
class emit_counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
emit_counter(event_base*);
|
||||||
|
~emit_counter();
|
||||||
|
private:
|
||||||
|
event_base * const evt_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//event_handle _m_emplace(::std::unique_ptr<detail::docker_interface>& docker_ptr, bool in_front);
|
||||||
|
event_handle _m_emplace(detail::docker_interface*, bool in_front);
|
||||||
|
protected:
|
||||||
|
unsigned emitting_count_{ 0 };
|
||||||
|
bool deleted_flags_{ false };
|
||||||
|
//std::unique_ptr<std::vector<std::unique_ptr<detail::docker_interface>>> dockers_;
|
||||||
|
std::vector<detail::docker_interface*> * dockers_{ nullptr };
|
||||||
|
};
|
||||||
}//end namespace detail
|
}//end namespace detail
|
||||||
|
|
||||||
/// base clase for all event argument types
|
/// base clase for all event argument types
|
||||||
@ -59,83 +104,32 @@ namespace nana
|
|||||||
|
|
||||||
/// the type of the members of general_events
|
/// the type of the members of general_events
|
||||||
template<typename Arg>
|
template<typename Arg>
|
||||||
class basic_event : public detail::event_interface
|
class basic_event : public detail::event_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using arg_reference = const typename std::remove_reference<Arg>::type &;
|
using arg_reference = const typename std::remove_reference<Arg>::type &;
|
||||||
private:
|
private:
|
||||||
struct docker
|
struct docker
|
||||||
: public detail::docker_interface
|
: public detail::docker_base
|
||||||
{
|
{
|
||||||
basic_event * const event_ptr;
|
|
||||||
std::function<void(arg_reference)> invoke;
|
std::function<void(arg_reference)> invoke;
|
||||||
|
|
||||||
bool flag_deleted{ false };
|
docker(basic_event * evt, std::function<void(arg_reference)> && ivk, bool unignorable_flag)
|
||||||
bool unignorable{false};
|
: docker_base(evt, unignorable_flag), invoke(std::move(ivk))
|
||||||
|
|
||||||
docker(basic_event * s, std::function<void(arg_reference)> && ivk, bool unignorable_flag)
|
|
||||||
: event_ptr(s), invoke(std::move(ivk)), unignorable(unignorable_flag)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
docker(basic_event * s, const std::function<void(arg_reference)> & ivk, bool unignorable_flag)
|
docker(basic_event * evt, const std::function<void(arg_reference)> & ivk, bool unignorable_flag)
|
||||||
: event_ptr(s), invoke(ivk), unignorable(unignorable_flag)
|
: docker_base(evt, unignorable_flag), invoke(ivk)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~docker()
|
|
||||||
{
|
|
||||||
detail::events_operation_cancel(reinterpret_cast<event_handle>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
detail::event_interface * get_event() const override
|
|
||||||
{
|
|
||||||
return event_ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//class emit_counter is a RAII helper for emitting count
|
|
||||||
//It is used for avoiding a try{}catch block which is required for some finial works when
|
|
||||||
//event handlers throw exceptions.
|
|
||||||
class emit_counter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
emit_counter(basic_event* evt)
|
|
||||||
: evt_{evt}
|
|
||||||
{
|
|
||||||
++evt->emitting_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
~emit_counter()
|
|
||||||
{
|
|
||||||
if ((0 == --evt_->emitting_count_) && evt_->deleted_flags_)
|
|
||||||
{
|
|
||||||
evt_->deleted_flags_ = false;
|
|
||||||
for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
|
|
||||||
{
|
|
||||||
if (static_cast<docker*>(i->get())->flag_deleted)
|
|
||||||
i = evt_->dockers_->erase(i);
|
|
||||||
else
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
basic_event * const evt_;
|
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
/// It will get called firstly, because it is set at the beginning of the chain.
|
/// Creates an event handler at the beginning of event chain
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
event_handle connect_front(Function && fn)
|
event_handle connect_front(Function && fn)
|
||||||
{
|
{
|
||||||
internal_scope_guard lock;
|
|
||||||
if (nullptr == dockers_)
|
|
||||||
dockers_.reset(new std::vector<std::unique_ptr<detail::docker_interface>>);
|
|
||||||
|
|
||||||
using prototype = typename std::remove_reference<Function>::type;
|
using prototype = typename std::remove_reference<Function>::type;
|
||||||
std::unique_ptr<detail::docker_interface> dck(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false));
|
|
||||||
auto evt = reinterpret_cast<event_handle>(dck.get());
|
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), true);
|
||||||
dockers_->emplace(dockers_->begin(), std::move(dck));
|
|
||||||
detail::events_operation_register(evt);
|
|
||||||
return evt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event_handle connect(void (*fn)(arg_reference))
|
event_handle connect(void (*fn)(arg_reference))
|
||||||
@ -149,16 +143,9 @@ namespace nana
|
|||||||
template<typename Function>
|
template<typename Function>
|
||||||
event_handle connect(Function && fn)
|
event_handle connect(Function && fn)
|
||||||
{
|
{
|
||||||
internal_scope_guard lock;
|
|
||||||
if (nullptr == dockers_)
|
|
||||||
dockers_.reset(new std::vector<std::unique_ptr<detail::docker_interface>>);
|
|
||||||
|
|
||||||
using prototype = typename std::remove_reference<Function>::type;
|
using prototype = typename std::remove_reference<Function>::type;
|
||||||
std::unique_ptr<detail::docker_interface> dck(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false));
|
|
||||||
auto evt = reinterpret_cast<event_handle>(dck.get());
|
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), false);
|
||||||
dockers_->emplace_back(std::move(dck));
|
|
||||||
detail::events_operation_register(evt);
|
|
||||||
return evt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// It will not get called if stop_propagation() was called.
|
/// It will not get called if stop_propagation() was called.
|
||||||
@ -172,25 +159,9 @@ namespace nana
|
|||||||
template<typename Function>
|
template<typename Function>
|
||||||
event_handle connect_unignorable(Function && fn, bool in_front = false)
|
event_handle connect_unignorable(Function && fn, bool in_front = false)
|
||||||
{
|
{
|
||||||
internal_scope_guard lock;
|
|
||||||
if (nullptr == dockers_)
|
|
||||||
dockers_.reset(new std::vector<std::unique_ptr<detail::docker_interface>>);
|
|
||||||
|
|
||||||
using prototype = typename std::remove_reference<Function>::type;
|
using prototype = typename std::remove_reference<Function>::type;
|
||||||
std::unique_ptr<detail::docker_interface> dck(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), true));
|
|
||||||
auto evt = reinterpret_cast<event_handle>(dck.get());
|
|
||||||
if (in_front)
|
|
||||||
dockers_->emplace(dockers_->begin(), std::move(dck));
|
|
||||||
else
|
|
||||||
dockers_->emplace_back(std::move(dck));
|
|
||||||
detail::events_operation_register(evt);
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t length() const
|
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), true), in_front);
|
||||||
{
|
|
||||||
internal_scope_guard lock;
|
|
||||||
return (nullptr == dockers_ ? 0 : dockers_->size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit(arg_reference& arg)
|
void emit(arg_reference& arg)
|
||||||
@ -202,13 +173,13 @@ namespace nana
|
|||||||
emit_counter ec(this);
|
emit_counter ec(this);
|
||||||
|
|
||||||
auto& dockers = *dockers_;
|
auto& dockers = *dockers_;
|
||||||
const auto dockers_len = dockers.size();
|
const auto dockers_len = dockers_->size();
|
||||||
|
|
||||||
//The dockers may resize when a new event handler is created by a calling handler.
|
//The dockers may resize when a new event handler is created by a calling handler.
|
||||||
//Traverses with position can avaid crash error which caused by a iterator which becomes invalid.
|
//Traverses with position can avaid crash error which caused by a iterator which becomes invalid.
|
||||||
for (std::size_t pos = 0; pos < dockers_len; ++pos)
|
for (std::size_t pos = 0; pos < dockers_len; ++pos)
|
||||||
{
|
{
|
||||||
auto docker_ptr = static_cast<docker*>(dockers[pos].get());
|
auto docker_ptr = static_cast<docker*>(dockers[pos]);
|
||||||
if (docker_ptr->flag_deleted)
|
if (docker_ptr->flag_deleted)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -217,7 +188,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
for (++pos; pos < dockers_len; ++pos)
|
for (++pos; pos < dockers_len; ++pos)
|
||||||
{
|
{
|
||||||
auto docker_ptr = static_cast<docker*>(dockers[pos].get());
|
auto docker_ptr = static_cast<docker*>(dockers[pos]);
|
||||||
if (!docker_ptr->unignorable || docker_ptr->flag_deleted)
|
if (!docker_ptr->unignorable || docker_ptr->flag_deleted)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -227,36 +198,6 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
internal_scope_guard lock;
|
|
||||||
if (dockers_)
|
|
||||||
dockers_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(event_handle evt) override
|
|
||||||
{
|
|
||||||
internal_scope_guard lock;
|
|
||||||
if (dockers_)
|
|
||||||
{
|
|
||||||
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
|
|
||||||
{
|
|
||||||
if (reinterpret_cast<detail::docker_interface*>(evt) == i->get())
|
|
||||||
{
|
|
||||||
//Checks whether this event is working now.
|
|
||||||
if (emitting_count_ > 1)
|
|
||||||
{
|
|
||||||
static_cast<docker*>(i->get())->flag_deleted = true;
|
|
||||||
deleted_flags_ = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dockers_->erase(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
template<typename Fn, bool IsBind>
|
template<typename Fn, bool IsBind>
|
||||||
struct factory
|
struct factory
|
||||||
@ -413,10 +354,6 @@ namespace nana
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private:
|
|
||||||
unsigned emitting_count_{ 0 };
|
|
||||||
bool deleted_flags_{ false };
|
|
||||||
std::unique_ptr<std::vector<std::unique_ptr<detail::docker_interface>>> dockers_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arg_mouse
|
struct arg_mouse
|
||||||
@ -427,12 +364,12 @@ namespace nana
|
|||||||
::nana::point pos; ///< cursor position in the event window
|
::nana::point pos; ///< cursor position in the event window
|
||||||
::nana::mouse button; ///< indicates a button which triggers the event
|
::nana::mouse button; ///< indicates a button which triggers the event
|
||||||
|
|
||||||
bool left_button; ///< mouse left button is pressed?
|
bool left_button; ///< true if mouse left button is pressed
|
||||||
bool mid_button; ///< mouse middle button is pressed?
|
bool mid_button; ///< true if mouse middle button is pressed
|
||||||
bool right_button; ///< mouse right button is pressed?
|
bool right_button; ///< true if mouse right button is pressed
|
||||||
bool alt; ///< keyboard alt is pressed?
|
bool alt; ///< true if keyboard alt is pressed
|
||||||
bool shift; ///< keyboard Shift is pressed?
|
bool shift; ///< true if keyboard Shift is pressed
|
||||||
bool ctrl; ///< keyboard Ctrl is pressed?
|
bool ctrl; ///< true if keyboard Ctrl is pressed
|
||||||
|
|
||||||
/// Checks if left button is operated,
|
/// Checks if left button is operated,
|
||||||
bool is_left_button() const
|
bool is_left_button() const
|
||||||
@ -481,7 +418,7 @@ namespace nana
|
|||||||
event_code evt_code; ///< it is event_code::key_press in current event
|
event_code evt_code; ///< it is event_code::key_press in current event
|
||||||
::nana::window window_handle; ///< A handle to the event window
|
::nana::window window_handle; ///< A handle to the event window
|
||||||
mutable wchar_t key; ///< the key corresponding to the key pressed
|
mutable wchar_t key; ///< the key corresponding to the key pressed
|
||||||
mutable bool ignore; ///< this member is not used
|
mutable bool ignore; ///< this member is only available for key_char event, set 'true' to ignore the input.
|
||||||
bool ctrl; ///< keyboard Ctrl is pressed?
|
bool ctrl; ///< keyboard Ctrl is pressed?
|
||||||
bool shift; ///< keyboard Shift is pressed
|
bool shift; ///< keyboard Shift is pressed
|
||||||
};
|
};
|
||||||
|
|||||||
@ -42,5 +42,112 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//end namespace events_operation
|
//end namespace events_operation
|
||||||
|
|
||||||
|
|
||||||
|
//class docker_base
|
||||||
|
docker_base::docker_base(event_interface* evt, bool unignorable_flag)
|
||||||
|
: event_ptr(evt), unignorable(unignorable_flag)
|
||||||
|
{}
|
||||||
|
|
||||||
|
detail::event_interface * docker_base::get_event() const
|
||||||
|
{
|
||||||
|
return event_ptr;
|
||||||
|
}
|
||||||
|
//end class docker_base
|
||||||
|
|
||||||
|
//class event_base
|
||||||
|
event_base::~event_base()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t event_base::length() const
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
return (nullptr == dockers_ ? 0 : dockers_->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_base::clear() noexcept
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
if (dockers_)
|
||||||
|
{
|
||||||
|
for (auto p : *dockers_)
|
||||||
|
{
|
||||||
|
detail::events_operation_cancel(reinterpret_cast<event_handle>(p));
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
dockers_->clear();
|
||||||
|
|
||||||
|
delete dockers_;
|
||||||
|
dockers_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_base::remove(event_handle evt)
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
if (dockers_)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (reinterpret_cast<detail::docker_interface*>(evt) == *i)
|
||||||
|
{
|
||||||
|
//Checks whether this event is working now.
|
||||||
|
if (emitting_count_ > 1)
|
||||||
|
{
|
||||||
|
static_cast<docker_base*>(*i)->flag_deleted = true;
|
||||||
|
deleted_flags_ = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dockers_->erase(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event_handle event_base::_m_emplace(detail::docker_interface* docker_ptr, bool in_front)
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
if (nullptr == dockers_)
|
||||||
|
dockers_ = new std::vector<detail::docker_interface*>;
|
||||||
|
|
||||||
|
auto evt = reinterpret_cast<event_handle>(docker_ptr);
|
||||||
|
|
||||||
|
if (in_front)
|
||||||
|
dockers_->emplace(dockers_->begin(), docker_ptr);
|
||||||
|
else
|
||||||
|
dockers_->emplace_back(docker_ptr);
|
||||||
|
|
||||||
|
detail::events_operation_register(evt);
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//class emit_counter
|
||||||
|
event_base::emit_counter::emit_counter(event_base* evt)
|
||||||
|
: evt_{ evt }
|
||||||
|
{
|
||||||
|
++evt->emitting_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_base::emit_counter::~emit_counter()
|
||||||
|
{
|
||||||
|
if ((0 == --evt_->emitting_count_) && evt_->deleted_flags_)
|
||||||
|
{
|
||||||
|
evt_->deleted_flags_ = false;
|
||||||
|
for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
|
||||||
|
{
|
||||||
|
if (static_cast<docker_base*>(*i)->flag_deleted)
|
||||||
|
i = evt_->dockers_->erase(i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end class emit_counter
|
||||||
|
//end class event_base
|
||||||
|
|
||||||
}//end namespace detail
|
}//end namespace detail
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
Loading…
x
Reference in New Issue
Block a user