GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / Unbounded_Queue.cpp
blob02f96eeab5cde3de00ba1f6350d2d410cba541e3
1 #ifndef ACE_UNBOUNDED_QUEUE_CPP
2 #define ACE_UNBOUNDED_QUEUE_CPP
4 #include "ace/Unbounded_Queue.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #if !defined (__ACE_INLINE__)
11 #include "ace/Unbounded_Queue.inl"
12 #endif /* __ACE_INLINE__ */
14 #include "ace/Malloc_Base.h"
15 #include "ace/Log_Category.h"
16 #include "ace/os_include/os_errno.h"
18 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
20 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Unbounded_Queue)
22 template <class T>
23 ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (ACE_Allocator *alloc)
24 : head_ (0),
25 cur_size_ (0),
26 allocator_ (alloc)
28 // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (void)");
30 if (this->allocator_ == 0)
31 this->allocator_ = ACE_Allocator::instance ();
33 ACE_NEW_MALLOC (this->head_,
34 (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
35 ACE_Node<T>);
36 // Make the list circular by pointing it back to itself.
37 this->head_->next_ = this->head_;
40 template <class T>
41 ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue (const ACE_Unbounded_Queue<T> &us)
42 : head_ (0),
43 cur_size_ (0),
44 allocator_ (us.allocator_)
46 // ACE_TRACE ("ACE_Unbounded_Queue<T>::ACE_Unbounded_Queue");
48 if (this->allocator_ == 0)
49 this->allocator_ = ACE_Allocator::instance ();
51 ACE_NEW_MALLOC (this->head_,
52 (ACE_Node<T> *) this->allocator_->malloc (sizeof (ACE_Node<T>)),
53 ACE_Node<T>);
54 this->head_->next_ = this->head_;
55 this->copy_nodes (us);
58 template <class T> void
59 ACE_Unbounded_Queue<T>::operator= (const ACE_Unbounded_Queue<T> &us)
61 // ACE_TRACE ("ACE_Unbounded_Queue<T>::operator=");
63 if (this != &us)
65 this->delete_nodes ();
66 this->copy_nodes (us);
70 template <class T> ACE_Unbounded_Queue_Iterator<T>
71 ACE_Unbounded_Queue<T>::begin (void)
73 // ACE_TRACE ("ACE_Unbounded_Queue<T>::begin");
74 return ACE_Unbounded_Queue_Iterator<T> (*this);
77 template <class T> ACE_Unbounded_Queue_Iterator<T>
78 ACE_Unbounded_Queue<T>::end (void)
80 // ACE_TRACE ("ACE_Unbounded_Queue<T>::end");
81 return ACE_Unbounded_Queue_Iterator<T> (*this, 1);
84 template <class T> void
85 ACE_Unbounded_Queue<T>::dump (void) const
87 #if defined (ACE_HAS_DUMP)
88 // ACE_TRACE ("ACE_Unbounded_Queue<T>::dump");
90 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
91 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_ = %u"), this->head_));
92 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhead_->next_ = %u"), this->head_->next_));
93 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d\n"), this->cur_size_));
95 T *item = 0;
96 #if !defined (ACE_NLOGGING)
97 size_t count = 1;
98 #endif /* ! ACE_NLOGGING */
100 for (ACE_Unbounded_Queue_Iterator<T> iter (*(ACE_Unbounded_Queue<T> *) this);
101 iter.next (item) != 0;
102 iter.advance ())
103 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("count = %d\n"), count++));
105 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
106 #endif /* ACE_HAS_DUMP */
109 template <class T> void
110 ACE_Unbounded_Queue<T>::copy_nodes (const ACE_Unbounded_Queue<T> &us)
112 for (ACE_Node<T> *curr = us.head_->next_;
113 curr != us.head_;
114 curr = curr->next_)
115 if (this->enqueue_tail (curr->item_) == -1)
116 // @@ What's the right thing to do here?
117 this->delete_nodes ();
120 template <class T> void
121 ACE_Unbounded_Queue<T>::delete_nodes (void)
123 for (ACE_Node<T> *curr = this->head_->next_;
124 // Keep looking until we've hit the dummy node.
125 curr != this->head_;
128 ACE_Node<T> *temp = curr;
129 curr = curr->next_;
131 ACE_DES_FREE_TEMPLATE (temp,
132 this->allocator_->free,
133 ACE_Node,
134 <T>);
135 --this->cur_size_;
136 // @@ Doesnt make sense to have this check since
137 // this will always be true.
138 // ACE_ASSERT (this->cur_size_ >= 0);
141 // Reset the list to be a circular list with just a dummy node.
142 this->head_->next_ = this->head_;
145 template <class T>
146 ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void)
148 // ACE_TRACE ("ACE_Unbounded_Queue<T>::~ACE_Unbounded_Queue (void)");
150 this->delete_nodes ();
151 ACE_DES_FREE_TEMPLATE (head_,
152 this->allocator_->free,
153 ACE_Node,
154 <T>);
157 template <class T> int
158 ACE_Unbounded_Queue<T>::enqueue_head (const T &new_item)
160 // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_head");
162 ACE_Node<T> *temp = 0;
164 // Create a new node that points to the original head.
165 ACE_NEW_MALLOC_RETURN (temp,
166 static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
167 ACE_Node<T> (new_item, this->head_->next_),
168 -1);
169 // Link this pointer into the front of the list. Note that the
170 // "real" head of the queue is <head_->next_>, whereas <head_> is
171 // just a pointer to the dummy node.
172 this->head_->next_ = temp;
174 ++this->cur_size_;
175 return 0;
178 template <class T> int
179 ACE_Unbounded_Queue<T>::enqueue_tail (const T &new_item)
181 // ACE_TRACE ("ACE_Unbounded_Queue<T>::enqueue_tail");
183 // Insert <item> into the old dummy node location. Note that this
184 // isn't actually the "head" item in the queue, it's a dummy node at
185 // the "tail" of the queue...
186 this->head_->item_ = new_item;
188 ACE_Node<T> *temp = 0;
190 // Create a new dummy node.
191 ACE_NEW_MALLOC_RETURN (temp,
192 static_cast<ACE_Node<T> *> (this->allocator_->malloc (sizeof (ACE_Node<T>))),
193 ACE_Node<T> (this->head_->next_),
194 -1);
195 // Link this dummy pointer into the list.
196 this->head_->next_ = temp;
198 // Point the head to the new dummy node.
199 this->head_ = temp;
201 ++this->cur_size_;
202 return 0;
205 template <class T> int
206 ACE_Unbounded_Queue<T>::dequeue_head (T &item)
208 // ACE_TRACE ("ACE_Unbounded_Queue<T>::dequeue_head");
210 // Check for empty queue.
211 if (this->is_empty ())
212 return -1;
214 ACE_Node<T> *temp = this->head_->next_;
216 item = temp->item_;
217 this->head_->next_ = temp->next_;
218 ACE_DES_FREE_TEMPLATE (temp,
219 this->allocator_->free,
220 ACE_Node,
221 <T>);
222 --this->cur_size_;
223 return 0;
226 template <class T> void
227 ACE_Unbounded_Queue<T>::reset (void)
229 ACE_TRACE ("reset");
231 this->delete_nodes ();
234 template <class T> int
235 ACE_Unbounded_Queue<T>::get (T *&item, size_t slot) const
237 // ACE_TRACE ("ACE_Unbounded_Queue<T>::get");
239 ACE_Node<T> *curr = this->head_->next_;
241 size_t i;
243 for (i = 0; i < this->cur_size_; i++)
245 if (i == slot)
246 break;
248 curr = curr->next_;
251 if (i < this->cur_size_)
253 item = &curr->item_;
254 return 0;
256 else
257 return -1;
260 template <class T> int
261 ACE_Unbounded_Queue<T>::set (const T &item,
262 size_t slot)
264 // ACE_TRACE ("ACE_Unbounded_Queue<T>::set");
266 ACE_Node<T> *curr = this->head_->next_;
268 size_t i;
270 for (i = 0;
271 i < slot && i < this->cur_size_;
272 ++i)
273 curr = curr->next_;
275 if (i < this->cur_size_)
277 // We're in range, so everything's cool.
278 curr->item_ = item;
279 return 0;
281 else
283 // We need to expand the list.
285 // A common case will be increasing the set size by 1.
286 // Therefore, we'll optimize for this case.
287 if (i == slot)
289 // Try to expand the size of the set by 1.
290 if (this->enqueue_tail (item) == -1)
291 return -1;
292 else
293 return 0;
295 else
297 T const dummy = T ();
299 // We need to expand the list by multiple (dummy) items.
300 for (; i < slot; ++i)
302 // This head points to the existing dummy node, which is
303 // about to be overwritten when we add the new dummy
304 // node.
305 curr = this->head_;
307 // Try to expand the size of the set by 1, but don't
308 // store anything in the dummy node (yet).
309 if (this->enqueue_tail (dummy) == -1)
310 return -1;
313 curr->item_ = item;
314 return 0;
319 // ****************************************************************
321 template <class T> void
322 ACE_Unbounded_Queue_Const_Iterator<T>::dump (void) const
324 #if defined (ACE_HAS_DUMP)
325 // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::dump");
326 #endif /* ACE_HAS_DUMP */
329 template <class T>
330 ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator (const ACE_Unbounded_Queue<T> &q, int end)
331 : current_ (end == 0 ? q.head_->next_ : q.head_ ),
332 queue_ (q)
334 // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::ACE_Unbounded_Queue_Const_Iterator");
337 template <class T> int
338 ACE_Unbounded_Queue_Const_Iterator<T>::advance (void)
340 // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::advance");
341 this->current_ = this->current_->next_;
342 return this->current_ != this->queue_.head_;
345 template <class T> int
346 ACE_Unbounded_Queue_Const_Iterator<T>::first (void)
348 // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::first");
349 this->current_ = this->queue_.head_->next_;
350 return this->current_ != this->queue_.head_;
353 template <class T> int
354 ACE_Unbounded_Queue_Const_Iterator<T>::done (void) const
356 ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::done");
358 return this->current_ == this->queue_.head_;
361 template <class T> int
362 ACE_Unbounded_Queue_Const_Iterator<T>::next (T *&item)
364 // ACE_TRACE ("ACE_Unbounded_Queue_Const_Iterator<T>::next");
365 if (this->current_ == this->queue_.head_)
366 return 0;
367 else
369 item = &this->current_->item_;
370 return 1;
374 // ****************************************************************
376 template <class T> void
377 ACE_Unbounded_Queue_Iterator<T>::dump (void) const
379 #if defined (ACE_HAS_DUMP)
380 // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::dump");
381 #endif /* ACE_HAS_DUMP */
384 template <class T>
385 ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator (ACE_Unbounded_Queue<T> &q, int end)
386 : current_ (end == 0 ? q.head_->next_ : q.head_ ),
387 queue_ (q)
389 // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::ACE_Unbounded_Queue_Iterator");
392 template <class T> int
393 ACE_Unbounded_Queue_Iterator<T>::advance (void)
395 // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::advance");
396 this->current_ = this->current_->next_;
397 return this->current_ != this->queue_.head_;
400 template <class T> int
401 ACE_Unbounded_Queue_Iterator<T>::first (void)
403 // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::first");
404 this->current_ = this->queue_.head_->next_;
405 return this->current_ != this->queue_.head_;
408 template <class T> int
409 ACE_Unbounded_Queue_Iterator<T>::done (void) const
411 ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::done");
413 return this->current_ == this->queue_.head_;
416 template <class T> int
417 ACE_Unbounded_Queue_Iterator<T>::next (T *&item)
419 // ACE_TRACE ("ACE_Unbounded_Queue_Iterator<T>::next");
420 if (this->current_ == this->queue_.head_)
421 return 0;
422 else
424 item = &this->current_->item_;
425 return 1;
429 ACE_END_VERSIONED_NAMESPACE_DECL
431 #endif /* ACE_UNBOUNDED_QUEUE_CPP */