use a condition variable in alert_manager to trigger wait_for_alert threads
This commit is contained in:
parent
652bf8323b
commit
f440bca2c4
117
docs/todo.html
117
docs/todo.html
|
@ -25,61 +25,7 @@
|
|||
<span style="color: #3c3">9 relevant</span>
|
||||
<span style="color: #77f">16 feasible</span>
|
||||
<span style="color: #999">33 notes</span>
|
||||
<table width="100%" border="1" style="border-collapse: collapse;"><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(0)">src/alert.cpp:370</a></td><td>change this to use a timed wait on a condition variable problem is, that's not necessarily portable. But it should be used where available. This implementation can be left the way it is for more primitive platforms</td></tr><tr id="0" style="display: none;" colspan="3"><td colspan="3"><h2>change this to use a timed wait on a condition variable
|
||||
problem is, that's not necessarily portable. But it should be used
|
||||
where available. This implementation can be left the way it is for
|
||||
more primitive platforms</h2><h4>src/alert.cpp:370</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> delete m_alerts.front();
|
||||
m_alerts.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
alert const* alert_manager::wait_for_alert(time_duration max_wait)
|
||||
{
|
||||
mutex::scoped_lock lock(m_mutex);
|
||||
|
||||
if (!m_alerts.empty()) return m_alerts.front();
|
||||
|
||||
// system_time end = get_system_time()
|
||||
// + boost::posix_time::microseconds(total_microseconds(max_wait));
|
||||
|
||||
// this call can be interrupted prematurely by other signals
|
||||
// while (m_condition.timed_wait(lock, end))
|
||||
// if (!m_alerts.empty()) return m_alerts.front();
|
||||
|
||||
ptime start = time_now_hires();
|
||||
|
||||
<div style="background: #ffff00" width="100%"> while (m_alerts.empty())
|
||||
</div> {
|
||||
lock.unlock();
|
||||
sleep(50);
|
||||
lock.lock();
|
||||
if (time_now_hires() - start >= max_wait) return 0;
|
||||
}
|
||||
return m_alerts.front();
|
||||
}
|
||||
|
||||
void alert_manager::set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const& fun)
|
||||
{
|
||||
mutex::scoped_lock lock(m_mutex);
|
||||
|
||||
m_dispatch = fun;
|
||||
|
||||
std::deque<alert*> alerts;
|
||||
m_alerts.swap(alerts);
|
||||
lock.unlock();
|
||||
|
||||
while (!alerts.empty())
|
||||
{
|
||||
TORRENT_TRY {
|
||||
m_dispatch(std::auto_ptr<alert>(alerts.front()));
|
||||
} TORRENT_CATCH(std::exception&) {}
|
||||
alerts.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch_alert(boost::function<void(alert const&)> dispatcher
|
||||
, alert* alert_)
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(1)">src/storage.cpp:989</a></td><td>use binary search to find the file entry</td></tr><tr id="1" style="display: none;" colspan="3"><td colspan="3"><h2>use binary search to find the file entry</h2><h4>src/storage.cpp:989</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> size_type ret = 0;
|
||||
<table width="100%" border="1" style="border-collapse: collapse;"><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(0)">src/storage.cpp:989</a></td><td>use binary search to find the file entry</td></tr><tr id="0" style="display: none;" colspan="3"><td colspan="3"><h2>use binary search to find the file entry</h2><h4>src/storage.cpp:989</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> size_type ret = 0;
|
||||
if (f && !ec) ret = f->phys_offset(file_offset);
|
||||
|
||||
if (ret == 0)
|
||||
|
@ -130,7 +76,7 @@ more primitive platforms</h2><h4>src/alert.cpp:370</h4><pre style="background: #
|
|||
if (file_bytes_left == 0) continue;
|
||||
|
||||
if (file_iter->pad_file) continue;
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(2)">src/storage.cpp:1095</a></td><td>use binary search to find the file entry</td></tr><tr id="2" style="display: none;" colspan="3"><td colspan="3"><h2>use binary search to find the file entry</h2><h4>src/storage.cpp:1095</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> TORRENT_ASSERT(offset >= 0);
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(1)">src/storage.cpp:1095</a></td><td>use binary search to find the file entry</td></tr><tr id="1" style="display: none;" colspan="3"><td colspan="3"><h2>use binary search to find the file entry</h2><h4>src/storage.cpp:1095</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> TORRENT_ASSERT(offset >= 0);
|
||||
TORRENT_ASSERT(offset < m_files.piece_size(slot));
|
||||
TORRENT_ASSERT(num_bufs > 0);
|
||||
|
||||
|
@ -181,7 +127,7 @@ more primitive platforms</h2><h4>src/alert.cpp:370</h4><pre style="background: #
|
|||
copy_bufs(bufs, size, current_buf);
|
||||
TORRENT_ASSERT(count_bufs(current_buf, size) == num_bufs);
|
||||
int file_bytes_left;
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(3)">src/torrent.cpp:1505</a></td><td>filter out peers that are disconnecting</td></tr><tr id="3" style="display: none;" colspan="3"><td colspan="3"><h2>filter out peers that are disconnecting</h2><h4>src/torrent.cpp:1505</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> snprintf(filename, sizeof(filename), "/tmp/%d.pem", rand());
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(2)">src/torrent.cpp:1505</a></td><td>filter out peers that are disconnecting</td></tr><tr id="2" style="display: none;" colspan="3"><td colspan="3"><h2>filter out peers that are disconnecting</h2><h4>src/torrent.cpp:1505</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> snprintf(filename, sizeof(filename), "/tmp/%d.pem", rand());
|
||||
FILE* f = fopen(filename, "w+");
|
||||
fwrite(cert.c_str(), cert.size(), 1, f);
|
||||
fclose(f);
|
||||
|
@ -232,7 +178,7 @@ more primitive platforms</h2><h4>src/alert.cpp:370</h4><pre style="background: #
|
|||
{
|
||||
set_error(errors::too_many_pieces_in_torrent, "");
|
||||
pause();
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(4)">src/torrent.cpp:6004</a></td><td>if peer is a really good peer, maybe we shouldn't disconnect it</td></tr><tr id="4" style="display: none;" colspan="3"><td colspan="3"><h2>if peer is a really good peer, maybe we shouldn't disconnect it</h2><h4>src/torrent.cpp:6004</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> return false;
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(3)">src/torrent.cpp:6004</a></td><td>if peer is a really good peer, maybe we shouldn't disconnect it</td></tr><tr id="3" style="display: none;" colspan="3"><td colspan="3"><h2>if peer is a really good peer, maybe we shouldn't disconnect it</h2><h4>src/torrent.cpp:6004</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> return false;
|
||||
}
|
||||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||
m_connections.insert(p);
|
||||
|
@ -283,7 +229,7 @@ more primitive platforms</h2><h4>src/alert.cpp:370</h4><pre style="background: #
|
|||
return m_connections.size() < m_max_connections
|
||||
&& !is_paused()
|
||||
&& ((m_state != torrent_status::checking_files
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(5)">src/torrent.cpp:8718</a></td><td>with 110 as response codes, we should just consider the tracker as a failure and not retry it anymore</td></tr><tr id="5" style="display: none;" colspan="3"><td colspan="3"><h2>with 110 as response codes, we should just consider
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(4)">src/torrent.cpp:8718</a></td><td>with 110 as response codes, we should just consider the tracker as a failure and not retry it anymore</td></tr><tr id="4" style="display: none;" colspan="3"><td colspan="3"><h2>with 110 as response codes, we should just consider
|
||||
the tracker as a failure and not retry
|
||||
it anymore</h2><h4>src/torrent.cpp:8718</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> TORRENT_ASSERT(m_ses.is_network_thread());
|
||||
TORRENT_ASSERT(b > 0);
|
||||
|
@ -336,7 +282,7 @@ it anymore</h2><h4>src/torrent.cpp:8718</h4><pre style="background: #f6f6f6; bor
|
|||
, ae?ae->fails:0, response_code, r.url, ec, msg));
|
||||
}
|
||||
}
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(6)">src/utp_stream.cpp:412</a></td><td>remove the read timeout concept. This should not be necessary</td></tr><tr id="6" style="display: none;" colspan="3"><td colspan="3"><h2>remove the read timeout concept. This should not be necessary</h2><h4>src/utp_stream.cpp:412</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> // these are the callbacks made into the utp_stream object
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(5)">src/utp_stream.cpp:412</a></td><td>remove the read timeout concept. This should not be necessary</td></tr><tr id="5" style="display: none;" colspan="3"><td colspan="3"><h2>remove the read timeout concept. This should not be necessary</h2><h4>src/utp_stream.cpp:412</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> // these are the callbacks made into the utp_stream object
|
||||
// on read/write/connect events
|
||||
utp_stream::handler_t m_read_handler;
|
||||
utp_stream::handler_t m_write_handler;
|
||||
|
@ -358,7 +304,7 @@ it anymore</h2><h4>src/torrent.cpp:8718</h4><pre style="background: #f6f6f6; bor
|
|||
// before)
|
||||
<div style="background: #ffff00" width="100%"> ptime m_read_timeout;
|
||||
</div>
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(7)">src/utp_stream.cpp:415</a></td><td>remove the write timeout concept. This should not be necessary</td></tr><tr id="7" style="display: none;" colspan="3"><td colspan="3"><h2>remove the write timeout concept. This should not be necessary</h2><h4>src/utp_stream.cpp:415</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> // these are the callbacks made into the utp_stream object
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(6)">src/utp_stream.cpp:415</a></td><td>remove the write timeout concept. This should not be necessary</td></tr><tr id="6" style="display: none;" colspan="3"><td colspan="3"><h2>remove the write timeout concept. This should not be necessary</h2><h4>src/utp_stream.cpp:415</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> // these are the callbacks made into the utp_stream object
|
||||
// on read/write/connect events
|
||||
utp_stream::handler_t m_read_handler;
|
||||
utp_stream::handler_t m_write_handler;
|
||||
|
@ -409,7 +355,7 @@ it anymore</h2><h4>src/torrent.cpp:8718</h4><pre style="background: #f6f6f6; bor
|
|||
timestamp_history m_their_delay_hist;
|
||||
|
||||
// the number of bytes we have buffered in m_inbuf
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(8)">src/kademlia/rpc_manager.cpp:36</a></td><td>remove this dependency by having the dht observer have its own flags</td></tr><tr id="8" style="display: none;" colspan="3"><td colspan="3"><h2>remove this dependency by having the dht observer
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(7)">src/kademlia/rpc_manager.cpp:36</a></td><td>remove this dependency by having the dht observer have its own flags</td></tr><tr id="7" style="display: none;" colspan="3"><td colspan="3"><h2>remove this dependency by having the dht observer
|
||||
have its own flags</h2><h4>src/kademlia/rpc_manager.cpp:36</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
|
@ -461,6 +407,53 @@ namespace io = libtorrent::detail;
|
|||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DEFINE_LOG(rpc)
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(8)">include/libtorrent/thread.hpp:61</a></td><td>make this interface compatible with c++11 to allow for smooth transition for platforms with support</td></tr><tr id="8" style="display: none;" colspan="3"><td colspan="3"><h2>make this interface compatible with c++11
|
||||
to allow for smooth transition for platforms with support</h2><h4>include/libtorrent/thread.hpp:61</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;">#endif
|
||||
|
||||
#if defined TORRENT_BEOS
|
||||
#include <kernel/OS.h>
|
||||
#endif
|
||||
|
||||
#include <memory> // for auto_ptr required by asio
|
||||
|
||||
#include <boost/asio/detail/thread.hpp>
|
||||
#include <boost/asio/detail/mutex.hpp>
|
||||
#include <boost/asio/detail/event.hpp>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
typedef boost::asio::detail::thread thread;
|
||||
typedef boost::asio::detail::mutex mutex;
|
||||
typedef boost::asio::detail::event event;
|
||||
|
||||
TORRENT_EXPORT void sleep(int milliseconds);
|
||||
|
||||
<div style="background: #ffff00" width="100%"> struct TORRENT_EXTRA_EXPORT condition
|
||||
</div> {
|
||||
condition();
|
||||
~condition();
|
||||
void wait(mutex::scoped_lock& l);
|
||||
void timed_wait(mutex::scoped_lock& l, int sleep_ms);
|
||||
void signal_all(mutex::scoped_lock& l);
|
||||
private:
|
||||
#ifdef BOOST_HAS_PTHREADS
|
||||
pthread_cond_t m_cond;
|
||||
#elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
|
||||
HANDLE m_sem;
|
||||
mutex m_mutex;
|
||||
int m_num_waiters;
|
||||
#elif defined TORRENT_BEOS
|
||||
sem_id m_sem;
|
||||
mutex m_mutex;
|
||||
int m_num_waiters;
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
</pre></td></tr><tr style="background: #fcc"><td>relevance 3</td><td><a href="javascript:expand(9)">include/libtorrent/kademlia/dht_tracker.hpp:79</a></td><td>take a udp_socket_interface here instead. Move udp_socket_interface down into libtorrent core</td></tr><tr id="9" style="display: none;" colspan="3"><td colspan="3"><h2>take a udp_socket_interface here instead. Move udp_socket_interface down into libtorrent core</h2><h4>include/libtorrent/kademlia/dht_tracker.hpp:79</h4><pre style="background: #f6f6f6; border: solid 1px #ddd;"> struct lazy_entry;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,11 +171,11 @@ namespace libtorrent {
|
|||
#endif
|
||||
|
||||
private:
|
||||
void post_impl(std::auto_ptr<alert>& alert_);
|
||||
void post_impl(std::auto_ptr<alert>& alert_, mutex::scoped_lock& l);
|
||||
|
||||
std::deque<alert*> m_alerts;
|
||||
mutable mutex m_mutex;
|
||||
// event m_condition;
|
||||
condition m_condition;
|
||||
boost::uint32_t m_alert_mask;
|
||||
size_t m_queue_size_limit;
|
||||
boost::function<void(std::auto_ptr<alert>)> m_dispatch;
|
||||
|
|
|
@ -58,11 +58,14 @@ namespace libtorrent
|
|||
|
||||
TORRENT_EXPORT void sleep(int milliseconds);
|
||||
|
||||
// TODO: 3 make this interface compatible with c++11
|
||||
// to allow for smooth transition for platforms with support
|
||||
struct TORRENT_EXTRA_EXPORT condition
|
||||
{
|
||||
condition();
|
||||
~condition();
|
||||
void wait(mutex::scoped_lock& l);
|
||||
void timed_wait(mutex::scoped_lock& l, int sleep_ms);
|
||||
void signal_all(mutex::scoped_lock& l);
|
||||
private:
|
||||
#ifdef BOOST_HAS_PTHREADS
|
||||
|
|
|
@ -358,27 +358,11 @@ namespace libtorrent {
|
|||
|
||||
if (!m_alerts.empty()) return m_alerts.front();
|
||||
|
||||
// system_time end = get_system_time()
|
||||
// + boost::posix_time::microseconds(total_microseconds(max_wait));
|
||||
|
||||
// this call can be interrupted prematurely by other signals
|
||||
// while (m_condition.timed_wait(lock, end))
|
||||
// if (!m_alerts.empty()) return m_alerts.front();
|
||||
m_condition.timed_wait(lock, total_milliseconds(max_wait));
|
||||
if (!m_alerts.empty()) return m_alerts.front();
|
||||
|
||||
ptime start = time_now_hires();
|
||||
|
||||
// TODO: 3 change this to use a timed wait on a condition variable
|
||||
// problem is, that's not necessarily portable. But it should be used
|
||||
// where available. This implementation can be left the way it is for
|
||||
// more primitive platforms
|
||||
while (m_alerts.empty())
|
||||
{
|
||||
lock.unlock();
|
||||
sleep(50);
|
||||
lock.lock();
|
||||
if (time_now_hires() - start >= max_wait) return 0;
|
||||
}
|
||||
return m_alerts.front();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void alert_manager::set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const& fun)
|
||||
|
@ -422,7 +406,7 @@ namespace libtorrent {
|
|||
#endif
|
||||
|
||||
mutex::scoped_lock lock(m_mutex);
|
||||
post_impl(a);
|
||||
post_impl(a, lock);
|
||||
}
|
||||
|
||||
void alert_manager::post_alert(const alert& alert_)
|
||||
|
@ -440,10 +424,10 @@ namespace libtorrent {
|
|||
#endif
|
||||
|
||||
mutex::scoped_lock lock(m_mutex);
|
||||
post_impl(a);
|
||||
post_impl(a, lock);
|
||||
}
|
||||
|
||||
void alert_manager::post_impl(std::auto_ptr<alert>& alert_)
|
||||
void alert_manager::post_impl(std::auto_ptr<alert>& alert_, mutex::scoped_lock& l)
|
||||
{
|
||||
if (m_dispatch)
|
||||
{
|
||||
|
@ -455,6 +439,8 @@ namespace libtorrent {
|
|||
else if (m_alerts.size() < m_queue_size_limit || !alert_->discardable())
|
||||
{
|
||||
m_alerts.push_back(alert_.release());
|
||||
if (m_alerts.size() == 1)
|
||||
m_condition.signal_all(l);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <kernel/OS.h>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PTHREADS
|
||||
#include <sys/time.h> // for gettimeofday()
|
||||
#include <boost/cstdint.hpp>
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
void sleep(int milliseconds)
|
||||
|
@ -69,6 +74,21 @@ namespace libtorrent
|
|||
pthread_cond_wait(&m_cond, (::pthread_mutex_t*)&l.mutex());
|
||||
}
|
||||
|
||||
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
||||
struct timeval tv;
|
||||
struct timespec ts;
|
||||
gettimeofday(&tv, NULL);
|
||||
boost::uint64_t microseconds = tv.tv_usec + boost::uint64_t(sleep_ms % 1000) * 1000;
|
||||
ts.tv_nsec = (microseconds % 1000000) * 1000;
|
||||
ts.tv_sec = tv.tv_sec + sleep_ms / 1000 + microseconds / 1000000;
|
||||
|
||||
// wow, this is quite a hack
|
||||
pthread_cond_timedwait(&m_cond, (::pthread_mutex_t*)&l.mutex(), &ts);
|
||||
}
|
||||
|
||||
void condition::signal_all(mutex::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
@ -96,6 +116,16 @@ namespace libtorrent
|
|||
--m_num_waiters;
|
||||
}
|
||||
|
||||
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
++m_num_waiters;
|
||||
l.unlock();
|
||||
WaitForSingleObject(m_sem, sleep_ms);
|
||||
l.lock();
|
||||
--m_num_waiters;
|
||||
}
|
||||
|
||||
void condition::signal_all(mutex::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
@ -123,6 +153,16 @@ namespace libtorrent
|
|||
--m_num_waiters;
|
||||
}
|
||||
|
||||
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
++m_num_waiters;
|
||||
l.unlock();
|
||||
acquire_sem_etc(m_sem, 1, B_RELATIVE_TIMEOUT, bigtime_t(sleep_ms) * 1000);
|
||||
l.lock();
|
||||
--m_num_waiters;
|
||||
}
|
||||
|
||||
void condition::signal_all(mutex::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
|
Loading…
Reference in New Issue