resip学习笔记之句柄Handle

相信很多同学都听说过句柄,也看过一些对句柄的解释。但是句柄到底是什么?他是怎么工作的,可能真正能回答出来的人不多,今天我们借助resip协议栈对句柄的实现来详细聊聊句柄。

首先作为句柄它最重要的功能就是能唯一指定一个内存对象,注意这里是“指定”,不是c++指针的“指向”。那句柄要怎么才能做到唯一指定一个内存对象呢?

想象一下,如果一个类A中有一个成员变量id(通过特定机制保证类A的多个变量拥有不等的id), 它用来唯一标识一个类A的对象。类似于学生的学号,可以唯一指定一个学生。然后我们在创建一个对象的管理类A_Manager, 在A_Manager中包含一个map成员变量。这个map成员变量的key是类A对象的id,value是类A对象的指针。那么只要知道类A对象的id我们就能够从管理类A_Manager的map中找到该对象。

如果我们在申明一个类handle,这个handle类需要用A_Manager类对象的引用和A对象的id来构造。那么我们是不是就可以使用handle类的对象去找到那个指定id的A类的对象了?

没错上面说的handle就是一个句柄,通过它我们可以找到指定id的类A的对象。

通过上面的介绍我们大概能总结如下:

1、句柄不一定是指针,只要通过一个类的对象能够找到指定的其他类对象,我们就可以称这个类为其他类的句柄;
2、句柄可以有无限多个,并且删除句柄,不会影响到句柄指定的对象;
3、能够被句柄指定的对象一定得具备一些属性,并且能够通过这些属性唯一确定对象。如上面介绍的类A就有一个id属性,通过id我们可以找到那个唯一的对象。
4、通过一种机制保证类的多个变量的属性拥有不等的值。

在resip协议栈中就是通过上面的思想来实现句柄类的。

class HandleManager;

class Handled
{
   public:
      typedef unsigned long Id; // make this a UInt64, fix the hash
      enum { npos = 0 };

      Handled(HandleManager& ham);
      virtual ~Handled();
      
      virtual EncodeStream& dump(EncodeStream& strm) const=0;
      
   protected:
      HandleManager& mHam;
      Handled::Id mId;
};

template <class T>
class Handle
{
   public:
      Handle(HandleManager& ham, Handled::Id id) : mHam(&ham), mId(id)
      {
      }

      Handle() : mHam(0), mId(0)
      {
      }

      bool isValid() const
      {
         if (!mHam)
         {
            return false;
         }
         else
         {
            return mHam->isValidHandle(mId);
         }
      }
      
      // throws if not found
      T* get()
      {
         if (!mHam)
         {
            //assert(0);
            throw HandleException("Reference to unitialized handle.", __FILE__, __LINE__);
         }
         return static_cast<T*>(mHam->getHandled(mId));
      }

      const T* get() const
      {
         if (!mHam)
         {
            //assert(0);
            throw HandleException("Reference to unitialized handle.", __FILE__, __LINE__);
         }
         return static_cast<T*>(mHam->getHandled(mId));
      }
      
      T* operator->()
      {
         return get();
      }

      const T* operator->() const
      {
         return get();
      }

      T& operator*()
      {
         return *get();
      }

      const T& operator*() const
      {
         return *get();
      }
      

      Handled::Id getId() const
      {
         return mId;
      }

      static Handle<T> NotValid()
      {
         static Handle<T> notValid;
         return notValid;
      }
      
      bool operator==(const Handle<T>& other)
      {
         return (mHam == other.mHam) && (mId == other.mId);
      }
      
      // !nash! to be able to use Handle in Set or Map container
      bool operator<(const Handle<T>& other) const
      {
         assert(mHam);
         assert(other.mHam);
         return mId < other.mId;
      }

   private:
      HandleManager* mHam;

   protected:
      Handled::Id mId;

      friend class Handled;
};

class HandleManager
{
   public:
      HandleManager();
      virtual ~HandleManager();

      bool isValidHandle(Handled::Id) const;
      Handled* getHandled(Handled::Id) const;

      virtual void shutdownWhenEmpty();
      //subclasses(for now DUM) overload this method to handle shutdown
   protected:
      virtual void onAllHandlesDestroyed()=0;      
      virtual void dumpHandles() const;
      
      //private:
      friend class Handled;
      
      Handled::Id create(Handled* handled);
      void remove(Handled::Id id);

      typedef HashMap<Handled::Id, Handled*> HandleMap;
      HandleMap mHandleMap;
      bool mShuttingDown;      
      Handled::Id mLastId;

   public:
      /// Returns the number of handles in use.
      HandleMap::size_type handleCount(void) const 
      { 
          return mHandleMap.size(); 
      }

};

通过上面代码的分析,我们可以看出handle对象是handled对象的句柄,handled有成员变量mId来区分不同的handled。HandleManager类提供一个map用来储存handled对象。handled对象都是通过HandleManger类来创建,从而保证每个handled类的对象拥有不等的mId。最后handle对象需要通过HandleManager的引用与handled对象的id来创建,以确保handle类对象可以准确找到handled类的对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heibao111728

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值