31.4.2. acestl::message_queue_sequence::iterator
清单31.8展示了acestl::message_queue_sequence::iterator类的定义。基于之前的经验,这里的很多内容我们都不感到陌生。(至此我希望你对这些技术已经有所熟悉,既能认识到它们之间的相似之处,在不同的应用场景中,也可以指出改变的地方。当然,我也希望你自己编写STL扩展时同样从中受益。)迭代器的类别是输入迭代器(1.3.1节)。元素引用类别(3.3节)是瞬时引用或更高的精化;不过事实上就是固定引用,但是需要注意,不论在定义底层消息队列的线程之内或之外,都不能有别的代码改变队列或其中的块(否则会使引用失效)。迭代器的实现基于shared_handle,很快会讨论。因为我们在别的序列(19.3节和20.5节)中已经见识了使用shared_handle的规范方式,所以在下面的构造方法中不再赘述。
清单 31.8. message_queue_sequence::iterator 的定义
Code View: Scroll / Show All class message_queue_sequence<. . .>::iterator : public std::iterator<std::input_iterator_tag , char, ptrdiff_t , char*, char& > { private: // Member Types friend class message_queue_sequence<ACE_SYNCH_USE>; typedef ACE_Message_Queue_Iterator<ACE_SYNCH_USE> mq_iterator_type; struct shared_handle; public: typedef iterator class_type; typedef char value_type; private: // Construction iterator(sequence_type& mq) : m_handle(new shared_handle(mq)) {} public: iterator() : m_handle(NULL) {} iterator(class_type const& rhs); // Share handle via AddRef() (+) ~iterator() throw(); // Call Release() (-) if non-NULL class_type& operator =(class_type const& rhs); // (+) new; (-) old public: // Input Iteration class_type& operator ++() { ACESTL_ASSERT(NULL != m_handle); if(!m_handle->advance()) { m_handle->Release(); m_handle = NULL; } return *this; } class_type operator ++(int); // Canonical implementation value_type& operator *() { ACESTL_ASSERT(NULL != m_handle); return m_handle->current(); } value_type operator *() const { ACESTL_ASSERT(NULL != m_handle); return m_handle->current(); } bool equal(class_type const& rhs) const { return lhs.is_end_point() == rhs.is_end_point(); } private: // Implementation bool is_end_point() const { return NULL == m_handle || m_handle->is_end_point(); } private: // Member Variables shared_handle* m_handle; }; |
迭代方法都实现在shared_handle方法的基础上。有两种方式表示终点状态:m_handle是空指针,或者其本身就代表终点 。前自增运算符调用shared_handle::advance()使迭代过程前进,但如果后者返回值为false,就释放m_handle。解引用运算符的重载实现基于shared_handle的current()方法的重载版本。注意其中的变动性(非const)重载返回变动性引用,而非变动性(const)重载返回char值。
主要的动作都放在shared_handle之中,其实现见清单31.9。现在我施展另一个诡计,不去解释算法的细节,而是留给你作为练习。但为了公平起见,我还是给个提示吧,shared_handle跳过了空白的ACE_Message_Block实例,这就是为什么终点条件的判断逻辑如此简单。
清单 31.9. shared_handle 的定义
Code View: Scroll / Show All struct message_queue_sequence<. . .>::iterator::shared_handle { public: // Member Types typedef shared_handle class_type; public: // Member Variables mq_iterator_type m_mqi; ACE_Message_Block* m_entry; size_t m_entryLength; size_t m_entryIndex; private: sint32_t m_refCount; public: // Construction explicit shared_handle(sequence_type& mq) : m_mqi(mq) , m_entry(NULL) , m_entryLength(0) , m_entryIndex(0) , m_refCount(1) { if(m_mqi.next(m_entry)) { for(;;) { if(0 != (m_entryLength = m_entry->length())) { break; } else if(NULL == (m_entry = nextEntry())) { break; } } } } private: ~shared_handle() throw() { ACESTL_MESSAGE_ASSERT("Shared handle destroyed with outstanding references!", 0 == m_refCount); } public: sint32_t AddRef(); // Canonical implementation sint32_t Release(); // Canonical implementation public: // Iteration Methods bool is_end_point() const { return m_entryIndex == m_entryLength; } char& current() { ACESTL_ASSERT(NULL != m_entry); ACESTL_ASSERT(m_entryIndex != m_entryLength); return m_entryIndex[m_entry->rd_ptr()]; } char current() const { ACESTL_ASSERT(NULL != m_entry); ACESTL_ASSERT(m_entryIndex != m_entryLength); return m_entryIndex[m_entry->rd_ptr()]; } bool advance() { ACESTL_MESSAGE_ASSERT("Invalid index", m_entryIndex < m_entryLength); if(++m_entryIndex == m_entryLength) { m_entryIndex = 0; for(;;) { if(NULL == (m_entry = nextEntry())) { return false; } else if(0 != (m_entryLength = m_entry->length())) { break; } } } return true; } private: // Implementation ACE_Message_Block* nextEntry() { ACE_Message_Block* entry = NULL; return m_mqi.advance() (m_mqi.next(entry), entry) : NULL; } private: // Not to be implemented shared_handle(class_type const&); class_type& operator =(class_type const&); };
|
【责任编辑:
董书 TEL:(010)68476606】