aboutsummaryrefslogtreecommitdiff
path: root/Src/nu/ProgressTracker.h
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nu/ProgressTracker.h')
-rw-r--r--Src/nu/ProgressTracker.h125
1 files changed, 125 insertions, 0 deletions
diff --git a/Src/nu/ProgressTracker.h b/Src/nu/ProgressTracker.h
new file mode 100644
index 00000000..c0f1153a
--- /dev/null
+++ b/Src/nu/ProgressTracker.h
@@ -0,0 +1,125 @@
+#include <map>
+#include "AutoLock.h"
+#include <bfc/platform/types.h>
+
+class ProgressTracker
+{
+public:
+ static const uint64_t null_position;
+ ProgressTracker()
+ {
+ current_position=0;
+ current_chunk=0;
+ chunks[0]=0;
+ chunks[null_position]=null_position;
+ };
+
+ void Write(uint64_t bytes_written)
+ {
+ Nullsoft::Utility::AutoLock list_lock(list_guard);
+ ChunkList::iterator next, itr = chunks.find(current_chunk);
+ current_position += bytes_written;
+ if (itr->second < current_position)
+ itr->second = current_position;
+
+ for (;;)
+ {
+ next = itr;
+ ++next;
+ if (next != chunks.end() && (next->first <= itr->second))
+ {
+ itr->second = next->second;
+ chunks.erase(next);
+ }
+ else
+ break;
+ }
+ }
+
+ bool Valid(uint64_t requested_position, uint64_t requested_end)
+ {
+ Nullsoft::Utility::AutoLock list_lock(list_guard);
+ for (ChunkList::iterator itr=chunks.begin();itr!=chunks.end();itr++)
+ {
+ if (requested_position >= itr->first)
+ {
+ if (requested_position < itr->second)
+ {
+ if (requested_end <= itr->second)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ bool Seek(uint64_t requested_position, uint64_t requested_end, uint64_t *new_start, uint64_t *new_end)
+ {
+ Nullsoft::Utility::AutoLock list_lock(list_guard);
+ uint64_t last_good_start=0;
+ ChunkList::iterator itr;
+ for (itr=chunks.begin();itr!=chunks.end();itr++)
+ {
+ if (requested_position >= itr->first)
+ {
+ current_chunk = itr->first;
+ if (requested_position <= itr->second)
+ {
+ ChunkList::iterator next = itr;
+ ++next;
+ *new_end = next->first;
+
+ *new_start = current_position = itr->second;
+
+ if (requested_end <= itr->second)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ last_good_start = itr->second;
+ }
+ }
+ }
+ if (last_good_start > requested_position)
+ *new_start = current_position = last_good_start;
+ else
+ {
+
+ *new_start = current_chunk = current_position = requested_position;
+ chunks[current_chunk] = current_chunk;
+ }
+ *new_end = null_position;
+ return false;
+ }
+
+#if 0
+ void Dump()
+ {
+ ChunkList::iterator itr;
+ for (itr=chunks.begin();itr!=chunks.end();itr++)
+ {
+ printf("%I64u - %I64u\n", itr->first, itr->second);
+ }
+
+ }
+ #endif
+
+ typedef std::map<uint64_t, uint64_t> ChunkList;
+ ChunkList chunks;
+ uint64_t current_chunk;
+ uint64_t current_position;
+ Nullsoft::Utility::LockGuard list_guard;
+};
+const uint64_t ProgressTracker::null_position = (uint64_t)-1; \ No newline at end of file