merged RC_1_1 into master
This commit is contained in:
commit
4b368e1cfc
|
@ -74,7 +74,7 @@ namespace libtorrent {
|
||||||
template <class T, typename... Args>
|
template <class T, typename... Args>
|
||||||
void emplace_alert(Args&&... args) try
|
void emplace_alert(Args&&... args) try
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
// don't add more than this number of alerts, unless it's a
|
// don't add more than this number of alerts, unless it's a
|
||||||
// high priority alert, in which case we try harder to deliver it
|
// high priority alert, in which case we try harder to deliver it
|
||||||
|
@ -90,12 +90,12 @@ namespace libtorrent {
|
||||||
T& alert = m_alerts[m_generation].emplace_back<T>(
|
T& alert = m_alerts[m_generation].emplace_back<T>(
|
||||||
m_allocations[m_generation], std::forward<Args>(args)...);
|
m_allocations[m_generation], std::forward<Args>(args)...);
|
||||||
|
|
||||||
maybe_notify(&alert, lock);
|
maybe_notify(&alert);
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc const&)
|
catch (std::bad_alloc const&)
|
||||||
{
|
{
|
||||||
// record that we dropped an alert of this type
|
// record that we dropped an alert of this type
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||||
m_dropped.set(T::alert_type);
|
m_dropped.set(T::alert_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,12 +105,7 @@ namespace libtorrent {
|
||||||
template <class T>
|
template <class T>
|
||||||
bool should_post() const
|
bool should_post() const
|
||||||
{
|
{
|
||||||
if (!(m_alert_mask.load(std::memory_order_relaxed) & T::static_category))
|
return bool(m_alert_mask.load(std::memory_order_relaxed) & T::static_category);
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return should_post_impl(T::priority);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
alert* wait_for_alert(time_duration max_wait);
|
alert* wait_for_alert(time_duration max_wait);
|
||||||
|
@ -136,11 +131,15 @@ namespace libtorrent {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool should_post_impl(int priority) const;
|
void maybe_notify(alert* a);
|
||||||
void maybe_notify(alert* a, std::unique_lock<std::mutex>& lock);
|
|
||||||
|
|
||||||
mutable std::mutex m_mutex;
|
// this mutex protects everything. Since it's held while executing user
|
||||||
std::condition_variable m_condition;
|
// callbacks (the notify function and extension on_alert()) it must be
|
||||||
|
// recursive to post new alerts. This is implemented by storing the
|
||||||
|
// current thread-id in m_mutex_holder, if it matches ours, we don't need
|
||||||
|
// to lock
|
||||||
|
mutable std::recursive_mutex m_mutex;
|
||||||
|
std::condition_variable_any m_condition;
|
||||||
std::atomic<alert_category_t> m_alert_mask;
|
std::atomic<alert_category_t> m_alert_mask;
|
||||||
int m_queue_size_limit;
|
int m_queue_size_limit;
|
||||||
|
|
||||||
|
|
|
@ -47,16 +47,9 @@ namespace libtorrent {
|
||||||
|
|
||||||
alert_manager::~alert_manager() = default;
|
alert_manager::~alert_manager() = default;
|
||||||
|
|
||||||
bool alert_manager::should_post_impl(int const priority) const
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
return m_alerts[m_generation].size()
|
|
||||||
< m_queue_size_limit * (1 + priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
alert* alert_manager::wait_for_alert(time_duration max_wait)
|
alert* alert_manager::wait_for_alert(time_duration max_wait)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
if (!m_alerts[m_generation].empty())
|
if (!m_alerts[m_generation].empty())
|
||||||
return m_alerts[m_generation].front();
|
return m_alerts[m_generation].front();
|
||||||
|
@ -69,12 +62,10 @@ namespace libtorrent {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void alert_manager::maybe_notify(alert* a, std::unique_lock<std::mutex>& lock)
|
void alert_manager::maybe_notify(alert* a)
|
||||||
{
|
{
|
||||||
if (m_alerts[m_generation].size() == 1)
|
if (m_alerts[m_generation].size() == 1)
|
||||||
{
|
{
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
// we just posted to an empty queue. If anyone is waiting for
|
// we just posted to an empty queue. If anyone is waiting for
|
||||||
// alerts, we need to notify them. Also (potentially) call the
|
// alerts, we need to notify them. Also (potentially) call the
|
||||||
// user supplied m_notify callback to let the client wake up its
|
// user supplied m_notify callback to let the client wake up its
|
||||||
|
@ -85,10 +76,6 @@ namespace libtorrent {
|
||||||
// > 0 notify them
|
// > 0 notify them
|
||||||
m_condition.notify_all();
|
m_condition.notify_all();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (auto& e : m_ses_extensions)
|
for (auto& e : m_ses_extensions)
|
||||||
|
@ -100,12 +87,10 @@ namespace libtorrent {
|
||||||
|
|
||||||
void alert_manager::set_notify_function(std::function<void()> const& fun)
|
void alert_manager::set_notify_function(std::function<void()> const& fun)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||||
m_notify = fun;
|
m_notify = fun;
|
||||||
if (!m_alerts[m_generation].empty())
|
if (!m_alerts[m_generation].empty())
|
||||||
{
|
{
|
||||||
// never call a callback with the lock held!
|
|
||||||
lock.unlock();
|
|
||||||
if (m_notify) m_notify();
|
if (m_notify) m_notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,9 +104,8 @@ namespace libtorrent {
|
||||||
|
|
||||||
void alert_manager::get_all(std::vector<alert*>& alerts)
|
void alert_manager::get_all(std::vector<alert*>& alerts)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
alerts.clear();
|
|
||||||
if (m_alerts[m_generation].empty()) return;
|
if (m_alerts[m_generation].empty()) return;
|
||||||
|
|
||||||
m_alerts[m_generation].get_pointers(alerts);
|
m_alerts[m_generation].get_pointers(alerts);
|
||||||
|
@ -135,13 +119,13 @@ namespace libtorrent {
|
||||||
|
|
||||||
bool alert_manager::pending() const
|
bool alert_manager::pending() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
return !m_alerts[m_generation].empty();
|
return !m_alerts[m_generation].empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int alert_manager::set_alert_queue_size_limit(int queue_size_limit_)
|
int alert_manager::set_alert_queue_size_limit(int queue_size_limit_)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
std::swap(m_queue_size_limit, queue_size_limit_);
|
std::swap(m_queue_size_limit, queue_size_limit_);
|
||||||
return queue_size_limit_;
|
return queue_size_limit_;
|
||||||
|
@ -149,7 +133,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
dropped_alerts_t alert_manager::dropped_alerts()
|
dropped_alerts_t alert_manager::dropped_alerts()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||||
dropped_alerts_t const ret = m_dropped;
|
dropped_alerts_t const ret = m_dropped;
|
||||||
m_dropped.reset();
|
m_dropped.reset();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -277,3 +277,33 @@ TORRENT_TEST(dropped_alerts)
|
||||||
// it should have been cleared now though
|
// it should have been cleared now though
|
||||||
TEST_CHECK(mgr.dropped_alerts().none());
|
TEST_CHECK(mgr.dropped_alerts().none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
|
struct post_plugin : lt::plugin
|
||||||
|
{
|
||||||
|
explicit post_plugin(alert_manager& m) : mgr(m) {}
|
||||||
|
void on_alert(alert const*)
|
||||||
|
{
|
||||||
|
if (++depth > 10) return;
|
||||||
|
mgr.emplace_alert<piece_finished_alert>(torrent_handle(), piece_index_t{0});
|
||||||
|
}
|
||||||
|
|
||||||
|
alert_manager& mgr;
|
||||||
|
int depth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// make sure the alert manager supports alerts being posted while executing a
|
||||||
|
// plugin handler
|
||||||
|
TORRENT_TEST(recursive_alerts)
|
||||||
|
{
|
||||||
|
alert_manager mgr(100, alert::all_categories);
|
||||||
|
auto pl = std::make_shared<post_plugin>(mgr);
|
||||||
|
mgr.add_extension(pl);
|
||||||
|
|
||||||
|
mgr.emplace_alert<piece_finished_alert>(torrent_handle(), piece_index_t{0});
|
||||||
|
|
||||||
|
TEST_EQUAL(pl->depth, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TORRENT_DISABLE_EXTENSIONS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue