Panda3D
datagramGeneratorNet.cxx
1 // Filename: datagramGeneratorNet.cxx
2 // Created by: drose (15Feb09)
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 "pandabase.h"
16 
17 #include "datagramGeneratorNet.h"
18 #include "mutexHolder.h"
19 #include "lightMutexHolder.h"
20 
21 ////////////////////////////////////////////////////////////////////
22 // Function: DatagramGeneratorNet::Constructor
23 // Access: Published
24 // Description: Creates a new DatagramGeneratorNet with the indicated
25 // number of threads to handle requests. Normally
26 // num_threads should be either 0 or 1 to guarantee that
27 // datagrams are generated in the same order in which
28 // they were received.
29 ////////////////////////////////////////////////////////////////////
31 DatagramGeneratorNet(ConnectionManager *manager, int num_threads) :
32  ConnectionReader(manager, num_threads),
33  _dg_received(_dg_lock),
34  _dg_processed(_dg_lock)
35 {
36 }
37 
38 ////////////////////////////////////////////////////////////////////
39 // Function: DatagramGeneratorNet::Destructor
40 // Access: Published, Virtual
41 // Description:
42 ////////////////////////////////////////////////////////////////////
43 DatagramGeneratorNet::
44 ~DatagramGeneratorNet() {
45 }
46 
47 ////////////////////////////////////////////////////////////////////
48 // Function: DatagramGeneratorNet::get_datagram
49 // Access: Published, Virtual
50 // Description: Reads the next datagram from the stream. Blocks
51 // until a datagram is available. Returns true on
52 // success, false on stream closed or error.
53 ////////////////////////////////////////////////////////////////////
56  if (is_polling()) {
57  // Single-threaded case: we poll. No need to lock.
58  if (!thing_available()) {
59  if (net_cat.is_spam()) {
60  net_cat.spam()
61  << "DatagramGeneratorNet polling\n";
62  }
63  poll();
64  }
65  while (!thing_available()) {
66  if (is_eof()) {
67  if (net_cat.is_spam()) {
68  net_cat.spam()
69  << "DatagramGeneratorNet returning EOF\n";
70  }
71  return false;
72  }
73  poll();
75  }
76  bool got_dg = get_thing(data);
77  nassertr(got_dg, false);
78 
79  } else {
80  // Threaded case: no polling, we use mutexes and cvars to block
81  // instead.
82  MutexHolder holder(_dg_lock);
83  while (!thing_available()) {
84  if (is_eof()) {
85  if (net_cat.is_spam()) {
86  net_cat.spam()
87  << "DatagramGeneratorNet returning EOF\n";
88  }
89  return false;
90  }
91  if (net_cat.is_spam()) {
92  net_cat.spam()
93  << "DatagramGeneratorNet waiting\n";
94  }
95  _dg_received.wait();
96  }
97  bool got_dg = get_thing(data);
98  nassertr(got_dg, false);
99  _dg_processed.notify();
100  }
101 
102  if (net_cat.is_spam()) {
103  net_cat.spam()
104  << "DatagramGeneratorNet returning datagram of length "
105  << data.get_length() << "\n";
106  }
107 
108  return true;
109 }
110 
111 ////////////////////////////////////////////////////////////////////
112 // Function: DatagramGeneratorNet::is_eof
113 // Access: Published, Virtual
114 // Description: Returns true if the stream has been closed normally.
115 // This test may only be made after a call to
116 // get_datagram() has failed.
117 ////////////////////////////////////////////////////////////////////
120  // We're at eof if we have no more connected sockets.
121  LightMutexHolder holder(_sockets_mutex);
122  return _sockets.empty();
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: DatagramGeneratorNet::is_error
127 // Access: Published, Virtual
128 // Description: Returns true if the stream has an error condition.
129 ////////////////////////////////////////////////////////////////////
132  // There's an error if any one of our connected sockets reports an error.
133  LightMutexHolder holder(_sockets_mutex);
134  Sockets::const_iterator si;
135  for (si = _sockets.begin(); si != _sockets.end(); ++si) {
136  SocketInfo *sinfo = (*si);
137  if (sinfo->_error) {
138  return true;
139  }
140  }
141 
142  return false;
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: DatagramGeneratorNet::receive_datagram
147 // Access: Protected, Virtual
148 // Description: An internal function called by ConnectionReader()
149 // when a new datagram has become available. This call
150 // may be received in a sub-thread.
151 ////////////////////////////////////////////////////////////////////
152 void DatagramGeneratorNet::
153 receive_datagram(const NetDatagram &datagram) {
154  MutexHolder holder(_dg_lock);
155  while (!enqueue_thing(datagram)) {
156  _dg_processed.wait();
157  }
158  _dg_received.notify();
159 }
160 
virtual bool get_datagram(Datagram &data)
Reads the next datagram from the stream.
A specific kind of Datagram, especially for sending across or receiving from a network.
Definition: netDatagram.h:43
bool is_polling() const
Returns true if the reader is a polling reader, i.e.
The primary interface to the low-level networking layer in this package.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:29
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition: thread.I:248
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
void poll()
Explicitly polls the available sockets to see if any of them have any noise.
virtual bool is_eof()
Returns true if the stream has been closed normally.
Similar to MutexHolder, but for a light mutex.
DatagramGeneratorNet(ConnectionManager *manager, int num_threads)
Creates a new DatagramGeneratorNet with the indicated number of threads to handle requests...
virtual bool is_error()
Returns true if the stream has an error condition.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
void wait()
Waits on the condition.
void notify()
Informs one of the other threads who are currently blocked on wait() that the relevant condition has ...
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:457