Panda3D
datagramQueue.cxx
1 // Filename: datagramQueue.cxx
2 // Created by: drose (08Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "datagramQueue.h"
16 #include "config_net.h"
17 #include "mutexHolder.h"
18 
19 ////////////////////////////////////////////////////////////////////
20 // Function: DatagramQueue::Constructor
21 // Access: Public
22 // Description:
23 ////////////////////////////////////////////////////////////////////
24 DatagramQueue::
25 DatagramQueue() :
26  _cvlock("DatagramQueue::_cvlock"),
27  _cv(_cvlock)
28 {
29  _shutdown = false;
30  _max_queue_size = get_net_max_write_queue();
31 }
32 
33 ////////////////////////////////////////////////////////////////////
34 // Function: DatagramQueue::Destructor
35 // Access: Public
36 // Description:
37 ////////////////////////////////////////////////////////////////////
38 DatagramQueue::
39 ~DatagramQueue() {
40  // It's an error to delete a DatagramQueue without first shutting it
41  // down (and waiting for any associated threads to terminate).
42  nassertv(_shutdown);
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: DatagramQueue::shutdown
47 // Access: Public
48 // Description: Marks the queue as shutting down, which will
49 // eventually cause all threads blocking on extract() to
50 // return false. The normal way to delete a
51 // DatagramQueue will be to call first shutdown() and
52 // then wait for all known threads to terminate. Then
53 // it is safe to delete the queue.
54 ////////////////////////////////////////////////////////////////////
55 void DatagramQueue::
57  // Notify all of our threads that we're shutting down. This will
58  // cause any thread blocking on extract() to return false.
59  MutexHolder holder(_cvlock);
60 
61  _shutdown = true;
62  _cv.notify_all();
63 }
64 
65 
66 ////////////////////////////////////////////////////////////////////
67 // Function: DatagramQueue::insert
68 // Access: Public
69 // Description: Inserts the indicated datagram onto the end of the
70 // queue, and returns. If the queue is empty and any
71 // threads are waiting on the queue, this will wake one
72 // of them up. Returns true if successful, false if the
73 // queue was full.
74 //
75 // If block is true, this will not return until
76 // successful, waiting until the queue has space
77 // available if necessary.
78 ////////////////////////////////////////////////////////////////////
79 bool DatagramQueue::
80 insert(const NetDatagram &data, bool block) {
81  MutexHolder holder(_cvlock);
82 
83  bool enqueue_ok = ((int)_queue.size() < _max_queue_size);
84  if (block) {
85  while (!enqueue_ok && !_shutdown) {
86  _cv.wait();
87  enqueue_ok = ((int)_queue.size() < _max_queue_size);
88  }
89  }
90 
91  if (enqueue_ok) {
92  _queue.push_back(data);
93  }
94  _cv.notify(); // Only need to wake up one thread.
95 
96  return enqueue_ok;
97 }
98 
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: DatagramQueue::extract
102 // Access: Public
103 // Description: Extracts a datagram from the head of the queue, if
104 // one is available. If a datagram is available, this
105 // will immediately return; otherwise, it will block
106 // until a datagram becomes available. Multiple threads
107 // may simultaneously block on extract(); when a
108 // datagram is subsequently inserted into the queue, one
109 // of the threads will return from extract() with the
110 // datagram.
111 //
112 // The return value is true if the datagram is
113 // successfully extracted, or false if the queue was
114 // destroyed while waiting. (In the case of a false
115 // return, the thread should not attempt to operate on
116 // the queue again.)
117 ////////////////////////////////////////////////////////////////////
118 bool DatagramQueue::
120  // First, clear the datagram result in case it's got an outstanding
121  // connection pointer--we're about to go to sleep for a while.
122  result.clear();
123 
124  MutexHolder holder(_cvlock);
125 
126  while (_queue.empty() && !_shutdown) {
127  _cv.wait();
128  }
129 
130  if (_shutdown) {
131  return false;
132  }
133 
134  nassertr(!_queue.empty(), false);
135  result = _queue.front();
136  _queue.pop_front();
137 
138  // Wake up any threads waiting to stuff things into the queue.
139  _cv.notify_all();
140 
141  return true;
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: DatagramQueue::set_max_queue_size
146 // Access: Public
147 // Description: Sets the maximum size the queue is allowed to grow
148 // to. This is primarily for a sanity check; this is a
149 // limit beyond which we can assume something bad has
150 // happened.
151 //
152 // It's also a crude check against unfortunate seg
153 // faults due to the queue filling up and quietly
154 // consuming all available memory.
155 ////////////////////////////////////////////////////////////////////
156 void DatagramQueue::
157 set_max_queue_size(int max_size) {
158  MutexHolder holder(_cvlock);
159  _max_queue_size = max_size;
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: DatagramQueue::get_max_queue_size
164 // Access: Public
165 // Description: Returns the maximum size the queue is allowed to grow
166 // to. See set_max_queue_size().
167 ////////////////////////////////////////////////////////////////////
168 int DatagramQueue::
170  return _max_queue_size;
171 }
172 
173 ////////////////////////////////////////////////////////////////////
174 // Function: DatagramQueue::get_current_queue_size
175 // Access: Public
176 // Description: Returns the current number of things in the queue.
177 ////////////////////////////////////////////////////////////////////
178 int DatagramQueue::
180  MutexHolder holder(_cvlock);
181  int size = _queue.size();
182  return size;
183 }
void set_max_queue_size(int max_size)
Sets the maximum size the queue is allowed to grow to.
A specific kind of Datagram, especially for sending across or receiving from a network.
Definition: netDatagram.h:43
bool insert(const NetDatagram &data, bool block=false)
Inserts the indicated datagram onto the end of the queue, and returns.
void notify()
Informs one of the other threads who are currently blocked on wait() that the relevant condition has ...
void wait()
Waits on the condition.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:29
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
virtual void clear()
Resets the datagram to empty, in preparation for building up a new datagram.
Definition: netDatagram.cxx:93
bool extract(NetDatagram &result)
Extracts a datagram from the head of the queue, if one is available.
int get_max_queue_size() const
Returns the maximum size the queue is allowed to grow to.
void shutdown()
Marks the queue as shutting down, which will eventually cause all threads blocking on extract() to re...
int get_current_queue_size() const
Returns the current number of things in the queue.