/src/libtorrent/src/alert_manager.cpp
Line | Count | Source |
1 | | /* |
2 | | |
3 | | Copyright (c) 2003-2013, Daniel Wallin |
4 | | Copyright (c) 2013-2020, Arvid Norberg |
5 | | Copyright (c) 2015, Steven Siloti |
6 | | Copyright (c) 2016, 2020, Alden Torres |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use in source and binary forms, with or without |
10 | | modification, are permitted provided that the following conditions |
11 | | are met: |
12 | | |
13 | | * Redistributions of source code must retain the above copyright |
14 | | notice, this list of conditions and the following disclaimer. |
15 | | * Redistributions in binary form must reproduce the above copyright |
16 | | notice, this list of conditions and the following disclaimer in |
17 | | the documentation and/or other materials provided with the distribution. |
18 | | * Neither the name of the author nor the names of its |
19 | | contributors may be used to endorse or promote products derived |
20 | | from this software without specific prior written permission. |
21 | | |
22 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
23 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
26 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | | POSSIBILITY OF SUCH DAMAGE. |
33 | | |
34 | | */ |
35 | | |
36 | | #include "libtorrent/config.hpp" |
37 | | #include "libtorrent/aux_/alert_manager.hpp" |
38 | | #include "libtorrent/alert_types.hpp" |
39 | | |
40 | | #ifndef TORRENT_DISABLE_EXTENSIONS |
41 | | #include "libtorrent/extensions.hpp" |
42 | | #include <memory> // for shared_ptr |
43 | | #endif |
44 | | |
45 | | namespace libtorrent { |
46 | | namespace aux { |
47 | | |
48 | | alert_manager::alert_manager(int const queue_limit, alert_category_t const alert_mask) |
49 | 0 | : m_alert_mask(alert_mask) |
50 | 0 | , m_queue_size_limit(queue_limit) |
51 | 0 | {} |
52 | | |
53 | 0 | alert_manager::~alert_manager() = default; |
54 | | |
55 | | alert* alert_manager::wait_for_alert(time_duration max_wait) |
56 | 0 | { |
57 | 0 | std::unique_lock<std::recursive_mutex> lock(m_mutex); |
58 | |
|
59 | 0 | if (!m_alerts[m_generation & 1].empty()) |
60 | 0 | return m_alerts[m_generation & 1].front(); |
61 | | |
62 | | // this call can be interrupted prematurely by other signals |
63 | 0 | m_condition.wait_for(lock, max_wait); |
64 | 0 | if (!m_alerts[m_generation & 1].empty()) |
65 | 0 | return m_alerts[m_generation & 1].front(); |
66 | | |
67 | 0 | return nullptr; |
68 | 0 | } |
69 | | |
70 | | void alert_manager::maybe_notify(alert* a) |
71 | 0 | { |
72 | 0 | if (m_alerts[m_generation & 1].size() == 1) |
73 | 0 | { |
74 | | // we just posted to an empty queue. If anyone is waiting for |
75 | | // alerts, we need to notify them. Also (potentially) call the |
76 | | // user supplied m_notify callback to let the client wake up its |
77 | | // message loop to poll for alerts. |
78 | 0 | if (m_notify) m_notify(); |
79 | | |
80 | | // TODO: 2 keep a count of the number of threads waiting. Only if it's |
81 | | // > 0 notify them |
82 | 0 | m_condition.notify_all(); |
83 | 0 | } |
84 | |
|
85 | 0 | #ifndef TORRENT_DISABLE_EXTENSIONS |
86 | 0 | for (auto& e : m_ses_extensions) |
87 | 0 | e->on_alert(a); |
88 | | #else |
89 | | TORRENT_UNUSED(a); |
90 | | #endif |
91 | 0 | } |
92 | | |
93 | | void alert_manager::set_notify_function(std::function<void()> const& fun) |
94 | 0 | { |
95 | 0 | std::unique_lock<std::recursive_mutex> lock(m_mutex); |
96 | 0 | m_notify = fun; |
97 | 0 | if (!m_alerts[m_generation & 1].empty()) |
98 | 0 | { |
99 | 0 | if (m_notify) m_notify(); |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | #ifndef TORRENT_DISABLE_EXTENSIONS |
104 | | void alert_manager::add_extension(std::shared_ptr<plugin> ext) |
105 | 0 | { |
106 | 0 | m_ses_extensions.push_back(std::move(ext)); |
107 | 0 | } |
108 | | #endif |
109 | | |
110 | | void alert_manager::get_all(std::vector<alert*>& alerts) |
111 | 0 | { |
112 | 0 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
113 | |
|
114 | 0 | if (m_alerts[m_generation & 1].empty()) |
115 | 0 | { |
116 | 0 | alerts.clear(); |
117 | 0 | return; |
118 | 0 | } |
119 | | |
120 | 0 | if (m_dropped.any()) { |
121 | 0 | emplace_alert<alerts_dropped_alert>(m_dropped); |
122 | 0 | m_dropped.reset(); |
123 | 0 | } |
124 | |
|
125 | 0 | m_alerts[m_generation & 1].get_pointers(alerts); |
126 | | |
127 | | // swap buffers |
128 | 0 | m_generation += 1; |
129 | | // clear the one we will start writing to now |
130 | 0 | m_alerts[m_generation & 1].clear(); |
131 | 0 | m_allocations[m_generation & 1].reset(m_generation); |
132 | 0 | } |
133 | | |
134 | | bool alert_manager::pending() const |
135 | 0 | { |
136 | 0 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
137 | 0 | return !m_alerts[m_generation & 1].empty(); |
138 | 0 | } |
139 | | |
140 | | int alert_manager::set_alert_queue_size_limit(int queue_size_limit_) |
141 | 0 | { |
142 | 0 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
143 | |
|
144 | 0 | std::swap(m_queue_size_limit, queue_size_limit_); |
145 | 0 | return queue_size_limit_; |
146 | 0 | } |
147 | | } |
148 | | } |