Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // A combined list/hash set for read or write-blocked entities.
      6 
      7 #ifndef NET_QUIC_BLOCKED_LIST_H_
      8 #define NET_QUIC_BLOCKED_LIST_H_
      9 
     10 #include <list>
     11 
     12 #include "base/containers/hash_tables.h"
     13 #include "base/logging.h"
     14 
     15 namespace net {
     16 
     17 template <typename Object>
     18 class BlockedList {
     19  public:
     20   // Called to add an object to the blocked list. This indicates
     21   // the object should be notified when it can use the socket again.
     22   //
     23   // If this object is already on the list, it will not be added again.
     24   void AddBlockedObject(Object object) {
     25     // Only add the object to the list if we successfully add it to the set.
     26     if (object_set_.insert(object).second) {
     27       object_list_.push_back(object);
     28     }
     29   }
     30 
     31   // Called to remove an object from a blocked list.  This should be
     32   // called in the event the object is being deleted before the list is.
     33   void RemoveBlockedObject(Object object) {
     34     // Remove the object from the set.  We'll check the set before calling
     35     // OnCanWrite on a object from the list.
     36     //
     37     // There is potentially ordering unfairness should a session be removed and
     38     // then readded (as it keeps its position in the list) but it's not worth
     39     // the overhead to walk the list and remove it.
     40     object_set_.erase(object);
     41   }
     42 
     43   // Called when the socket is usable and some objects can access it.  Returns
     44   // the first object and removes it from the list.
     45   Object GetNextBlockedObject() {
     46     DCHECK(!IsEmpty());
     47 
     48     // Walk the list to find the first object which was not removed from the
     49     // set.
     50     while (!object_list_.empty()) {
     51       Object object = *object_list_.begin();
     52       object_list_.pop_front();
     53       int removed = object_set_.erase(object);
     54       if (removed > 0) {
     55         return object;
     56       }
     57     }
     58 
     59     // This is a bit of a hack: It's illegal to call GetNextBlockedObject() if
     60     // the list is empty (see DCHECK above) but we must return something.  This
     61     // compiles for ints (returns 0) and pointers in the case that someone has a
     62     // bug in their call site.
     63     return 0;
     64   };
     65 
     66   // Returns the number of objects in the blocked list.
     67   int NumObjects() {
     68     return object_set_.size();
     69   };
     70 
     71   // Returns true if there are no objects in the list, false otherwise.
     72   bool IsEmpty() {
     73     return object_set_.empty();
     74   };
     75 
     76  private:
     77   // A set tracking the objects. This is the authoritative container for
     78   // determining if an object is blocked.   Objects in the list will always
     79   // be in the set.
     80   base::hash_set<Object> object_set_;
     81   // A list tracking the order in which objects were added to the list.
     82   // Objects are added to the back and pulled off the front, but only get
     83   // resumption calls if they're still in the set.
     84   // It's possible to be in the list twice, but only the first entry will get an
     85   // OnCanWrite call.
     86   std::list<Object> object_list_;
     87 };
     88 
     89 }  // namespace net
     90 
     91 #endif  // NET_QUIC_BLOCKED_LIST_H_
     92