updated documentation to call out the save-resume-data race condition and added an assert to the destructor of alert_manager

This commit is contained in:
Arvid Norberg 2011-07-04 05:45:39 +00:00
parent 444d584446
commit 94b3ef81c3
2 changed files with 22 additions and 5 deletions

View File

@ -3057,7 +3057,7 @@ closing down.
Example code to pause and save resume data for all torrents and wait for the alerts:: Example code to pause and save resume data for all torrents and wait for the alerts::
int num_resume_data = 0; extern int outstanding_resume_data; // global counter of outstanding resume data
std::vector<torrent_handle> handles = ses.get_torrents(); std::vector<torrent_handle> handles = ses.get_torrents();
ses.pause(); ses.pause();
for (std::vector<torrent_handle>::iterator i = handles.begin(); for (std::vector<torrent_handle>::iterator i = handles.begin();
@ -3067,12 +3067,13 @@ Example code to pause and save resume data for all torrents and wait for the ale
if (!h.is_valid()) continue; if (!h.is_valid()) continue;
torrent_status s = h.status(); torrent_status s = h.status();
if (!s.has_metadata) continue; if (!s.has_metadata) continue;
if (!s.need_save_resume_data()) continue;
h.save_resume_data(); h.save_resume_data();
++num_resume_data; ++outstanding_resume_data;
} }
while (num_resume_data > 0) while (outstanding_resume_data > 0)
{ {
alert const* a = ses.wait_for_alert(seconds(10)); alert const* a = ses.wait_for_alert(seconds(10));
@ -3084,7 +3085,7 @@ Example code to pause and save resume data for all torrents and wait for the ale
if (alert_cast<save_resume_data_failed_alert>(a)) if (alert_cast<save_resume_data_failed_alert>(a))
{ {
process_alert(a); process_alert(a);
--num_resume_data; --outstanding_resume_data;
continue; continue;
} }
@ -3100,9 +3101,16 @@ Example code to pause and save resume data for all torrents and wait for the ale
/ (h.get_torrent_info().name() + ".fastresume"), std::ios_base::binary); / (h.get_torrent_info().name() + ".fastresume"), std::ios_base::binary);
out.unsetf(std::ios_base::skipws); out.unsetf(std::ios_base::skipws);
bencode(std::ostream_iterator<char>(out), *rd->resume_data); bencode(std::ostream_iterator<char>(out), *rd->resume_data);
--num_resume_data; --outstanding_resume_data;
} }
.. note:: Note how ``outstanding_resume_data`` is a global counter in this example.
This is deliberate, otherwise there is a race condition for torrents that
was just asked to save their resume data, they posted the alert, but it has
not been received yet. Those torrents would report that they don't need to
save resume data again, and skipped by the initial loop, and thwart the counter
otherwise.
need_save_resume_data() need_save_resume_data()
----------------------- -----------------------
@ -3116,6 +3124,11 @@ torrent was first loaded or since the last time the resume data was saved. When
saving resume data periodically, it makes sense to skip any torrent which hasn't saving resume data periodically, it makes sense to skip any torrent which hasn't
downloaded anything since the last time. downloaded anything since the last time.
.. note:: A torrent's resume data is considered saved as soon as the alert
is posted. It is important to make sure this alert is received and handled
in order for this function to be meaningful.
status() status()
-------- --------

View File

@ -341,6 +341,10 @@ namespace libtorrent {
{ {
while (!m_alerts.empty()) while (!m_alerts.empty())
{ {
TORRENT_ASSERT(alert_cast<save_resume_data_alert>(m_alerts.front()) == 0
&& "shutting down session with remaining resume data alerts in the alert queue. "
"You proabably wany to make sure you always wait for all resume data "
"alerts before shutting down");
delete m_alerts.front(); delete m_alerts.front();
m_alerts.pop_front(); m_alerts.pop_front();
} }