mirror of https://github.com/aria2/aria2
				
				
				
			Use std::deque instead of std::list in IndexedList
We choose faster iteration over rare slower deletion in the middle.pull/46/head
							parent
							
								
									643e7222b0
								
							
						
					
					
						commit
						561f0b3e29
					
				|  | @ -37,8 +37,10 @@ | |||
| 
 | ||||
| #include "common.h" | ||||
| 
 | ||||
| #include <list> | ||||
| #include <deque> | ||||
| #include <map> | ||||
| #include <vector> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| namespace aria2 { | ||||
| 
 | ||||
|  | @ -48,15 +50,14 @@ enum A2_HOW { | |||
|   A2_POS_END | ||||
| }; | ||||
| 
 | ||||
| // List with O(logN) look-up using std::map as an index.
 | ||||
| template<typename KeyType, typename ValuePtrType> | ||||
| class IndexedList { | ||||
| public: | ||||
|   IndexedList() {} | ||||
|   ~IndexedList() {} | ||||
| 
 | ||||
|   typedef std::list<std::pair<KeyType, ValuePtrType> > SeqType; | ||||
|   typedef std::map<KeyType, typename SeqType::iterator> IndexType; | ||||
|   typedef std::deque<std::pair<KeyType, ValuePtrType> > SeqType; | ||||
|   typedef std::map<KeyType, ValuePtrType> IndexType; | ||||
| 
 | ||||
|   // Inserts (|key|, |value|) to the end of the list. If the same key
 | ||||
|   // has been already added, this function fails. This function
 | ||||
|  | @ -65,10 +66,9 @@ public: | |||
|   { | ||||
|     typename IndexType::iterator i = index_.lower_bound(key); | ||||
|     if(i == index_.end() || (*i).first != key) { | ||||
|       seq_.push_back(std::make_pair(key, value)); | ||||
|       typename SeqType::iterator j = seq_.end(); | ||||
|       --j; | ||||
|       index_.insert(i, std::make_pair(key, j)); | ||||
|       std::pair<KeyType, ValuePtrType> p(key, value); | ||||
|       seq_.push_back(p); | ||||
|       index_.insert(i, p); | ||||
|       return true; | ||||
|     } else { | ||||
|       return false; | ||||
|  | @ -82,9 +82,9 @@ public: | |||
|   { | ||||
|     typename IndexType::iterator i = index_.lower_bound(key); | ||||
|     if(i == index_.end() || (*i).first != key) { | ||||
|       seq_.push_front(std::make_pair(key, value)); | ||||
|       typename SeqType::iterator j = seq_.begin(); | ||||
|       index_.insert(i, std::make_pair(key, j)); | ||||
|       std::pair<KeyType, ValuePtrType> p(key, value); | ||||
|       seq_.push_front(p); | ||||
|       index_.insert(i, p); | ||||
|       return true; | ||||
|     } else { | ||||
|       return false; | ||||
|  | @ -105,8 +105,9 @@ public: | |||
|     if(i == index_.end() || (*i).first != key) { | ||||
|       typename SeqType::iterator j = seq_.begin(); | ||||
|       std::advance(j, dest); | ||||
|       j = seq_.insert(j, std::make_pair(key, value)); | ||||
|       index_.insert(i, std::make_pair(key, j)); | ||||
|       std::pair<KeyType, ValuePtrType> p(key, value); | ||||
|       j = seq_.insert(j, p); | ||||
|       index_.insert(i, p); | ||||
|       return j; | ||||
|     } else { | ||||
|       return seq_.end(); | ||||
|  | @ -116,32 +117,61 @@ public: | |||
|   // Inserts (|key|, |value|) to the position |dest|. If the same key
 | ||||
|   // has been already added, this function fails. This function
 | ||||
|   // returns the iterator to the newly added element if it is
 | ||||
|   // succeeds, or end(). Complexity: O(logN)
 | ||||
|   // succeeds, or end(). Complexity: O(logN) if inserted to the first
 | ||||
|   // or last, otherwise O(N)
 | ||||
|   typename SeqType::iterator insert(typename SeqType::iterator dest, | ||||
|                                     KeyType key, | ||||
|                                     ValuePtrType value) | ||||
|   { | ||||
|     typename IndexType::iterator i = index_.lower_bound(key); | ||||
|     if(i == index_.end() || (*i).first != key) { | ||||
|       dest = seq_.insert(dest, std::make_pair(key, value)); | ||||
|       index_.insert(i, std::make_pair(key, dest)); | ||||
|       std::pair<KeyType, ValuePtrType> p(key, value); | ||||
|       dest = seq_.insert(dest, p); | ||||
|       index_.insert(i, p); | ||||
|       return dest; | ||||
|     } else { | ||||
|       return seq_.end(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Inserts values in iterator range [first, last). The key for each
 | ||||
|   // value is retrieved by functor |keyFunc|. The insertion position
 | ||||
|   // is given by |dest|.
 | ||||
|   template<typename KeyFunc, typename InputIterator> | ||||
|   void insert(typename SeqType::iterator dest, KeyFunc keyFunc, | ||||
|               InputIterator first, InputIterator last) | ||||
|   { | ||||
|     std::vector<typename SeqType::value_type> v; | ||||
|     v.reserve(std::distance(first, last)); | ||||
|     for(; first != last; ++first) { | ||||
|       KeyType key = keyFunc(*first); | ||||
|       typename IndexType::iterator i = index_.lower_bound(key); | ||||
|       if(i == index_.end() || (*i).first != key) { | ||||
|         std::pair<KeyType, ValuePtrType> p(key, *first); | ||||
|         v.push_back(p); | ||||
|         index_.insert(i, p); | ||||
|       } | ||||
|     } | ||||
|     seq_.insert(dest, v.begin(), v.end()); | ||||
|   } | ||||
| 
 | ||||
|   // Removes |key| from the list. If the element is not found, this
 | ||||
|   // function fails. This function returns true if it
 | ||||
|   // succeeds. Complexity: O(logN)
 | ||||
|   // succeeds. Complexity: O(N)
 | ||||
|   bool erase(KeyType key) | ||||
|   { | ||||
|     typename IndexType::iterator i = index_.find(key); | ||||
|     if(i == index_.end()) { | ||||
|       return false; | ||||
|     } | ||||
|     seq_.erase((*i).second); | ||||
|     index_.erase(i); | ||||
|     for(typename SeqType::iterator j = seq_.begin(), eoj = seq_.end(); | ||||
|         j != eoj; ++j) { | ||||
|       if((*j).first == key) { | ||||
|         seq_.erase(j); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|  | @ -174,40 +204,38 @@ public: | |||
|     if(idxent == index_.end()) { | ||||
|       return -1; | ||||
|     } | ||||
|     typename SeqType::iterator x = seq_.begin(), eseq = seq_.end(); | ||||
|     for(; x != eseq; ++x) { | ||||
|       if((*x).first == key) { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     ssize_t xp = std::distance(seq_.begin(), x); | ||||
|     ssize_t size = index_.size(); | ||||
|     ssize_t dest; | ||||
|     typename SeqType::iterator x = (*idxent).second; | ||||
|     typename SeqType::iterator d; | ||||
|     if(how == A2_POS_CUR) { | ||||
|       // Because aria2.changePosition() RPC method must return the
 | ||||
|       // absolute position after move, we have to calculate absolute
 | ||||
|       // position here.
 | ||||
|       if(offset > 0) { | ||||
|         d = x; | ||||
|         for(; offset >= 0 && d != seq_.end(); --offset, ++d); | ||||
|         dest = std::distance(seq_.begin(), d)-1; | ||||
|         dest = std::min(xp+offset, static_cast<ssize_t>(size-1)); | ||||
|       } else { | ||||
|         d = x; | ||||
|         for(; offset < 0 && d != seq_.begin(); ++offset, --d); | ||||
|         dest = std::distance(seq_.begin(), d); | ||||
|         dest = std::max(xp+offset, static_cast<ssize_t>(0)); | ||||
|       } | ||||
|     } else { | ||||
|       ssize_t size = index_.size(); | ||||
|       if(how == A2_POS_END) { | ||||
|         dest = std::min(size-1, size-1+offset); | ||||
|         dest = std::min(size-1+offset, size-1); | ||||
|       } else if(how == A2_POS_SET) { | ||||
|         dest = std::min(size-1, offset); | ||||
|         dest = std::min(offset, size-1); | ||||
|       } else { | ||||
|         return -1; | ||||
|       } | ||||
|       dest = std::max(dest, static_cast<ssize_t>(0)); | ||||
|       d = seq_.begin(); | ||||
|       for(ssize_t i = 0; i < dest; ++i, ++d) { | ||||
|         if(d == x) { | ||||
|           ++d; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     seq_.splice(d, seq_, x); | ||||
|     typename SeqType::iterator d = seq_.begin(); | ||||
|     std::advance(d, dest); | ||||
|     if(xp < dest) { | ||||
|       std::rotate(x, x+1, d+1); | ||||
|     } else { | ||||
|       std::rotate(d, x, x+1); | ||||
|     } | ||||
|     return dest; | ||||
|   } | ||||
| 
 | ||||
|  | @ -218,30 +246,6 @@ public: | |||
|     typename IndexType::const_iterator idxent = index_.find(key); | ||||
|     if(idxent == index_.end()) { | ||||
|       return ValuePtrType(); | ||||
|     } else { | ||||
|       return (*(*idxent).second).second; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Returns the iterator to the element associated by |key|. If it is
 | ||||
|   // not found, end() is returned. Complexity: O(logN)
 | ||||
|   typename SeqType::iterator find(KeyType key) | ||||
|   { | ||||
|     typename IndexType::iterator idxent = index_.find(key); | ||||
|     if(idxent == index_.end()) { | ||||
|       return seq_.end(); | ||||
|     } else { | ||||
|       return (*idxent).second; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Returns the iterator to the element associated by |key|. If it is
 | ||||
|   // not found, end() is returned. Complexity: O(logN)
 | ||||
|   typename SeqType::const_iterator find(KeyType key) const | ||||
|   { | ||||
|     typename IndexType::const_iterator idxent = index_.find(key); | ||||
|     if(idxent == index_.end()) { | ||||
|       return seq_.end(); | ||||
|     } else { | ||||
|       return (*idxent).second; | ||||
|     } | ||||
|  |  | |||
|  | @ -151,6 +151,15 @@ void RequestGroupMan::addReservedGroup | |||
|   reservedGroups_.push_back(group->getGID(), group); | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| struct RequestGroupKeyFunc { | ||||
|   a2_gid_t operator()(const SharedHandle<RequestGroup>& rg) const | ||||
|   { | ||||
|     return rg->getGID(); | ||||
|   } | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| void RequestGroupMan::insertReservedGroup | ||||
| (size_t pos, const std::vector<SharedHandle<RequestGroup> >& groups) | ||||
| { | ||||
|  | @ -158,10 +167,8 @@ void RequestGroupMan::insertReservedGroup | |||
|   pos = std::min(reservedGroups_.size(), pos); | ||||
|   RequestGroupList::SeqType::iterator dest =  reservedGroups_.begin(); | ||||
|   std::advance(dest, pos); | ||||
|   for(std::vector<SharedHandle<RequestGroup> >::const_iterator i = | ||||
|         groups.begin(), eoi = groups.end(); i != eoi; ++i, ++dest) { | ||||
|     dest = reservedGroups_.insert(dest, (*i)->getGID(), *i); | ||||
|   } | ||||
|   reservedGroups_.insert(dest, RequestGroupKeyFunc(), | ||||
|                          groups.begin(), groups.end()); | ||||
| } | ||||
| 
 | ||||
| void RequestGroupMan::insertReservedGroup | ||||
|  | @ -482,42 +489,36 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e) | |||
|   } | ||||
|   int count = 0; | ||||
|   int num = maxSimultaneousDownloads_-requestGroups_.size(); | ||||
|   // In the following loop, the download which is not ready to start
 | ||||
|   // is kept in reservedGroups_. We use iterator to see if we
 | ||||
|   // evaluated them all. So don't use empty() for this. Compare to
 | ||||
|   // reservedGroups_.end() instead.
 | ||||
|   RequestGroupList::SeqType::iterator resitr = reservedGroups_.begin(); | ||||
|   while(count < num && (uriListParser_ || resitr != reservedGroups_.end())) { | ||||
|     if(uriListParser_ && resitr == reservedGroups_.end()) { | ||||
|   std::vector<SharedHandle<RequestGroup> > pending; | ||||
| 
 | ||||
|   while(count < num && (uriListParser_ || !reservedGroups_.empty())) { | ||||
|     if(uriListParser_ && reservedGroups_.empty()) { | ||||
|       std::vector<SharedHandle<RequestGroup> > groups; | ||||
|       // May throw exception
 | ||||
|       bool ok = createRequestGroupFromUriListParser(groups, option_, | ||||
|                                                     uriListParser_.get()); | ||||
|       if(ok) { | ||||
|         appendReservedGroup(reservedGroups_, groups.begin(), groups.end()); | ||||
|         resitr = reservedGroups_.end(); | ||||
|         std::advance(resitr, -static_cast<ssize_t>(groups.size())); | ||||
|       } else { | ||||
|         uriListParser_.reset(); | ||||
|         if(resitr == reservedGroups_.end()) { | ||||
|         if(reservedGroups_.empty()) { | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     SharedHandle<RequestGroup> groupToAdd = (*resitr).second; | ||||
|     std::vector<Command*> commands; | ||||
|     SharedHandle<RequestGroup> groupToAdd = (*reservedGroups_.begin()).second; | ||||
|     reservedGroups_.pop_front(); | ||||
|     if((rpc_ && groupToAdd->isPauseRequested()) || | ||||
|        !groupToAdd->isDependencyResolved()) { | ||||
|       ++resitr; | ||||
|       pending.push_back(groupToAdd); | ||||
|       continue; | ||||
|     } | ||||
|     ++resitr; | ||||
|     reservedGroups_.erase(groupToAdd->getGID()); | ||||
|     // Drop pieceStorage here because paused download holds its
 | ||||
|     // reference.
 | ||||
|     groupToAdd->dropPieceStorage(); | ||||
|     configureRequestGroup(groupToAdd); | ||||
|     groupToAdd->setRequestGroupMan(this); | ||||
|     std::vector<Command*> commands; | ||||
|     try { | ||||
|       createInitialCommand(groupToAdd, commands, e); | ||||
|       ++count; | ||||
|  | @ -543,6 +544,10 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e) | |||
|                                PREF_ON_DOWNLOAD_START); | ||||
|     notifyDownloadEvent(Notifier::ON_DOWNLOAD_START, groupToAdd); | ||||
|   } | ||||
|   if(!pending.empty()) { | ||||
|     reservedGroups_.insert(reservedGroups_.begin(), RequestGroupKeyFunc(), | ||||
|                            pending.begin(), pending.end()); | ||||
|   } | ||||
|   if(count > 0) { | ||||
|     e->setNoWait(true); | ||||
|     e->setRefreshInterval(0); | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ class IndexedListTest:public CppUnit::TestFixture { | |||
|   CPPUNIT_TEST(testMove); | ||||
|   CPPUNIT_TEST(testGet); | ||||
|   CPPUNIT_TEST(testInsert); | ||||
|   CPPUNIT_TEST(testInsert_keyFunc); | ||||
|   CPPUNIT_TEST_SUITE_END(); | ||||
| public: | ||||
|   void setUp() | ||||
|  | @ -34,6 +35,7 @@ public: | |||
|   void testMove(); | ||||
|   void testGet(); | ||||
|   void testInsert(); | ||||
|   void testInsert_keyFunc(); | ||||
| }; | ||||
| 
 | ||||
| CPPUNIT_TEST_SUITE_REGISTRATION( IndexedListTest ); | ||||
|  | @ -203,9 +205,57 @@ void IndexedListTest::testGet() | |||
|   list.push_back(1, &b); | ||||
|   CPPUNIT_ASSERT_EQUAL((int*)0, list.get(1000)); | ||||
|   CPPUNIT_ASSERT_EQUAL(&a, list.get(123)); | ||||
| } | ||||
| 
 | ||||
|   CPPUNIT_ASSERT(list.begin() == list.find(123)); | ||||
|   CPPUNIT_ASSERT(list.end() == list.find(124)); | ||||
| namespace { | ||||
| struct KeyFunc { | ||||
|   int n; | ||||
|   KeyFunc(int n):n(n) {} | ||||
|   int operator()(const SharedHandle<std::string>& x) | ||||
|   { | ||||
|     return n++; | ||||
|   } | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| void IndexedListTest::testInsert_keyFunc() | ||||
| { | ||||
|   SharedHandle<std::string> s[] = { | ||||
|     SharedHandle<std::string>(new std::string("a")), | ||||
|     SharedHandle<std::string>(new std::string("b")), | ||||
|     SharedHandle<std::string>(new std::string("c")), | ||||
|     SharedHandle<std::string>(new std::string("d")) | ||||
|   }; | ||||
|   size_t slen = sizeof(s)/sizeof(s[0]); | ||||
|   IndexedList<int, SharedHandle<std::string> > list; | ||||
|   list.insert(list.begin(), KeyFunc(0), vbegin(s), vend(s)); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)slen, list.size()); | ||||
|   for(size_t i = 0; i < slen; ++i) { | ||||
|     CPPUNIT_ASSERT_EQUAL(*s[i], *list.get(i)); | ||||
|   } | ||||
|   list.insert(list.begin()+2, KeyFunc(slen), vbegin(s), vend(s)); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)slen*2, list.size()); | ||||
|   for(size_t i = slen; i < slen*2; ++i) { | ||||
|     CPPUNIT_ASSERT_EQUAL(*s[i - slen], *list.get(i)); | ||||
|   } | ||||
|   IndexedList<int, SharedHandle<std::string> >::SeqType::iterator itr; | ||||
|   itr = list.begin(); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("a"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("b"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("a"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("b"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("c"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("d"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("c"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("d"), *(*itr++).second); | ||||
| 
 | ||||
|   list.insert(list.begin(), KeyFunc(2*slen-1), vbegin(s), vend(s)); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)slen*3-1, list.size()); | ||||
|   itr = list.begin(); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("b"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("c"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("d"), *(*itr++).second); | ||||
|   CPPUNIT_ASSERT_EQUAL(std::string("a"), *(*itr++).second); | ||||
| } | ||||
| 
 | ||||
| void IndexedListTest::testInsert() | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
| #include "util.h" | ||||
| #include "DownloadEngine.h" | ||||
| #include "SelectEventPoll.h" | ||||
| #include "UriListParser.h" | ||||
| 
 | ||||
| namespace aria2 { | ||||
| 
 | ||||
|  | @ -31,6 +32,8 @@ class RequestGroupManTest : public CppUnit::TestFixture { | |||
|   CPPUNIT_TEST(testSaveServerStat); | ||||
|   CPPUNIT_TEST(testChangeReservedGroupPosition); | ||||
|   CPPUNIT_TEST(testFillRequestGroupFromReserver); | ||||
|   CPPUNIT_TEST(testFillRequestGroupFromReserver_uriParser); | ||||
|   CPPUNIT_TEST(testInsertReservedGroup); | ||||
|   CPPUNIT_TEST_SUITE_END(); | ||||
| private: | ||||
|   SharedHandle<DownloadEngine> e_; | ||||
|  | @ -59,6 +62,8 @@ public: | |||
|   void testSaveServerStat(); | ||||
|   void testChangeReservedGroupPosition(); | ||||
|   void testFillRequestGroupFromReserver(); | ||||
|   void testFillRequestGroupFromReserver_uriParser(); | ||||
|   void testInsertReservedGroup(); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -229,4 +234,59 @@ void RequestGroupManTest::testFillRequestGroupFromReserver() | |||
|   CPPUNIT_ASSERT_EQUAL((size_t)2, rgman_->getReservedGroups().size()); | ||||
| } | ||||
| 
 | ||||
| void RequestGroupManTest::testFillRequestGroupFromReserver_uriParser() | ||||
| { | ||||
|   SharedHandle<RequestGroup> rgs[] = { | ||||
|     createRequestGroup(0, 0, "mem1", "http://mem1", util::copy(option_)), | ||||
|     createRequestGroup(0, 0, "mem2", "http://mem2", util::copy(option_)), | ||||
|   }; | ||||
|   rgs[0]->setPauseRequested(true); | ||||
|   for(SharedHandle<RequestGroup>* i = vbegin(rgs); i != vend(rgs); ++i) { | ||||
|     rgman_->addReservedGroup(*i); | ||||
|   } | ||||
| 
 | ||||
|   SharedHandle<UriListParser> flp | ||||
|     (new UriListParser(A2_TEST_DIR"/filelist2.txt")); | ||||
|   rgman_->setUriListParser(flp); | ||||
| 
 | ||||
|   rgman_->fillRequestGroupFromReserver(e_.get()); | ||||
| 
 | ||||
|   RequestGroupList::SeqType::const_iterator itr; | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)1, rgman_->getReservedGroups().size()); | ||||
|   itr = rgman_->getReservedGroups().begin(); | ||||
|   CPPUNIT_ASSERT_EQUAL(rgs[0]->getGID(), (*itr).second->getGID()); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)3, rgman_->getRequestGroups().size()); | ||||
| } | ||||
| 
 | ||||
| void RequestGroupManTest::testInsertReservedGroup() | ||||
| { | ||||
|   SharedHandle<RequestGroup> rgs1[] = { | ||||
|     SharedHandle<RequestGroup>(new RequestGroup(GroupId::create(), | ||||
|                                                 util::copy(option_))), | ||||
|     SharedHandle<RequestGroup>(new RequestGroup(GroupId::create(), | ||||
|                                                 util::copy(option_))) | ||||
|   }; | ||||
|   SharedHandle<RequestGroup> rgs2[] = { | ||||
|     SharedHandle<RequestGroup>(new RequestGroup(GroupId::create(), | ||||
|                                                 util::copy(option_))), | ||||
|     SharedHandle<RequestGroup>(new RequestGroup(GroupId::create(), | ||||
|                                                 util::copy(option_))) | ||||
|   }; | ||||
|   std::vector<SharedHandle<RequestGroup> > groups(vbegin(rgs1), vend(rgs1)); | ||||
|   rgman_->insertReservedGroup(0, groups); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)2, rgman_->getReservedGroups().size()); | ||||
|   RequestGroupList::SeqType::const_iterator itr; | ||||
|   itr = rgman_->getReservedGroups().begin(); | ||||
|   CPPUNIT_ASSERT_EQUAL(rgs1[0]->getGID(), (*itr++).second->getGID()); | ||||
|   CPPUNIT_ASSERT_EQUAL(rgs1[1]->getGID(), (*itr++).second->getGID()); | ||||
| 
 | ||||
|   groups.assign(vbegin(rgs2), vend(rgs2)); | ||||
|   rgman_->insertReservedGroup(1, groups); | ||||
|   CPPUNIT_ASSERT_EQUAL((size_t)4, rgman_->getReservedGroups().size()); | ||||
|   itr = rgman_->getReservedGroups().begin(); | ||||
|   ++itr; | ||||
|   CPPUNIT_ASSERT_EQUAL(rgs2[0]->getGID(), (*itr++).second->getGID()); | ||||
|   CPPUNIT_ASSERT_EQUAL(rgs2[1]->getGID(), (*itr++).second->getGID()); | ||||
| } | ||||
| 
 | ||||
| } // namespace aria2
 | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| http://fromfile1 | ||||
| http://fromfile2 | ||||
		Loading…
	
		Reference in New Issue
	
	 Tatsuhiro Tsujikawa
						Tatsuhiro Tsujikawa