summaryrefslogtreecommitdiff
path: root/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp
blob: 7253794cf0bcee7a90ac827abd4b2acb89c80c78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// $Id$

#include "CSD_TP_Queue.h"
#include "CSD_TP_Request.h"
#include "CSD_TP_Queue_Visitor.h"

ACE_RCSID (CSD_ThreadPool,
           TP_Queue,
           "$Id$")

#if !defined (__ACE_INLINE__)
# include "CSD_TP_Queue.inl"
#endif /* ! __ACE_INLINE__ */


void
TAO::CSD::TP_Queue::put(TP_Request* request)
{
  // The request is passed in as an "in" argument, and we would like to
  // hold on to a "copy" within the queue (the linked list).  We will
  // perform an _add_ref() on the request now to make the queue's "copy".
  request->_add_ref();

  if (this->tail_ == 0)
    {
      // The tail_ is a NULL pointer only when the queue is empty.
      // Make the request be the only element in the queue.
      this->head_ = this->tail_ = request;

      // Make sure the request's prev_ and next_ pointers are set to NULL.
      request->prev_ = request->next_ = 0;
    }
  else
    {
      // There is at least one request already in the queue.  "Append" the
      // supplied request object to the end of the queue.
      request->prev_ = this->tail_;
      request->next_ = 0;
      this->tail_->next_ = request;
      this->tail_ = request;
    }
}


void
TAO::CSD::TP_Queue::accept_visitor(TP_Queue_Visitor& visitor)
{
  TP_Request* cur = this->head_;

  while (cur != 0)
    {
      TP_Request* prev = cur->prev_;
      TP_Request* next = cur->next_;

      // Pass the current request to the visitor.  Also pass-in a reference
      // to the remove_from_queue flag.  The visitor may decide that it
      // wants to keep the current request for itself, and desires that the
      // request be (surgically) removed from the queue.  The visitor also
      // gets to decide, via its return value, whether or not visitation
      // should continue (or cease to continue).
      bool remove_from_queue = false;

      bool continue_visitation = visitor.visit_request(cur,remove_from_queue);

      if (remove_from_queue)
        {
          // Create a local handle to release the current request once
          // the handle falls out of scope.  We need to do this because the
          // queue "owns" a "copy" of each request in the queue.
          TP_Request_Handle handle = cur;

          if (this->head_ == cur)
            {
              // The current request is at the front (the head_) of the queue.

              // Move the head_ to the next request in the queue.
              this->head_ = next;

              if (this->head_ == 0)
                {
                  // Not only was the current request at the front of the
                  // queue - it was the *only* request in the queue.
                  // Update the tail_ pointer now that the queue is empty.
                  this->tail_ = 0;
                }
              else
                {
                  // Set the (new) head_ request's prev_ pointer to be NULL.
                  this->head_->prev_ = 0;
                }
            }
          else if (this->tail_ == cur)
            {
              // The current request is not at the front of the queue,
              // but it is at the back of the queue.  This implies that
              // the queue currently contains at least two requests -
              // the current request (cur), and the previous request (prev).
              // The point is that we can now assume that the 'prev' pointer
              // is never NULL in this case.
              this->tail_ = prev;
              this->tail_->next_ = 0;
            }
          else
            {
              // The current request is not at the front or at the back.
              // This implies that there are at least three requests in
              // the queue.  We can assume that the 'next' and 'prev'
              // pointers are never NULL in this case.
              prev->next_ = next;
              next->prev_ = prev;
            }
        }

      if (!continue_visitation)
        {
          // The visitor doesn't want to procede with any further visitation.
          // Break out of the visitation loop now.
          break;
        }

      // Move on to the next request in the queue.
      cur = next;
    }
}