用STL设计消息队列、优先级消息队列、资源分配管理器

          STL库老早已经成为C++的一部分,在使用C++开发项目的过程中,很多人还在犹豫要不要使用STL库,觉得STL库很难,其实不然。我工作的项目中现在大量使用STL库,STL使用调试简单,高效,可以减少很多重复的代码。

       本文的主要目的是使用STL的queue 和 priority queue来阐述下项目中经常使用的消息队列以及资源分配模式。本文的例子主要如下:

  • 消息队列
  • 带优先级的消息队列
  • 资源分配管理器

    STL容器

    我们将使用下面的容器来实现本文的例子:

    queue队列容器支持添加一个元素,并且从中删除一个元素,也可以变成一个双端队列
    priority_queue向队尾添加一个新元素,如果该优先权大于前面的元素,将放在前面,元素的优先权由用户指定的函数传入。
    stack有后进先出的特点,可以选择选择vetctor或其他线性列表放入容器。

        

     

    1.消息队列

        消息队列是项目中经常需要使用的模式,下面使用STL的queue容器实现:

      

    #include <queue>     // STL header file for queue
    #include <list>
    using namespace std; // Specify that we are using the std namespace
    
    class Message;
    
    class Message_Queue
    {
       typedef queue<Message *, list<Message *> > MsgQueType;
    
       MsgQueType m_msgQueue;
          
    public:
       void Add(Message *pMsg)
       {
          // Insert the element at the end of the queue
          m_msgQueue.push(pMsg);
       }
    
       Message *Remove()
       {
          Message *pMsg = NULL;
          
          // Check if the message queue is not empty
          if (!m_msgQueue.empty())
          {
             // Queue is not empty so get a pointer to the
             // first message in the queue
             pMsg = m_msgQueue.front();
             
             // Now remove the pointer from the message queue
             m_msgQueue.pop();
          }
          return pMsg;
       }
       
       int GetLength() const
       {
          return m_msgQueue.size();
       }   
    };
    


     

    2.优先级消息队列

          上面的消息队列类只支持在队列的尾部添加一个元素,在许多的应用程序中,需要根据消息的优先级将消息添加到队列中,当一个高优先级的消息来了,需要将该消息添加到所有比它优先级低的消息前面,下面将使用priority_queue来实现优先级消息队列类。

        

    函数对象(Functors)

    优先级消息队列的实现和上面消息队列实现相似,唯一不同的是这里使用了函数对象来决定优先权CompareMessages,该结构重载了操作符"(,)",该机制可以实现可以将一个函数作为一个参数,和函数指针对比有如下好处:

           1.函数对象效率更高,可以是内联函数,函数指针总是有函数调用的开销。

            2.函数对象提供了一个安全的实现方法,这样的实现不会出现空指针访问。

    #include <queue>      // STL header file for queue
    #include <list>
    using namespace std;  // Specify that we are using the std namespace
    
    class Message;
    
    class Priority_Message_Queue
    {
        struct Entry
        {
            Message *pMsg;
            int priority;
        };
       
        struct Compare_Messages
        {
            bool operator () (const Entry& left , const Entry& right)
            {
                return (left.priority < right.priority);
            }
        };  
     
       typedef priority_queue<Entry, vector<Entry>, Compare_Messages  > 
                 Message_Queue_Type;
    
       Message_Queue_Type m_message_Queue;
          
    public:
    
       void Add(Message *pMsg, int priority)
       {
          // Make an entry
          Entry entry;
          entry.pMsg = pMsg;
          entry.priority = priority;
          // Insert the element according to its priority
          m_message_Queue.push(entry);
       }
       
       Message *Remove()
       {
          Message *pMsg = NULL;
          
          // Check if the message queue is not empty
          if (!m_message_Queue.empty())
          {
             // Queue is not empty so get a pointer to the
             // first message in the queue
             pMsg = (m_message_Queue.top()).pMsg;
             
             // Now remove the pointer from the message queue
             m_message_Queue.pop();
          }
          return (pMsg);
       }
       
       size_t Get_Length() const
       {
          return m_message_Queue.size();
       }   
    };
    


         

    3.资源分配管理器

    这里使用queue 和 stack两个容器来实现一个简单的资源分配器,用该容器来保存空闲的资源列表。

    该资源分配器支持如下接口:

           1.Construction:当这个资源分配器构造出来,需要给定空闲的资源列表,这些资源将添加到这个空闲资源列表。

           2.Allocate:当需要一个资源时,需要从空闲资源队列中移除一个资源,并返回给调用者。

          3.Free:当一个资源被释放,需要将该资源加入空闲资源列表。

          4.GetFreeResourceCount:返回当前可用的资源数目。

    Coldest First(使用queue)

    #include <queue>      // STL header file for queue
    #include <list>
    using namespace std;  // Specify that we are using the std namespace
    
    class Resource;
    
    class Cold_Resource_Allocator
    {
       typedef queue<Resource *, list<Resource *> > Free_Queue_Type;
    
       Free_Queue_Type m_free_Resource_Queue;
          
    public:
       
       Cold_Resource_Allocator(int resource_Count, 
                                 Resource *resource_Array[])
       {
          for (int i = 0; i < resource_Count; i++)
          {
             m_free_Resource_Queue.push(resource_Array[i]);
          }
       }
     
       Resource * Allocate()
       {
          Resource *pResource = NULL;
          
          // Check if any free resources are available.
          if (!m_free_Resource_Queue.empty())
          {
             // Queue is not empty so get a pointer to the
             // first resource in the queue
             pResource = m_free_Resource_Queue.front();
             
             // Now remove the pointer from the free resource queue
             m_free_Resource_Queue.pop();
          }
          return pResource;
       }
       
       void Free(Resource *pResource)
       {
          // Insert the resource at the end of the free queue
          m_free_Resource_Queue.push(pResource);
       }
          
       size_t GetFreeResourceCount()
       {
          return m_free_Resource_Queue.size();
       }   
    };
    


     

    Hottest First(使用statck)

    #include <stack>     // STL header file for stack
    #include <deque>
    using namespace std; // Specify that we are using the std namespace
    
    class Resource;
    
    class Hot_Resource_Allocator
    {
    
       typedef stack <Resource *, deque <Resource *> > 
                 Free_Stack_Type;
    
       Free_Stack_Type m_free_Resource_Stack;
          
    public:
       
       Hot_Resource_Allocator(int resource_Count, 
                                Resource *resource_Array[])
       {
          for (int i = 0; i < resource_Count; i++)
          {
             m_free_Resource_Stack.push(resource_Array[i]);
          }
       }
    
       Resource * Allocate()
       {
          Resource *pResource = NULL;
          
          // Check if any free resources are available.
          if (!m_free_Resource_Stack.empty())
          {
             // Queue is not empty so get a pointer to the
             // first resource in the stack
             pResource = m_free_Resource_Stack.top();
             
             // Now remove the pointer from the free resource stack
             m_free_Resource_Stack.pop();
          }
          return pResource;
       }
       
       void Free(Resource *pResource)
       {
          // Insert the resource at the end of the free stack
          m_free_Resource_Stack.push(pResource);
       }
          
       size_t GetFreeResourceCount()
       {
          return m_free_Resource_Stack.size();
       }   
    };
    


     

     

     

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值