1  /*
   2   * \brief  Object pool - map capabilities to objects
   3   * \author Norman Feske
   4   * \author Alexander Boettcher
   5   * \author Stafen Kalkowski
   6   * \date   2006-06-26
   7   */

   8  
   9  /*
  10   * Copyright (C) 2006-2013 Genode Labs GmbH
  11   *
  12   * This file is part of the Genode OS framework, which is distributed
  13   * under the terms of the GNU General Public License version 2.
  14   */

  15  
  16  #ifndef _INCLUDE__BASE__OBJECT_POOL_H_
  17  #define _INCLUDE__BASE__OBJECT_POOL_H_
  18  
  19  #include <util/avl_tree.h>
  20  #include <util/noncopyable.h>
  21  #include <base/capability.h>
  22  #include <base/weak_ptr.h>
  23  
  24  namespace Genode { template <typename> class Object_pool; }
  25  
  26  
  27  /**
  28   * Map capabilities to local objects
  29   *
  30   * \param OBJ_TYPE  object type (must be inherited from Object_pool::Entry)
  31   *
  32   * The local names of a capabilities are used to differentiate multiple server
  33   * objects managed by one and the same object pool.
  34   */

  35  template <typename OBJ_TYPE>
  36  class Genode::Object_pool
  37  {
  38     public:
  39  
  40        class Entry : public Avl_node<Entry>
  41        {
  42           private:
  43  
  44              friend class Object_pool;
  45              friend class Avl_tree<Entry>;
  46  
  47              struct Entry_lock : Weak_object<Entry_lock>, Noncopyable
  48              {
  49                 Entry &obj;
  50  
  51                 Entry_lock(Entry &e) : obj(e) { }
  52                 ~Entry_lock() {
  53                    Weak_object<Entry_lock>::lock_for_destruction(); }

  54              }
;

  55  
  56              Untyped_capability _cap;

  57              Entry_lock         _lock { *this };
  58  
  59              inline unsigned long _obj_id() { return _cap.local_name(); }
  60  
  61           public:
  62  
  63              Entry() { }
  64              Entry(Untyped_capability cap) : _cap(cap) { }
  65  
  66              virtual ~Entry() { }
  67  
  68              /**
  69               * Avl_node interface
  70               */

  71              bool higher(Entry *e) { return e->_obj_id() > _obj_id(); }

  72              void recompute() { }  /* for gcc-3.4 compatibility */
  73  
  74              /**
  75               * Support for object pool
  76               */

  77              Entry *find_by_obj_id(unsigned long obj_id)
  78              {
  79                 if (obj_id == _obj_id()) return this;
  80  
  81                 Entry *obj = this->child(obj_id > _obj_id());
  82  
  83                 return obj ? obj->find_by_obj_id(obj_id) : 0;

  84              }

  85  
  86              /**
  87               * Assign capability to object pool entry
  88               */

  89              void cap(Untyped_capability c) { _cap = c; }

  90  
  91              Untyped_capability const cap() const { return _cap; }

  92        }
;

  93  
  94     private:
  95  
  96        Avl_tree<Entry> _tree;
  97        Lock            _lock;

  98  
  99     protected:
 100  
 101        bool empty()
 102        {
 103           Lock::Guard lock_guard(_lock);
 104           return _tree.first() == nullptr;
 105        }

 106  
 107     public:
 108  
 109        void insert(OBJ_TYPE *obj)
 110        {
 111           Lock::Guard lock_guard(_lock);
 112           _tree.insert(obj);
 113        }

 114  
 115        void remove(OBJ_TYPE *obj)
 116        {
 117           Lock::Guard lock_guard(_lock);
 118           _tree.remove(obj);
 119        }

 120  
 121        template <typename FUNC>
 122        auto apply(unsigned long capid, FUNC func)
 123        -> typename Trait::Functor<decltype(&FUNC::operator())>::Return_type
 124        {
 125           using Functor        = Trait::Functor<decltype(&FUNC::operator())>;
 126           using Object_pointer = typename Functor::template Argument<0>::Type;
 127           using Weak_ptr       = Weak_ptr<typename Entry::Entry_lock>;
 128           using Locked_ptr     = Locked_ptr<typename Entry::Entry_lock>;
 129  
 130           Weak_ptr ptr;
 131  
 132           {
 133              Lock::Guard lock_guard(_lock);
 134  
 135              Entry * entry = _tree.first() ?
 136                 _tree.first()->find_by_obj_id(capid) : nullptr;

 137  
 138              if (entry) ptr = entry->_lock.weak_ptr();

 139           }

 140  
 141           {
 142              Locked_ptr lock_ptr(ptr);
 143              Object_pointer op = lock_ptr.is_valid()
 144                 ? dynamic_cast<Object_pointer>(&lock_ptr->obj) : nullptr;

 145              return func(op);

 146           }

 147        }

 148  
 149        template <typename FUNC>
 150        auto apply(Untyped_capability cap, FUNC func)
 151        -> typename Trait::Functor<decltype(&FUNC::operator())>::Return_type
 152        {
 153           return apply(cap.local_name(), func);
 154        }

 155  
 156        template <typename FUNC>
 157        void remove_all(FUNC func)
 158        {
 159           using Weak_ptr   = Weak_ptr<typename Entry::Entry_lock>;
 160           using Locked_ptr = Locked_ptr<typename Entry::Entry_lock>;
 161  
 162           for (;;) {
 163              OBJ_TYPE * obj;
 164  
 165              {
 166                 Lock::Guard lock_guard(_lock);
 167  
 168                 if (!((obj = (OBJ_TYPE*) _tree.first()))) return;
 169  
 170                 Weak_ptr ptr = obj->_lock.weak_ptr();
 171                 {
 172                    Locked_ptr lock_ptr(ptr);
 173                    if (!lock_ptr.is_valid()) return;
 174  
 175                    _tree.remove(obj);

 176                 }

 177              }

 178  
 179              func(obj);

 180           }

 181        }

 182  }
;

 183  
 184  #endif /* _INCLUDE__BASE__OBJECT_POOL_H_ */