RflySimSDK v3.05
RflySimSDK说明文档
载入中...
搜索中...
未找到
vrpn_Imager_Stream_Buffer.h
1#ifndef VRPN_IMAGER_STREAM_BUFFER_H
2#define VRPN_IMAGER_STREAM_BUFFER_H
3#include <string.h> // for NULL, strcpy, strlen
4
5#include "vrpn_Auxiliary_Logger.h"
6#include "vrpn_Configure.h" // for VRPN_CALLBACK, VRPN_API
7#include "vrpn_Connection.h" // for vrpn_Connection (ptr only), etc
8#include "vrpn_Imager.h"
9#include "vrpn_Shared.h" // for vrpn_Semaphore, etc
10#include "vrpn_Types.h" // for vrpn_int32, vrpn_uint16
11
12// This is a fairly complicated class that implements a multi-threaded
13// full-rate logger and partial-rate forwarder for a vrpn_Imager_Server
14// object. It is intended to allow previewing of microscopy experiments
15// at a subset of the camera's video rate while logging the video at
16// full rate, possibly on a remote computer and possibly on the original
17// video server computer. Its architecture is described in the "Full-rate
18// logging" section of the vrpn_Imager.html document in the VRPN web
19// page.
20
21//-------------------------------------------------------------------
22// This is a helper class for the vrpn_Imager_Stream_Shared_State class
23// below. It keeps a linked list of vrpn_HANDLERPARAM types and the
24// buffers to which they point. The buffers need to be allocated by
25// the one who inserts to this list and deleted by the one who pulls
26// elements from this list.
27
28class VRPN_API vrpn_Message_List {
29public:
31 {
32 d_first = d_last = NULL;
33 d_count = 0;
34 };
36 {
37 while (d_first != NULL) {
38 struct d_ELEMENT *next = d_first->next;
39 try {
40 delete d_first;
41 } catch (...) {
42 fprintf(stderr, "vrpn_Message_List::~vrpn_Message_List(): delete failed\n");
43 return;
44 }
45 d_first = next;
46 }
47 }
48
49 // Give the length of the list.
50 unsigned size(void) const { return d_count; }
51
52 // Insert an element into the list. Return false if fails.
53 bool insert_back(const vrpn_HANDLERPARAM &p)
54 {
55 struct d_ELEMENT *el;
56 try { el = new struct d_ELEMENT; }
57 catch (...) {
58 return false;
59 }
60 el->p = p;
61 el->next = NULL;
62 if (d_last != NULL) {
63 d_last->next = el;
64 }
65 d_last = el;
66 if (d_first == NULL) {
67 d_first = el;
68 }
69 d_count++;
70 return true;
71 }
72
73 // Remove an element from the list. Return false if fails.
74 bool retrieve_front(vrpn_HANDLERPARAM *p)
75 {
76 if (p == NULL) {
77 return false;
78 }
79 if (size() == 0) {
80 return false;
81 }
82
83 *p = d_first->p;
84 if (d_last == d_first) {
85 d_last = NULL;
86 }
87 struct d_ELEMENT *temp = d_first;
88 d_first = d_first->next;
89 try {
90 delete temp;
91 } catch (...) {
92 fprintf(stderr, "vrpn_Message_List::retrieve_front(): delete failed\n");
93 return false;
94 }
95
96 d_count--;
97 return true;
98 }
99
100protected:
101 struct d_ELEMENT {
103 struct d_ELEMENT *next;
104 };
105 struct d_ELEMENT *d_first, *d_last;
106 unsigned d_count;
107};
108
109//-------------------------------------------------------------------
110// This is the data structure that is shared between the initial
111// thread (which listens for client connections) and the non-blocking logging
112// thread that sometimes exists to listen to the vrpn_Imager_Server.
113// All of its methods must be thread-safe, so it creates a semaphore
114// for access and uses it in all of the non-atomic methods.
115// Note that some of the things in here are pointers to objects that
116// are in the parent class, and they are here just to provide the
117// semaphore protection. The parent class should only access these
118// things through this shared state object.
119
121public:
123
124 // Reset the shared state to what it should be at
125 // the time the logging thread is started.
126 void init(void)
127 {
128 d_time_to_exit = false;
129 d_description_updated = false;
130 d_nRows = d_nCols = d_nDepth = d_nChannels = 0;
131 d_new_log_request = false;
132 d_request_lil = NULL;
133 d_request_lol = NULL;
134 d_request_ril = NULL;
135 d_request_rol = NULL;
136 d_new_log_result = false;
137 d_result_lil = NULL;
138 d_result_lol = NULL;
139 d_result_ril = NULL;
140 d_result_rol = NULL;
141 d_new_throttle_request = false;
142 d_throttle_count = -1;
143 d_frames_in_queue = 0;
144 }
145
146 // Accessors for the "time to exit" flag; set by the initial thread and
147 // read by the logging thread.
148 bool time_to_exit(void)
149 {
150 vrpn::SemaphoreGuard guard(d_sem);
151 bool ret = d_time_to_exit;
152 return ret;
153 }
154 void time_to_exit(bool do_exit)
155 {
156 vrpn::SemaphoreGuard guard(d_sem);
157 d_time_to_exit = do_exit;
158 }
159
160 // Accessors for the parameters stored based on the
161 // imager server's reports. Returns false if nothing has
162 // been set since the last time it was read, true (and fills in
163 // the values) if it has. Channel buffer must be delete [] by
164 // the one calling this function iff the function returns true.
165 bool get_imager_description(vrpn_int32 &nRows, vrpn_int32 &nCols,
166 vrpn_int32 &nDepth, vrpn_int32 &nChannels,
167 const char **channelBuffer)
168 {
169 vrpn::SemaphoreGuard guard(d_sem);
170 bool ret = d_description_updated;
171 if (d_description_updated) {
172 nRows = d_nRows;
173 nCols = d_nCols;
174 nDepth = d_nDepth;
175 nChannels = d_nChannels;
176 *channelBuffer = d_channel_buffer;
177 }
178 d_description_updated = false;
179 return ret;
180 }
181 bool set_imager_description(vrpn_int32 nRows, vrpn_int32 nCols,
182 vrpn_int32 nDepth, vrpn_int32 nChannels,
183 const char *channelBuffer)
184 {
185 vrpn::SemaphoreGuard guard(d_sem);
186 d_nRows = nRows;
187 d_nCols = nCols;
188 d_nDepth = nDepth;
189 d_nChannels = nChannels;
190 d_channel_buffer = channelBuffer;
191 d_description_updated = true;
192 return true;
193 }
194
195 // Accessors for the initial thread to pass new logfile names down to the
196 // logging thread, which will cause it to initiate a changeover of logging
197 // connections. Space for the return strings will be allocated in these
198 // functions and must be deleted by the logging thread ONLY IF the get
199 // function fills the values in (it returns true if it does).
200 //
201 // NOTE: this is used to query BOTH the presence of new logfile names
202 // AS WELL AS the names themselves. this function will only return values
203 // if new logfile names have been requested since the last time this
204 // function was called.
205 bool get_logfile_request(char **lil, char **lol, char **ril, char **rol)
206 {
207 vrpn::SemaphoreGuard guard(d_sem);
208 bool ret = d_new_log_request;
209 if (d_new_log_request) {
210 // Allocate space to return the names in the handles passed in.
211 // Copy the values from our local storage to the return values.
212 if ((*lil = new(std::nothrow) char[strlen(d_request_lil) + 1]) != NULL) {
213 vrpn_strncpynull(*lil, d_request_lil, strlen(d_request_lil) + 1);
214 }
215 if ((*lol = new(std::nothrow) char[strlen(d_request_lol) + 1]) != NULL) {
216 vrpn_strncpynull(*lol, d_request_lol, strlen(d_request_lol) + 1);
217 }
218 if ((*ril = new(std::nothrow) char[strlen(d_request_ril) + 1]) != NULL) {
219 vrpn_strncpynull(*ril, d_request_ril, strlen(d_request_ril) + 1);
220 }
221 if ((*rol = new(std::nothrow) char[strlen(d_request_rol) + 1]) != NULL) {
222 vrpn_strncpynull(*rol, d_request_rol, strlen(d_request_rol) + 1);
223 }
224
225 // Delete and NULL the local storage pointers.
226 try {
227 delete[] d_request_lil;
228 d_request_lil = NULL;
229 delete[] d_request_lol;
230 d_request_lol = NULL;
231 delete[] d_request_ril;
232 d_request_ril = NULL;
233 delete[] d_request_rol;
234 d_request_rol = NULL;
235 } catch (...) {
236 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::get_logfile_request(): delete failed\n");
237 return false;
238 }
239 }
240 d_new_log_request = false;
241 return ret;
242 }
243
244 void set_logfile_request(const char *lil, const char *lol, const char *ril,
245 const char *rol)
246 {
247 vrpn::SemaphoreGuard guard(d_sem);
248
249 // delete file names, in case the logging thread hasn't had a chance to
250 // honor the request yet.
251 if (d_request_lil) {
252 try {
253 delete[] d_request_lil;
254 } catch (...) {
255 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_request(): delete failed\n");
256 return;
257 }
258 d_request_lil = NULL;
259 }
260 if (d_request_lol) {
261 try {
262 delete[] d_request_lol;
263 } catch (...) {
264 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_request(): delete failed\n");
265 return;
266 }
267 d_request_lol = NULL;
268 }
269 if (d_request_ril) {
270 try {
271 delete[] d_request_ril;
272 } catch (...) {
273 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_request(): delete failed\n");
274 return;
275 }
276 d_request_ril = NULL;
277 }
278 if (d_request_rol) {
279 try {
280 delete[] d_request_rol;
281 } catch (...) {
282 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_request(): delete failed\n");
283 return;
284 }
285 d_request_rol = NULL;
286 }
287
288 // Allocate space for each string and then copy into it.
289 if (lil != NULL) {
290 if ((d_request_lil = new(std::nothrow) char[strlen(lil) + 1]) != NULL) {
291 vrpn_strncpynull(d_request_lil, lil, strlen(lil) + 1);
292 }
293 }
294 if (lol != NULL) {
295 if ((d_request_lol = new(std::nothrow) char[strlen(lol) + 1]) != NULL) {
296 vrpn_strncpynull(d_request_lol, lol, strlen(lol) + 1);
297 }
298 }
299 if (ril != NULL) {
300 if ((d_request_ril = new(std::nothrow) char[strlen(ril) + 1]) != NULL) {
301 vrpn_strncpynull(d_request_ril, ril, strlen(ril) + 1);
302 }
303 }
304 if (rol != NULL) {
305 if ((d_request_rol = new(std::nothrow) char[strlen(rol) + 1]) != NULL) {
306 vrpn_strncpynull(d_request_rol, rol, strlen(rol) + 1);
307 }
308 }
309
310 d_new_log_request = true;
311 }
312
313 // Accessors for the logfile thread to pass new logfile names back up to the
314 // initial thread, reporting a changeover of logging connections.
315 // Space for the return strings will be allocated in these functions
316 // and must be deleted by the initial thread ONLY IF the get function fills
317 // the
318 // values in (it returns true if it does).
319 // NOTE: this function is intended to query BOTH the logfile names AS WELL
320 // AS
321 // the change in logging status. it ONLY returns filenames if logging has
322 // changed since the last time this function was called).
323 bool get_logfile_result(char **lil, char **lol, char **ril, char **rol)
324 {
325 vrpn::SemaphoreGuard guard(d_sem);
326 bool ret = d_new_log_result;
327 if (d_new_log_result) {
328 // Allocate space to return the names in the handles passed in.
329 // Copy the values from our local storage to the return values.
330 if (d_result_lil == NULL)
331 *lil = NULL;
332 else {
333 if ((*lil = new(std::nothrow) char[strlen(d_result_lil) + 1]) != NULL) {
334 vrpn_strncpynull(*lil, d_result_lil, strlen(d_result_lil) + 1);
335 }
336 }
337 if (d_result_lol == NULL)
338 *lol = NULL;
339 else {
340 if ((*lol = new(std::nothrow) char[strlen(d_result_lol) + 1]) != NULL) {
341 vrpn_strncpynull(*lol, d_result_lol, strlen(d_result_lol) + 1);
342 }
343 }
344 if (d_result_ril == NULL)
345 *ril = NULL;
346 else {
347 if ((*ril = new(std::nothrow) char[strlen(d_result_ril) + 1]) != NULL) {
348 vrpn_strncpynull(*ril, d_result_ril, strlen(d_result_ril) + 1);
349 }
350 }
351 if (d_result_rol == NULL)
352 *rol = NULL;
353 else {
354 if ((*rol = new(std::nothrow) char[strlen(d_result_rol) + 1]) != NULL) {
355 vrpn_strncpynull(*rol, d_result_rol, strlen(d_result_rol) + 1);
356 }
357 }
358
359 // do not Delete and NULL the local storage pointers.
360 // someone may request the filenames later.
361 }
362 d_new_log_result = false;
363 return ret;
364 }
365
366 void set_logfile_result(const char *lil, const char *lol, const char *ril,
367 const char *rol)
368 {
369 vrpn::SemaphoreGuard guard(d_sem);
370
371 if (d_result_lil) {
372 try {
373 delete[] d_result_lil;
374 } catch (...) {
375 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_result(): delete failed\n");
376 return;
377 }
378 }
379 d_result_lil = NULL;
380 if (d_result_lol) {
381 try {
382 delete[] d_result_lol;
383 } catch (...) {
384 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_result(): delete failed\n");
385 return;
386 }
387 }
388 d_result_lol = NULL;
389 if (d_result_ril) {
390 try {
391 delete[] d_result_ril;
392 } catch (...) {
393 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_result(): delete failed\n");
394 return;
395 }
396 }
397 d_result_ril = NULL;
398 if (d_result_rol) {
399 try {
400 delete[] d_result_rol;
401 } catch (...) {
402 fprintf(stderr, "vrpn_Imager_Stream_Shared_State::set_logfile_result(): delete failed\n");
403 return;
404 }
405 }
406 d_result_rol = NULL;
407
408 // Allocate space for each string and then copy into it.
409 if (lil != NULL) {
410 if ((d_result_lil = new(std::nothrow) char[strlen(lil) + 1]) != NULL) {
411 vrpn_strncpynull(d_result_lil, lil, strlen(lil) + 1);
412 }
413 }
414 if (lol != NULL) {
415 if ((d_result_lol = new(std::nothrow) char[strlen(lol) + 1]) != NULL) {
416 vrpn_strncpynull(d_result_lol, lol, strlen(lol) + 1);
417 }
418 }
419 if (ril != NULL) {
420 if ((d_result_ril = new(std::nothrow) char[strlen(ril) + 1]) != NULL) {
421 vrpn_strncpynull(d_result_ril, ril, strlen(ril) + 1);
422 }
423 }
424 if (rol != NULL) {
425 if ((d_result_rol = new(std::nothrow) char[strlen(rol) + 1]) != NULL) {
426 vrpn_strncpynull(d_result_rol, rol, strlen(rol) + 1);
427 }
428 }
429
430 d_new_log_result = true;
431 }
432
433 // fills in the arguments with the logfile names currently in use
434 // for a particular log, the value will be NULL if that log is not being
435 // collected.
436 // NOTE: this function allocates memory for each string returned. IT IS
437 // THE
438 // RESPONSIBILITY OF THE CALLING FUNCTION TO FREE THIS MEMORY.
439 void get_logfile_names(char **local_in, char **local_out, char **remote_in,
440 char **remote_out)
441 {
442 vrpn::SemaphoreGuard guard(d_sem);
443 if (d_result_lil == NULL)
444 *local_in = NULL;
445 else {
446 *local_in = new char[strlen(d_result_lil) + 1];
447 vrpn_strncpynull(*local_in, d_result_lil, strlen(d_result_lil) + 1);
448 }
449 if (d_result_lol == NULL)
450 *local_out = NULL;
451 else {
452 *local_out = new char[strlen(d_result_lol) + 1];
453 vrpn_strncpynull(*local_out, d_result_lol, strlen(d_result_lol) + 1);
454 }
455 if (d_result_ril == NULL)
456 *remote_in = NULL;
457 else {
458 *remote_in = new char[strlen(d_result_ril) + 1];
459 vrpn_strncpynull(*remote_in, d_result_ril, strlen(d_result_ril) + 1);
460 }
461 if (d_result_rol == NULL)
462 *remote_out = NULL;
463 else {
464 *remote_out = new char[strlen(d_result_rol) + 1];
465 vrpn_strncpynull(*remote_out, d_result_rol, strlen(d_result_rol) + 1);
466 }
467 }
468
469 // Accessors for the initial thread to pass new throttle values down to the
470 // logging thread, which will cause it to throttle as needed.
471 bool get_throttle_request(vrpn_int32 *throttle_count)
472 {
473 vrpn::SemaphoreGuard guard(d_sem);
474 bool ret = d_new_throttle_request;
475 if (d_new_throttle_request) {
476 *throttle_count = d_throttle_count;
477 }
478 d_new_throttle_request = false;
479 return ret;
480 }
481 void set_throttle_request(vrpn_int32 throttle_count)
482 {
483 vrpn::SemaphoreGuard guard(d_sem);
484 d_throttle_count = throttle_count;
485 d_new_throttle_request = true;
486 }
487
488 // Accessors for the logging thread to increment and read the number of
489 // frames in the queue and for the initial thread to decrement them. The
490 // increment/decrement is done when a begin_frame message is found. The
491 // increment/decrement routines return the new value.
492 vrpn_int32 get_frames_in_queue(void)
493 {
494 vrpn::SemaphoreGuard guard(d_sem);
495 vrpn_int32 ret = d_frames_in_queue;
496 return ret;
497 }
498 vrpn_int32 increment_frames_in_queue(void)
499 {
500 vrpn::SemaphoreGuard guard(d_sem);
501 d_frames_in_queue++;
502 vrpn_int32 ret = d_frames_in_queue;
503 return ret;
504 }
505 vrpn_int32 decrement_frames_in_queue(void)
506 {
507 vrpn::SemaphoreGuard guard(d_sem);
508 d_frames_in_queue--;
509 vrpn_int32 ret = d_frames_in_queue;
510 return ret;
511 }
512
513 // Accessors for the logging thread to add messages to the queue
514 // and for the initial thread to retrieve and count them.
515 vrpn_int32 get_logger_to_client_queue_size(void)
516 {
517 vrpn::SemaphoreGuard guard(d_sem);
518 vrpn_int32 ret = d_logger_to_client_messages.size();
519 return ret;
520 }
521 bool insert_logger_to_client_message(const vrpn_HANDLERPARAM &p)
522 {
523 vrpn::SemaphoreGuard guard(d_sem);
524 bool ret = d_logger_to_client_messages.insert_back(p);
525 return ret;
526 }
527 bool retrieve_logger_to_client_message(vrpn_HANDLERPARAM *p)
528 {
529 vrpn::SemaphoreGuard guard(d_sem);
530 bool ret = d_logger_to_client_messages.retrieve_front(p);
531 return ret;
532 }
533
534protected:
535 vrpn_Semaphore d_sem; // Semaphore to control access to data items.
536
537 // Is it time for the logging thread to exit?
538 bool d_time_to_exit;
539
540 // Stored copies of the value in the vrpn_Imager_Remote and a flag telling
541 // whether they have changed since last read.
542 bool d_description_updated; // Do we have a new description from imager
543 // server?
544 vrpn_int32 d_nRows;
545 vrpn_int32 d_nCols;
546 vrpn_int32 d_nDepth;
547 vrpn_int32 d_nChannels;
548 const char *d_channel_buffer; //< Allocated by sender, freed by receiver
549
550 // Names of the log files passed from the initial thread to the logging
551 // thread and a flag telling whether they have been changed since last
552 // read.
553 bool d_new_log_request;
554 char *d_request_lil;
555 char *d_request_lol;
556 char *d_request_ril;
557 char *d_request_rol;
558
559 // Names of the log files passed from the logging thread to the initial
560 // thread and a flag telling whether they have been changed since last
561 // read. NOTE: we maintain a copy of the log file names here, instead
562 // of using the accessor of vrpn_Connection to query the names. Only
563 // the logging thread is supposed to have access to the logging connection,
564 // but the logging thread is banned from calling methods on the client
565 // connection.
566 bool d_new_log_result;
567 char *d_result_lil;
568 char *d_result_lol;
569 char *d_result_ril;
570 char *d_result_rol;
571
572 // New throttle request passed on by the client-handling thread
573 bool d_new_throttle_request;
574 vrpn_int32 d_throttle_count;
575
576 // Records the number of frames in the queue. This is incremented
577 // by the non-blocking thread and decremented by the initial thread
578 // as the begin_frame() messages are queued and dequeued.
579 vrpn_int32 d_frames_in_queue;
580
581 // List of messages passing from the logging thread to the initial
582 // thread.
583 vrpn_Message_List d_logger_to_client_messages;
584};
585
586//-------------------------------------------------------------------
587// This class is a vrpn_Imager_Server; it has one or two instances of
588// vrpn_Imager_Clients to talk to the server it is forwarding packets
589// to. It does not use their callback parsers, but rather hooks its own
590// callbacks directly to the connection object for the server it is
591// buffering.
592
594 public vrpn_Imager_Server {
595public:
596 // Name of this object (the server side of the vrpn_Imager that is
597 // buffered and the vrpn_Auxiliary_Logger that the client will connect to).
598 // (Optional, can be NULL) pointer to the server connection on which to
599 // communicate.
600 // Name of the vrpn_Imager_Server to connect to (packets from this server
601 // will
602 // be forwarded to the main connection, and logging will occur on the
603 // connection
604 // to this imager_server). This server may be local or remote; if local,
605 // include "@localhost" in the name because new connections will be made to
606 // it.
607 vrpn_Imager_Stream_Buffer(const char *name, const char *imager_server_name,
608 vrpn_Connection *c);
609
610 // Get rid of any logging thread and then clean up.
612
613 // Required for servers.
614 virtual void mainloop(void);
615
616protected:
617 // Handle a logging-request message. The request contains four file
618 // names, two for local (to the Auxiliary server itself) and two for
619 // remote (the far side of its connection to the server). It must
620 // also respond to the client with a message saying what logging has
621 // been set up (using the send_logging_response function). Logging is
622 // turned off on a particular file by sending an empty-string name ("").
623 // The in/out local/remote are with respect to the connection that the
624 // logging is to occur on, which is to the imager server whose name is
625 // passed in to the constructor, not the connection that the client has
626 // sent the request on.
627 // Make sure to send a response saying what you did.
628 virtual void handle_request_logging(const char *local_in_logfile_name,
629 const char *local_out_logfile_name,
630 const char *remote_in_logfile_name,
631 const char *remote_out_logfile_name);
632
633 // Static portion of handling (unpacking) the request_logging message. It
634 // then calls the non-static virtual method above.
635 static int VRPN_CALLBACK
636 static_handle_request_logging(void *userdata, vrpn_HANDLERPARAM p);
637
638 virtual void handle_request_logging_status();
639
640 // Handle dropped last connection on our primary connection by shutting down
641 // the
642 // connection to the imager server. The static method in the base class
643 // looks up this
644 // pointer and calls the virtual method.
645 virtual void handle_dropped_last_connection(void);
646
647 // Handles a throttle request by passing it on down to the non-blocking
648 // thread to deal with.
649 static int VRPN_CALLBACK
650 static_handle_throttle_message(void *userdata, vrpn_HANDLERPARAM p);
651
652 // Handle got first connection request by (having the second thread) create
653 // a connection to the server and waiting until we get a description message
654 // from the imager server we're listening to. Timeout after a while if the
655 // connection cannot be made or the server does not respond.
656 virtual void handle_got_first_connection(void);
657 vrpn_int32 got_first_connection_m_id; // ID of message that we got the first
658 // connection
659 static int VRPN_CALLBACK
660 static_handle_got_first_connection(void *userdata, vrpn_HANDLERPARAM p);
661
662 // State shared between the initial thread and the logging thread.
663 vrpn_Imager_Stream_Shared_State d_shared_state;
664
665 //----------------------------------------------------------------------
666 // The section below includes methods and member variables that should
667 // only be used by the logging thread. They are not protected by
668 // semaphores and so should not be accessed except within the
669 // logging_thread_func().
670
671 // This class spawns a new thread to handle uninterrupted communication
672 // and logging with the vrpn_Imager_Server that we are forwarding messages
673 // for. This is created in the constructor and shut down (hopefully gently)
674 // in the destructor. There are a number of semaphores that are used by
675 // the initial thread and the logging thread to communicate.
676 vrpn_Thread *d_logging_thread;
677
678 // The function that is called to become the logging thread. It is passed
679 // a pointer to "this" so that it can acces the object that created it.
680 // Note that it must use semaphores to get at the data that will be shared
681 // between the main thread and itself. The static function basically just
682 // pulls the "this" pointer out and then calls the non-static function.
683 static void static_logging_thread_func(vrpn_ThreadData &threadData);
684 void logging_thread_func(void);
685
686 // Stop the logging thread function, cleanly if possible. Returns true if
687 // the function stopped cleanly, false if it had to be killed.
688 bool stop_logging_thread(void);
689
690 // Name of the vrpn_Imager_Server object we are to connect to and
691 // log/pass messages from.
692 char *d_imager_server_name;
693
694 // Are we ready to drop the old connection (new one has received its
695 // descriptor message)?
696 bool d_ready_to_drop_old_connection;
697
698 // The connection that is used to talk to the client.
699 vrpn_Connection *d_log_connection;
701 open_new_log_connection(const char *local_in_logfile_name,
702 const char *local_out_logfile_name,
703 const char *remote_in_logfile_name,
704 const char *remote_out_logfile_name);
705
706 // These will create/destroy the d_imager_remote and other callback handlers
707 // needed to provide the handling of messages from the logging connection
708 // passed in; they are used by the initial-connection code and by the
709 // code that handles handing off from an old connection to a new connection
710 // when a new logging message is received.
711 bool setup_handlers_for_logging_connection(vrpn_Connection *c);
712 bool teardown_handlers_for_logging_connection(vrpn_Connection *c);
713
714 // This is yet another "create me some logs" function; it handles the
715 // hand-off from one log file to another within the logging thread.
716 // It is called by the main logging thread function when a request comes in
717 // from the initial thread to perform logging.
718 bool make_new_logging_connection(const char *local_in_logfile_name,
719 const char *local_out_logfile_name,
720 const char *remote_in_logfile_name,
721 const char *remote_out_logfile_name);
722
723 // The imager remote to listen to the vrpn_Imager_Server, along
724 // with the callback functions that support its operation. The
725 // generic VRPN callback handler that receives all messages from
726 // the imager server and either queues them or handles them, there
727 // is a static version that just gets a this pointer and calls the
728 // non-static function.
729 vrpn_Imager_Remote *d_imager_remote;
730 static void VRPN_CALLBACK
731 handle_image_description(void *pvISB, const struct timeval msg_time);
732 static int VRPN_CALLBACK
733 static_handle_server_messages(void *pvISB, vrpn_HANDLERPARAM p);
734 int handle_server_messages(const vrpn_HANDLERPARAM &p);
735
736 // Types of messages we expect to be coming from the server.
737 vrpn_int32 d_server_description_m_id; //< ID of the message type describing
738 // the range and channels
739 vrpn_int32 d_server_begin_frame_m_id; //< ID of the message type describing
740 // the start of a region
741 vrpn_int32 d_server_end_frame_m_id; //< ID of the message type describing
742 // the start of a region
743 vrpn_int32 d_server_discarded_frames_m_id; //< ID of the message type
744 // describing the discarding of
745 // one or more regions
746 vrpn_int32 d_server_regionu8_m_id; //< ID of the message type describing a
747 // region with 8-bit unsigned entries
748 vrpn_int32 d_server_regionu12in16_m_id; //< ID of the message type
749 // describing a region with 12-bit
750 // unsigned entries packed in 16 bits
751 vrpn_int32 d_server_regionu16_m_id; //< ID of the message type describing a
752 // region with 16-bit unsigned entries
753 vrpn_int32 d_server_regionf32_m_id; //< ID of the message type describing a
754 // region with 32-bit float entries
755 vrpn_int32 d_server_text_m_id; //< ID of the system text message
756 vrpn_int32 d_server_ping_m_id; //< ID of the system ping message
757 vrpn_int32 d_server_pong_m_id; //< ID of the system pong message
758
759 // Transcode the sender and type fields from the logging server connection
760 // to
761 // the initial client connection and pack the resulting message into the
762 // queue
763 // from the logging thread to the initial thread. The data buffer is
764 // copied;
765 // this space is allocated by the logging thread and must be freed by the
766 // initial thread.
767 // Returns true on success and false on failure. The sender is set to the
768 // d_sender_id of our server object.
769 bool transcode_and_send(const vrpn_HANDLERPARAM &p);
770
771 // Transcode the type from the logging thread's connection type to
772 // the initial thread's connection type. Return -1 if we don't
773 // recognize the type.
774 vrpn_int32 transcode_type(vrpn_int32 type);
775
776 // Handling throttling on the non-blocking thread. This is a shadow
777 // copy of the structures in the vrpn_Image_Server base class; we cannot
778 // use those directly because they will be adjusted by their own callbacks
779 // in the initial thread.
780 vrpn_uint16 d_server_dropped_due_to_throttle;
781 vrpn_int32 d_server_frames_to_send;
782};
783
784//-----------------------------------------------------------
785// Client code should connect to the server twice, once as
786// a vrpn_Imager_Server and once as a vrpn_Auxiliary_Logger_Server.
787// There is not a special remote class for this.
788
789#endif
An RAII lock/guard class for vrpn_Semaphore
定义 vrpn_Thread.h:129
定义 vrpn_Auxiliary_Logger.h:65
Generic connection class not specific to the transport mechanism.
定义 vrpn_Connection.h:562
定义 vrpn_Imager.h:626
定义 vrpn_Imager.h:159
定义 vrpn_Imager_Stream_Buffer.h:594
virtual void mainloop(void)
定义 vrpn_Imager_Stream_Buffer.h:120
定义 vrpn_Imager_Stream_Buffer.h:28
定义 vrpn_Thread.h:63
定义 vrpn_Thread.h:185
This structure is what is passed to a vrpn_Connection message callback.
定义 vrpn_Connection.h:41
定义 vrpn_Imager_Stream_Buffer.h:101
定义 vrpn_Thread.h:175