Browse Source

first pass at new ipc

David Rose 23 năm trước cách đây
mục cha
commit
58b5397d87
87 tập tin đã thay đổi với 2056 bổ sung4854 xóa
  1. 1 1
      panda/metalibs/panda/Sources.pp
  2. 1 1
      panda/src/device/Sources.pp
  3. 5 5
      panda/src/device/clientBase.cxx
  4. 2 2
      panda/src/device/clientBase.h
  5. 2 2
      panda/src/device/clientDevice.I
  6. 2 2
      panda/src/device/clientDevice.h
  7. 2 2
      panda/src/downloader/Sources.pp
  8. 8 8
      panda/src/downloader/asyncUtility.cxx
  9. 2 2
      panda/src/downloader/asyncUtility.h
  10. 4 4
      panda/src/downloader/multiplexStreamBuf.cxx
  11. 2 2
      panda/src/downloader/multiplexStreamBuf.h
  12. 1 3
      panda/src/downloadertools/Sources.pp
  13. 1 1
      panda/src/event/Sources.pp
  14. 1 1
      panda/src/event/eventQueue.cxx
  15. 2 2
      panda/src/event/eventQueue.h
  16. 37 3
      panda/src/express/Sources.pp
  17. 51 0
      panda/src/express/atomicAdjust.I
  18. 19 0
      panda/src/express/atomicAdjust.cxx
  19. 41 0
      panda/src/express/atomicAdjust.h
  20. 53 0
      panda/src/express/atomicAdjustDummyImpl.I
  21. 25 0
      panda/src/express/atomicAdjustDummyImpl.cxx
  22. 45 0
      panda/src/express/atomicAdjustDummyImpl.h
  23. 15 16
      panda/src/express/atomicAdjustImpl.h
  24. 51 0
      panda/src/express/atomicAdjustNsprImpl.I
  25. 25 0
      panda/src/express/atomicAdjustNsprImpl.cxx
  26. 46 0
      panda/src/express/atomicAdjustNsprImpl.h
  27. 1 0
      panda/src/express/config_express.cxx
  28. 1 0
      panda/src/express/config_express.h
  29. 7 0
      panda/src/express/express_composite1.cxx
  30. 3 0
      panda/src/express/express_composite2.cxx
  31. 83 0
      panda/src/express/mutex.I
  32. 4 2
      panda/src/express/mutex.cxx
  33. 51 0
      panda/src/express/mutex.h
  34. 66 0
      panda/src/express/mutexDummyImpl.I
  35. 25 0
      panda/src/express/mutexDummyImpl.cxx
  36. 53 0
      panda/src/express/mutexDummyImpl.h
  37. 85 0
      panda/src/express/mutexHolder.I
  38. 19 0
      panda/src/express/mutexHolder.cxx
  39. 50 0
      panda/src/express/mutexHolder.h
  40. 20 10
      panda/src/express/mutexImpl.h
  41. 59 0
      panda/src/express/mutexNsprImpl.I
  42. 25 0
      panda/src/express/mutexNsprImpl.cxx
  43. 51 0
      panda/src/express/mutexNsprImpl.h
  44. 31 71
      panda/src/express/referenceCount.I
  45. 3 8
      panda/src/express/referenceCount.h
  46. 49 0
      panda/src/express/selectIpcImpl.h
  47. 90 0
      panda/src/express/test_threaddata.cxx
  48. 158 0
      panda/src/express/thread.I
  49. 29 0
      panda/src/express/thread.cxx
  50. 73 0
      panda/src/express/thread.h
  51. 93 0
      panda/src/express/threadDummyImpl.I
  52. 25 0
      panda/src/express/threadDummyImpl.cxx
  53. 64 0
      panda/src/express/threadDummyImpl.h
  54. 37 0
      panda/src/express/threadImpl.h
  55. 74 0
      panda/src/express/threadNsprImpl.I
  56. 196 0
      panda/src/express/threadNsprImpl.cxx
  57. 70 0
      panda/src/express/threadNsprImpl.h
  58. 15 20
      panda/src/express/threadPriority.h
  59. 0 33
      panda/src/ipc/Sources.pp
  60. 0 90
      panda/src/ipc/ipc.cxx
  61. 0 4
      panda/src/ipc/ipc_composite1.cxx
  62. 0 52
      panda/src/ipc/ipc_condition.h
  63. 0 54
      panda/src/ipc/ipc_file.h
  64. 0 297
      panda/src/ipc/ipc_mach_traits.h
  65. 0 53
      panda/src/ipc/ipc_mutex.h
  66. 0 350
      panda/src/ipc/ipc_nspr_traits.h
  67. 0 569
      panda/src/ipc/ipc_nt_traits.h
  68. 0 457
      panda/src/ipc/ipc_posix_traits.h
  69. 0 487
      panda/src/ipc/ipc_ps2_traits.h
  70. 0 57
      panda/src/ipc/ipc_semaphore.h
  71. 0 249
      panda/src/ipc/ipc_solaris_traits.h
  72. 0 281
      panda/src/ipc/ipc_thread.h
  73. 0 268
      panda/src/ipc/ipc_traits.cxx
  74. 0 229
      panda/src/ipc/ipc_traits.h
  75. 0 85
      panda/src/ipc/loom.cxx
  76. 0 74
      panda/src/ipc/loom.h
  77. 0 88
      panda/src/ipc/loom_internal.h
  78. 0 97
      panda/src/ipc/loom_main.cxx
  79. 0 163
      panda/src/ipc/loom_test1.cxx
  80. 0 54
      panda/src/ipc/loom_test2.cxx
  81. 0 152
      panda/src/ipc/test_diners.cxx
  82. 0 81
      panda/src/ipc/test_file.cxx
  83. 0 94
      panda/src/ipc/test_priority.cxx
  84. 0 106
      panda/src/ipc/test_prodcons.cxx
  85. 0 103
      panda/src/ipc/test_thread.cxx
  86. 0 57
      panda/src/ipc/test_threaddata.cxx
  87. 2 2
      panda/src/pgraph/loader.cxx

+ 1 - 1
panda/metalibs/panda/Sources.pp

@@ -22,7 +22,7 @@
 
 
 
-#define LOCAL_LIBS downloader event ipc express pandabase
+#define LOCAL_LIBS downloader event express pandabase
 #define OTHER_LIBS dtoolconfig dtool
 
 #if $[LINK_IN_GL]

+ 1 - 1
panda/src/device/Sources.pp

@@ -4,7 +4,7 @@
 #begin lib_target
   #define TARGET device
   #define LOCAL_LIBS \
-    dgraph display gobj gsgbase ipc mathutil linmath putil
+    dgraph display gobj gsgbase mathutil linmath putil
 
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
 

+ 5 - 5
panda/src/device/clientBase.cxx

@@ -34,7 +34,7 @@ ClientBase() {
   _last_poll_frame = 0;
   _cs = CS_default;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   _client_thread = (thread *)NULL;
   _shutdown = false;
 #endif
@@ -60,7 +60,7 @@ ClientBase::
     }
   }
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   if (_forked) {
     _shutdown = true;
 
@@ -84,7 +84,7 @@ ClientBase::
 ////////////////////////////////////////////////////////////////////
 bool ClientBase::
 fork_asynchronous_thread(double poll_time) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   if (_forked) {
     device_cat.error()
       << "Attempt to fork client thread twice.\n";
@@ -202,7 +202,7 @@ do_poll() {
   _last_poll_time = global_clock->get_frame_time();
 }
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 ////////////////////////////////////////////////////////////////////
 //     Function: ClientBase::st_callback
 //       Access: Private, static
@@ -239,4 +239,4 @@ callback() {
     ipc_traits::sleep(0, _sleep_time);
   }
 }
-#endif // HAVE_IPC
+#endif // OLD_HAVE_IPC

+ 2 - 2
panda/src/device/clientBase.h

@@ -31,7 +31,7 @@
 #include "pointerTo.h"
 #include "coordinateSystem.h"
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #include "ipc_thread.h"
 #endif
 
@@ -87,7 +87,7 @@ private:
   int _last_poll_frame;
   CoordinateSystem _cs;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   int _sleep_time;
   thread *_client_thread;
   bool _shutdown;

+ 2 - 2
panda/src/device/clientDevice.I

@@ -78,7 +78,7 @@ get_device_name() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void ClientDevice::
 lock() {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   _lock.lock();
 #endif
 }
@@ -92,7 +92,7 @@ lock() {
 ////////////////////////////////////////////////////////////////////
 INLINE void ClientDevice::
 unlock() {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   _lock.unlock();
 #endif
 }

+ 2 - 2
panda/src/device/clientDevice.h

@@ -23,7 +23,7 @@
 
 #include <typedReferenceCount.h>
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #include <ipc_mutex.h>
 #endif
 
@@ -64,7 +64,7 @@ private:
   string _device_name;
   bool _is_connected;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex _lock;
 #endif
 

+ 2 - 2
panda/src/downloader/Sources.pp

@@ -1,7 +1,7 @@
-#define LOCAL_LIBS event ipc express pandabase
+#define LOCAL_LIBS event express pandabase
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m
-#define USE_PACKAGES zlib ipc net
+#define USE_PACKAGES zlib net
 
 #begin lib_target
   #define TARGET downloader

+ 8 - 8
panda/src/downloader/asyncUtility.cxx

@@ -43,7 +43,7 @@ AsyncUtility(float frequency) : _frequency(frequency) {
   _threaded = false;
   _threads_enabled = true;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   _request_cond = new condition_variable(_lock);
 #endif
 }
@@ -55,7 +55,7 @@ AsyncUtility(float frequency) : _frequency(frequency) {
 ////////////////////////////////////////////////////////////////////
 AsyncUtility::
 ~AsyncUtility() {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   delete _request_cond;
 #endif
 }
@@ -67,7 +67,7 @@ AsyncUtility::
 ////////////////////////////////////////////////////////////////////
 void AsyncUtility::
 create_thread(void) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   if (_threaded == false && _threads_enabled == true) {
     downloader_cat.debug()
       << "AsyncUtility::create_thread()" << endl;
@@ -84,7 +84,7 @@ create_thread(void) {
 ////////////////////////////////////////////////////////////////////
 void AsyncUtility::
 destroy_thread(void) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   if (_threaded == false)
     return;
 
@@ -116,7 +116,7 @@ destroy_thread(void) {
 ////////////////////////////////////////////////////////////////////
 void* AsyncUtility::
 st_callback(void *arg) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   nassertr(arg != NULL, NULL);
   ((AsyncUtility *)arg)->callback();
 #endif
@@ -131,7 +131,7 @@ st_callback(void *arg) {
 ////////////////////////////////////////////////////////////////////
 void AsyncUtility::
 callback(void) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   while (process_request()) {
     // Sleep until a signal arrives
     _lock.lock();
@@ -148,7 +148,7 @@ callback(void) {
 ////////////////////////////////////////////////////////////////////
 void AsyncUtility::
 nap(void) const {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #ifdef WIN32
   _sleep((DWORD)(1000 * _frequency));
 #else
@@ -157,5 +157,5 @@ nap(void) const {
   tv.tv_usec = (long)(1000000 * _frequency);
   select(0, NULL, NULL, NULL, &tv);
 #endif
-#endif  // HAVE_IPC
+#endif  // OLD_HAVE_IPC
 }

+ 2 - 2
panda/src/downloader/asyncUtility.h

@@ -25,7 +25,7 @@
 #include <notify.h>
 #include <typedef.h>
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #include <ipc_mutex.h>
 #include <ipc_condition.h>
 #include <ipc_thread.h>
@@ -61,7 +61,7 @@ protected:
   float _frequency;
   bool _threads_enabled;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex _lock;
   condition_variable *_request_cond;
   thread *_thread;

+ 4 - 4
panda/src/downloader/multiplexStreamBuf.cxx

@@ -131,7 +131,7 @@ void MultiplexStreamBuf::
 add_output(MultiplexStreamBuf::BufferType buffer_type,
            MultiplexStreamBuf::OutputType output_type,
            ostream *out, FILE *fout, bool owns_obj) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   // Ensure that we have the mutex while we fiddle with the list of
   // outputs.
   mutex_lock m(_lock);
@@ -154,7 +154,7 @@ add_output(MultiplexStreamBuf::BufferType buffer_type,
 ////////////////////////////////////////////////////////////////////
 void MultiplexStreamBuf::
 flush() {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex_lock m(_lock);
 #endif
 
@@ -169,7 +169,7 @@ flush() {
 ////////////////////////////////////////////////////////////////////
 int MultiplexStreamBuf::
 overflow(int ch) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex_lock m(_lock);
 #endif
 
@@ -198,7 +198,7 @@ overflow(int ch) {
 ////////////////////////////////////////////////////////////////////
 int MultiplexStreamBuf::
 sync() {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex_lock m(_lock);
 #endif
 

+ 2 - 2
panda/src/downloader/multiplexStreamBuf.h

@@ -21,7 +21,7 @@
 
 #include <pandabase.h>
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #include <ipc_mutex.h>
 #endif
 
@@ -82,7 +82,7 @@ private:
 
   string _line_buffer;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex _lock;
 #endif
 };

+ 1 - 3
panda/src/downloadertools/Sources.pp

@@ -1,8 +1,6 @@
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m pystub
-#define LOCAL_LIBS downloader express event ipc
-//#define BUILD_DIRECTORY $[HAVE_IPC]
-#define USE_PACKAGES ipc
+#define LOCAL_LIBS downloader express event
 
 #begin bin_target
   #define TARGET apply_patch

+ 1 - 1
panda/src/event/Sources.pp

@@ -1,4 +1,4 @@
-#define LOCAL_LIBS ipc express pandabase
+#define LOCAL_LIBS express pandabase
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m
 

+ 1 - 1
panda/src/event/eventQueue.cxx

@@ -47,7 +47,7 @@ EventQueue::
 ////////////////////////////////////////////////////////////////////
 void EventQueue::
 queue_event(CPT_Event event) {
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex_lock lock(_lock);
 #endif
   if (_queue.full()) {

+ 2 - 2
panda/src/event/eventQueue.h

@@ -26,7 +26,7 @@
 
 #include <circBuffer.h>
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
 #include <ipc_mutex.h>
 #endif
 
@@ -61,7 +61,7 @@ protected:
   static void make_global_event_queue();
   static EventQueue *_global_event_queue;
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
   mutex _lock;
 #endif
 };

+ 37 - 3
panda/src/express/Sources.pp

@@ -9,6 +9,9 @@
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
 
   #define SOURCES \
+    atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I atomicAdjust.h \
+    atomicAdjust.I atomicAdjustImpl.h atomicAdjustNsprImpl.h \
+    atomicAdjustNsprImpl.I \
     bigEndian.h buffer.I buffer.h \
     checksumHashGenerator.I checksumHashGenerator.h circBuffer.I \
     circBuffer.h clockObject.I clockObject.h config_express.h \
@@ -25,7 +28,10 @@
     memoryUsage.I memoryUsage.h \
     memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
     memoryUsagePointers.I memoryUsagePointers.h \
-    multifile.I multifile.h namable.I \
+    multifile.I multifile.h \
+    mutexDummyImpl.h mutexDummyImpl.I mutex.h mutexHolder.h \
+    mutexHolder.I mutex.I mutexImpl.h mutexNsprImpl.h mutexNsprImpl.I \
+    namable.I \
     namable.h nativeNumericData.I nativeNumericData.h \
     numeric_types.h \
     ordered_vector.h ordered_vector.I ordered_vector.T \
@@ -35,8 +41,11 @@
     pta_uchar.h referenceCount.I referenceCount.h \
     register_type.I register_type.h \
     reversedNumericData.I reversedNumericData.h \
+    selectIpcImpl.h \
     streamReader.I streamReader.h streamWriter.I streamWriter.h \
     subStream.I subStream.h subStreamBuf.h \
+    threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
+    threadNsprImpl.h threadNsprImpl.I threadPriority.h \
     tokenBoard.I \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I \
     typeHandle.h typedObject.I typedObject.h \
@@ -56,6 +65,7 @@
        patchfile.cxx patchfile.h ]
 
   #define INCLUDED_SOURCES  \
+    atomicAdjust.cxx atomicAdjustDummyImpl.cxx atomicAdjustNsprImpl.cxx \
     buffer.cxx checksumHashGenerator.cxx clockObject.cxx \
     config_express.cxx datagram.cxx datagramGenerator.cxx \
     datagramIterator.cxx \
@@ -63,7 +73,9 @@
     get_config_path.cxx \
     hashGeneratorBase.cxx hashVal.cxx indent.cxx \
     memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
-    memoryUsagePointers.cxx multifile.cxx namable.cxx \
+    memoryUsagePointers.cxx multifile.cxx \
+    mutex.cxx mutexHolder.cxx mutexDummyImpl.cxx mutexNsprImpl.cxx \
+    namable.cxx \
     nativeNumericData.cxx \
     ordered_vector.cxx \
     profileTimer.cxx \
@@ -71,6 +83,7 @@
     reversedNumericData.cxx \
     streamReader.cxx streamWriter.cxx \
     subStream.cxx subStreamBuf.cxx \
+    thread.cxx threadDummyImpl.cxx threadNsprImpl.cxx \
     trueClock.cxx typeHandle.cxx \
     typedObject.cxx typedReferenceCount.cxx \
     typeRegistry.cxx typeRegistryNode.cxx vector_uchar.cxx \
@@ -81,6 +94,9 @@
     zStream.cxx zStreamBuf.cxx
 
   #define INSTALL_HEADERS  \
+    atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I atomicAdjust.h \
+    atomicAdjust.I atomicAdjustImpl.h atomicAdjustNsprImpl.h \
+    atomicAdjustNsprImpl.I \
     bigEndian.h buffer.I buffer.h checksumHashGenerator.I  \
     checksumHashGenerator.h circBuffer.I circBuffer.h clockObject.I \
     clockObject.h config_express.h datagram.I datagram.h \
@@ -94,7 +110,10 @@
     littleEndian.h memoryInfo.I memoryInfo.h memoryUsage.I \
     memoryUsage.h memoryUsagePointerCounts.I \
     memoryUsagePointerCounts.h memoryUsagePointers.I \
-    memoryUsagePointers.h multifile.I multifile.h namable.I namable.h \
+    memoryUsagePointers.h multifile.I multifile.h \
+    mutexDummyImpl.h mutexDummyImpl.I mutex.h mutexHolder.h \
+    mutexHolder.I mutex.I mutexImpl.h mutexNsprImpl.h mutexNsprImpl.I \
+    namable.I namable.h \
     nativeNumericData.I nativeNumericData.h numeric_types.h \
     ordered_vector.h ordered_vector.I ordered_vector.T \
     patchfile.I patchfile.h pointerTo.I pointerTo.h \
@@ -102,8 +121,11 @@
     profileTimer.h pta_uchar.h referenceCount.I referenceCount.h \
     register_type.I register_type.h \
     reversedNumericData.I reversedNumericData.h \
+    selectIpcImpl.h \
     streamReader.I streamReader.h streamWriter.I streamWriter.h \
     subStream.I subStream.h subStreamBuf.h \
+    threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
+    threadNsprImpl.h threadNsprImpl.I threadPriority.h \
     tokenBoard.I \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h \
     typedObject.I typedObject.h typedReferenceCount.I \
@@ -158,3 +180,15 @@
 
 #end test_bin_target
 #endif
+
+
+#begin test_bin_target
+  #define TARGET test_threaddata
+  #define LOCAL_LIBS $[LOCAL_LIBS] express
+  #define OTHER_LIBS dtoolutil:c dtool:m pystub
+
+  #define SOURCES \
+    test_threaddata.cxx
+
+#end test_bin_target
+

+ 51 - 0
panda/src/express/atomicAdjust.I

@@ -0,0 +1,51 @@
+// Filename: atomicAdjust.I
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjust::inc
+//       Access: Public, Static
+//  Description: Atomically increments the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjust::
+inc(int &var) {
+  return AtomicAdjustImpl::inc(var);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjust::dec
+//       Access: Public, Static
+//  Description: Atomically decrements the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjust::
+dec(int &var) {
+  return AtomicAdjustImpl::dec(var);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjust::set
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjust::
+set(int &var, int new_value) {
+  return AtomicAdjustImpl::set(var, new_value);
+}

+ 19 - 0
panda/src/express/atomicAdjust.cxx

@@ -0,0 +1,19 @@
+// Filename: atomicAdjust.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "atomicAdjust.h"

+ 41 - 0
panda/src/express/atomicAdjust.h

@@ -0,0 +1,41 @@
+// Filename: atomicAdjust.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ATOMICADJUST_H
+#define ATOMICADJUST_H
+
+#include "pandabase.h"
+#include "atomicAdjustImpl.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : AtomicAdjust
+// Description : A suite of functions to atomically adjust a numeric
+//               value.  Some platforms require a bit more work than
+//               others to guarantee that a multibyte value is changed
+//               in one atomic operation.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA AtomicAdjust {
+public:
+  INLINE static int inc(int &var);
+  INLINE static int dec(int &var);
+  INLINE static int set(int &var, int new_value);
+};
+
+#include "atomicAdjust.I"
+
+#endif

+ 53 - 0
panda/src/express/atomicAdjustDummyImpl.I

@@ -0,0 +1,53 @@
+// Filename: atomicAdjustDummyImpl.I
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustDummyImpl::inc
+//       Access: Public, Static
+//  Description: Atomically increments the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustDummyImpl::
+inc(int &var) {
+  return ++var;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustDummyImpl::dec
+//       Access: Public, Static
+//  Description: Atomically decrements the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustDummyImpl::
+dec(int &var) {
+  return --var;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustDummyImpl::set
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustDummyImpl::
+set(int &var, int new_value) {
+  int orig_value = var;
+  var = new_value;
+  return orig_value;
+}

+ 25 - 0
panda/src/express/atomicAdjustDummyImpl.cxx

@@ -0,0 +1,25 @@
+// Filename: atomicAdjustDummyImpl.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+
+#include "atomicAdjustDummyImpl.h"
+
+#endif  // IPC_DUMMY_IMPL

+ 45 - 0
panda/src/express/atomicAdjustDummyImpl.h

@@ -0,0 +1,45 @@
+// Filename: atomicAdjustDummyImpl.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ATOMICADJUSTDUMMYIMPL_H
+#define ATOMICADJUSTDUMMYIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : AtomicAdjustDummyImpl
+// Description : A trivial implementation for atomic adjustments for
+//               systems that don't require multiprogramming, and
+//               therefore don't require special atomic operations.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA AtomicAdjustDummyImpl {
+public:
+  INLINE static int inc(int &var);
+  INLINE static int dec(int &var);
+  INLINE static int set(int &var, int new_value);
+};
+
+#include "atomicAdjustDummyImpl.I"
+
+#endif  // IPC_DUMMY_IMPL
+
+#endif

+ 15 - 16
panda/src/ipc/ipc_atomics.h → panda/src/express/atomicAdjustImpl.h

@@ -1,5 +1,5 @@
-// Filename: ipc_atomics.h
-// Created by:  frang (10Feb00)
+// Filename: atomicAdjustImpl.h
+// Created by:  drose (09Aug02)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -16,23 +16,22 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef __IPC_ATOMICS_H__
-#define __IPC_ATOMICS_H__
+#ifndef ATOMICADJUSTIMPL_H
+#define ATOMICADJUSTIMPL_H
 
-#include <pandabase.h>
+#include "pandabase.h"
+#include "selectIpcImpl.h"
 
-#include "ipc_traits.h"
+#if defined(IPC_DUMMY_IMPL)
 
-INLINE int set_atomic(int& var, int val) {
-  return ipc_traits::set_atomic(var, val);
-}
+#include "atomicAdjustDummyImpl.h"
+typedef AtomicAdjustDummyImpl AtomicAdjustImpl;
 
-INLINE int inc_atomic(int& var) {
-  return ipc_traits::inc_atomic(var);
-}
+#elif defined(IPC_NSPR_IMPL)
 
-INLINE int dec_atomic(int& var) {
-  return ipc_traits::dec_atomic(var);
-}
+#include "atomicAdjustNsprImpl.h"
+typedef AtomicAdjustNsprImpl AtomicAdjustImpl;
 
-#endif /* __IPC_ATOMICS_H__ */
+#endif
+
+#endif

+ 51 - 0
panda/src/express/atomicAdjustNsprImpl.I

@@ -0,0 +1,51 @@
+// Filename: atomicAdjustNsprImpl.I
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustNsprImpl::inc
+//       Access: Public, Static
+//  Description: Atomically increments the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustNsprImpl::
+inc(int &var) {
+  return PR_AtomicIncrement(&var);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustNsprImpl::dec
+//       Access: Public, Static
+//  Description: Atomically decrements the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustNsprImpl::
+dec(int &var) {
+  return PR_AtomicDecrement(&var);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustNsprImpl::set
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE int AtomicAdjustNsprImpl::
+set(int &var, int new_value) {
+  return PR_AtomicSet(&var, new_value);
+}

+ 25 - 0
panda/src/express/atomicAdjustNsprImpl.cxx

@@ -0,0 +1,25 @@
+// Filename: atomicAdjustNsprImpl.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "atomicAdjustNsprImpl.h"
+
+#endif  // IPC_NSPR_IMPL

+ 46 - 0
panda/src/express/atomicAdjustNsprImpl.h

@@ -0,0 +1,46 @@
+// Filename: atomicAdjustNsprImpl.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ATOMICADJUSTNSPRIMPL_H
+#define ATOMICADJUSTNSPRIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "notify.h"
+
+#include <pratom.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : AtomicAdjustNsprImpl
+// Description : Uses NSPR to implement atomic adjustments.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA AtomicAdjustNsprImpl {
+public:
+  INLINE static int inc(int &var);
+  INLINE static int dec(int &var);
+  INLINE static int set(int &var, int new_value);
+};
+
+#include "atomicAdjustNsprImpl.I"
+
+#endif  // IPC_NSPR_IMPL
+
+#endif

+ 1 - 0
panda/src/express/config_express.cxx

@@ -33,6 +33,7 @@
 
 ConfigureDef(config_express);
 NotifyCategoryDef(express, "");
+NotifyCategoryDef(ipc, "");
 
 extern void init_system_type_handles();
 

+ 1 - 0
panda/src/express/config_express.h

@@ -25,6 +25,7 @@
 
 ConfigureDecl(config_express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
 NotifyCategoryDecl(express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
+NotifyCategoryDecl(ipc, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
 
 // Actually, we can't determine this config variable the normal way,
 // because we must be able to access it at static init time.  Instead

+ 7 - 0
panda/src/express/express_composite1.cxx

@@ -1,3 +1,6 @@
+#include "atomicAdjust.cxx"
+#include "atomicAdjustDummyImpl.cxx"
+#include "atomicAdjustNsprImpl.cxx"
 #include "buffer.cxx"
 #include "checksumHashGenerator.cxx"
 #include "clockObject.cxx"
@@ -17,6 +20,10 @@
 #include "memoryUsagePointerCounts.cxx"
 #include "memoryUsagePointers.cxx"
 #include "multifile.cxx"
+#include "mutex.cxx"
+#include "mutexHolder.cxx"
+#include "mutexDummyImpl.cxx"
+#include "mutexNsprImpl.cxx"
 #include "namable.cxx"
 #include "nativeNumericData.cxx"
 #include "ordered_vector.cxx"

+ 3 - 0
panda/src/express/express_composite2.cxx

@@ -4,6 +4,9 @@
 #include "streamWriter.cxx"
 #include "subStream.cxx"
 #include "subStreamBuf.cxx"
+#include "thread.cxx"
+#include "threadDummyImpl.cxx"
+#include "threadNsprImpl.cxx"
 #include "trueClock.cxx"
 #include "typeHandle.cxx"
 #include "typedObject.cxx"

+ 83 - 0
panda/src/express/mutex.I

@@ -0,0 +1,83 @@
+// Filename: mutex.I
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Mutex::
+Mutex() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Mutex::
+~Mutex() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::Copy Constructor
+//       Access: Private
+//  Description: Do not attempt to copy mutexes.
+////////////////////////////////////////////////////////////////////
+INLINE Mutex::
+Mutex(const Mutex &copy) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::Copy Assignment Operator
+//       Access: Private
+//  Description: Do not attempt to copy mutexes.
+////////////////////////////////////////////////////////////////////
+INLINE void Mutex::
+operator = (const Mutex &copy) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::lock
+//       Access: Public
+//  Description: Grabs the mutex if it is available.  If it is not
+//               available, blocks until it becomes available, then
+//               grabs it.  In either case, the function does not
+//               return until the mutex is held; you should then call
+//               unlock().
+//
+//               Also see MutexHolder.
+////////////////////////////////////////////////////////////////////
+INLINE void Mutex::
+lock() {
+  _impl.lock();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Mutex::release
+//       Access: Public
+//  Description: Releases the mutex.  It is an error to call this if
+//               the mutex was not already locked.
+////////////////////////////////////////////////////////////////////
+INLINE void Mutex::
+release() {
+  _impl.release();
+}

+ 4 - 2
panda/src/ipc/ipc_file.I → panda/src/express/mutex.cxx

@@ -1,5 +1,5 @@
-// Filename: ipc_file.I
-// Created by:  jason (07Jun00)
+// Filename: mutex.cxx
+// Created by:  drose (08Aug02)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -15,3 +15,5 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
+
+#include "mutex.h"

+ 51 - 0
panda/src/express/mutex.h

@@ -0,0 +1,51 @@
+// Filename: mutex.h
+// Created by:  cary (16Sep98)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MUTEX_H
+#define MUTEX_H
+
+#include "pandabase.h"
+#include "mutexImpl.h"
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Mutex
+// Description : A standard mutex, or mutual exclusion lock.  Only one
+//               thread can hold ("lock") a mutex at any given time;
+//               other threads trying to grab the mutex will block
+//               until the holding thread releases it.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA Mutex {
+public:
+  INLINE Mutex();
+  INLINE ~Mutex();
+private:
+  INLINE Mutex(const Mutex &copy);
+  INLINE void operator = (const Mutex &copy);
+
+public:
+  INLINE void lock();
+  INLINE void release();
+
+private:
+  MutexImpl _impl;
+};
+
+#include "mutex.I"
+
+#endif

+ 66 - 0
panda/src/express/mutexDummyImpl.I

@@ -0,0 +1,66 @@
+// Filename: mutexDummyImpl.I
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDummyImpl::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexDummyImpl::
+MutexDummyImpl() {
+#ifndef NDEBUG
+  _lock_count = 0;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDummyImpl::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexDummyImpl::
+~MutexDummyImpl() {
+  nassertv(_lock_count == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDummyImpl::lock
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexDummyImpl::
+lock() {
+#ifndef NDEBUG
+  _lock_count++;
+  nassertv(_lock_count == 1);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDummyImpl::release
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexDummyImpl::
+release() {
+#ifndef NDEBUG
+  _lock_count--;
+  nassertv(_lock_count == 0);
+#endif
+}

+ 25 - 0
panda/src/express/mutexDummyImpl.cxx

@@ -0,0 +1,25 @@
+// Filename: mutexDummyImpl.cxx
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+
+#include "mutexDummyImpl.h"
+
+#endif  // IPC_DUMMY_IMPL

+ 53 - 0
panda/src/express/mutexDummyImpl.h

@@ -0,0 +1,53 @@
+// Filename: mutexDummyImpl.h
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MUTEXDUMMYIMPL_H
+#define MUTEXDUMMYIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : MutexDummyImpl
+// Description : A fake mutex implementation for single-threaded
+//               applications that don't need any synchronization
+//               control.  This does nothing but assert that the same
+//               process does not try to grab the mutex twice.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA MutexDummyImpl {
+public:
+  INLINE MutexDummyImpl();
+  INLINE ~MutexDummyImpl();
+
+  INLINE void lock();
+  INLINE void release();
+
+private:
+#ifndef NDEBUG
+  int _lock_count;
+#endif
+};
+
+#include "mutexDummyImpl.I"
+
+#endif  // IPC_DUMMY_IMPL
+
+#endif

+ 85 - 0
panda/src/express/mutexHolder.I

@@ -0,0 +1,85 @@
+// Filename: mutexHolder.I
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexHolder::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexHolder::
+MutexHolder(Mutex &mutex) {
+#ifdef HAVE_IPC
+  _mutex = &mutex;
+  _mutex->lock();
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexHolder::Constructor
+//       Access: Public
+//  Description: If the MutexHolder constructor is given a pointer to
+//               a Mutex object (instead of an actual object), it will
+//               first check to see if the pointer is NULL, and
+//               allocate a new Mutex if it is.  This is intended as a
+//               convenience for functions that may need to reference
+//               a Mutex at static init time, when it is impossible to
+//               guarantee ordering of initializers.
+////////////////////////////////////////////////////////////////////
+INLINE MutexHolder::
+MutexHolder(Mutex *&mutex) {
+#ifdef HAVE_IPC
+  if (mutex == (Mutex *)NULL) {
+    mutex = new Mutex;
+  }
+  _mutex = mutex;
+  _mutex->lock();
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexHolder::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexHolder::
+~MutexHolder() {
+#ifdef HAVE_IPC
+  _mutex->release();
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexHolder::Copy Constructor
+//       Access: Private
+//  Description: Do not attempt to copy MutexHolders.
+////////////////////////////////////////////////////////////////////
+INLINE MutexHolder::
+MutexHolder(const MutexHolder &copy) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexHolder::Copy Assignment Operator
+//       Access: Private
+//  Description: Do not attempt to copy MutexHolders.
+////////////////////////////////////////////////////////////////////
+INLINE void MutexHolder::
+operator = (const MutexHolder &copy) {
+  nassertv(false);
+}

+ 19 - 0
panda/src/express/mutexHolder.cxx

@@ -0,0 +1,19 @@
+// Filename: mutexHolder.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "mutexHolder.h"

+ 50 - 0
panda/src/express/mutexHolder.h

@@ -0,0 +1,50 @@
+// Filename: mutexHolder.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MUTEXHOLDER_H
+#define MUTEXHOLDER_H
+
+#include "pandabase.h"
+#include "mutex.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : MutexHolder
+// Description : A lightweight C++ object whose constructor calls
+//               lock() and whose destructor calls release() on a
+//               mutex.  It is a C++ convenience wrapper to call
+//               release() automatically when a block exits (for
+//               instance, on return).
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA MutexHolder {
+public:
+  INLINE MutexHolder(Mutex &mutex);
+  INLINE MutexHolder(Mutex *&mutex);
+  INLINE ~MutexHolder();
+private:
+  INLINE MutexHolder(const MutexHolder &copy);
+  INLINE void operator = (const MutexHolder &copy);
+
+private:
+#ifdef HAVE_IPC
+  Mutex *_mutex;
+#endif
+};
+
+#include "mutexHolder.I"
+
+#endif

+ 20 - 10
panda/src/ipc/ipc_nt_traits.cxx → panda/src/express/mutexImpl.h

@@ -1,5 +1,5 @@
-// Filename: ipc_nt_traits.cxx
-// Created by:  mike (23Oct98)
+// Filename: mutexImpl.h
+// Created by:  drose (08Aug02)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -16,15 +16,25 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifdef WIN32_VC
+#ifndef MUTEXIMPL_H
+#define MUTEXIMPL_H
 
-#include "ipc_nt_traits.h"
+#include "pandabase.h"
+#include "selectIpcImpl.h"
 
-const int ipc_traits::days_in_preceeding_months[12] = { 0, 31, 59, 90,
-                                                120, 151, 181, 212,
-                                                243, 273, 304, 334 };
-const int ipc_traits::days_in_preceeding_months_leap[12] = { 0, 31, 60,
-                                                91, 121, 152, 182, 213,
-                                                244, 274, 305, 335 };
+#if defined(IPC_DUMMY_IMPL)
+
+#include "mutexDummyImpl.h"
+typedef MutexDummyImpl MutexImpl;
+
+#elif defined(IPC_NSPR_IMPL)
+
+#include "mutexNsprImpl.h"
+typedef MutexNsprImpl MutexImpl;
+
+#endif
 
 #endif
+
+
+

+ 59 - 0
panda/src/express/mutexNsprImpl.I

@@ -0,0 +1,59 @@
+// Filename: mutexNsprImpl.I
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexNsprImpl::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexNsprImpl::
+MutexNsprImpl() {
+  _lock = PR_NewLock();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexNsprImpl::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexNsprImpl::
+~MutexNsprImpl() {
+  PR_DestroyLock(_lock);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexNsprImpl::lock
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexNsprImpl::
+lock() {
+  PR_Lock(_lock);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexNsprImpl::release
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexNsprImpl::
+release() {
+  int status = PR_Unlock(_lock);
+  nassertv(status == PR_SUCCESS);
+}

+ 25 - 0
panda/src/express/mutexNsprImpl.cxx

@@ -0,0 +1,25 @@
+// Filename: mutexNsprImpl.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "mutexNsprImpl.h"
+
+#endif  // IPC_NSPR_IMPL

+ 51 - 0
panda/src/express/mutexNsprImpl.h

@@ -0,0 +1,51 @@
+// Filename: mutexNsprImpl.h
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MUTEXNSPRIMPL_H
+#define MUTEXNSPRIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "notify.h"
+
+#include <prlock.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : MutexNsprImpl
+// Description : Uses NSPR to implement a mutex.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA MutexNsprImpl {
+public:
+  INLINE MutexNsprImpl();
+  INLINE ~MutexNsprImpl();
+
+  INLINE void lock();
+  INLINE void release();
+
+private:
+  PRLock *_lock;
+};
+
+#include "mutexNsprImpl.I"
+
+#endif  // IPC_NSPR_IMPL
+
+#endif

+ 31 - 71
panda/src/express/referenceCount.I

@@ -94,25 +94,6 @@ operator = (const ReferenceCount &) {
 ////////////////////////////////////////////////////////////////////
 INLINE ReferenceCount::
 ~ReferenceCount() {
-  prepare_delete();
-#ifdef DO_MEMORY_USAGE
-  MemoryUsage::remove_pointer(this);
-#endif
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ReferenceCount::prepare_delete
-//       Access: Public
-//  Description: This function is called by the ReferenceCount
-//               destructor to check on all of the numbers and make
-//               sure it's all right to delete the object.  Normally
-//               it will never be called explicitly elsewhere, except
-//               maybe in unref_delete() to simulate deleting the node
-//               without actually deleting it, when we want to test
-//               ref count integrities.
-////////////////////////////////////////////////////////////////////
-INLINE void ReferenceCount::
-prepare_delete() {
   nassertv(this != NULL);
 
   // If this assertion fails, we're trying to delete an object that
@@ -138,28 +119,16 @@ prepare_delete() {
   // all--onto a locally allocated one.
   nassertv(_ref_count == 0);
 
+#ifndef NDEBUG
   // Ok, all clear to delete.  Now set the reference count to -100,
   // so we'll have a better chance of noticing if we happen to have
   // a stray pointer to it still out there.
   _ref_count = -100;
-}
+#endif
 
-////////////////////////////////////////////////////////////////////
-//     Function: ReferenceCount::unref_consider_delete
-//       Access: Public
-//  Description: This function is called by the global unref_delete()
-//               function.  This function unrefs the pointer and
-//               returns true if it should be deleted (i.e. the count
-//               has gone to zero), or false otherwise.  It doesn't
-//               delete itself because (a) a method cannot safely
-//               delete this, and (b) we don't have a virtual
-//               destructor anyway.  The decision of whether to delete
-//               is left up to unref_delete().
-////////////////////////////////////////////////////////////////////
-INLINE bool ReferenceCount::
-unref_consider_delete() {
-  unref();
-  return (get_ref_count() == 0);
+#ifdef DO_MEMORY_USAGE
+  MemoryUsage::remove_pointer(this);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -169,9 +138,9 @@ unref_consider_delete() {
 ////////////////////////////////////////////////////////////////////
 INLINE int ReferenceCount::
 get_ref_count() const {
- #ifndef NDEBUG
+#ifndef NDEBUG
   test_ref_count_integrity();
- #endif
+#endif
   return _ref_count;
 }
 
@@ -190,10 +159,12 @@ get_ref_count() const {
 //               with the object.  An object might be const in other
 //               ways, but we still need to accurately count the
 //               number of references to it.
+//
+//               The return value is the new reference count.
 ////////////////////////////////////////////////////////////////////
-INLINE void ReferenceCount::
+INLINE int ReferenceCount::
 ref() const {
-  nassertv(this != NULL);
+  nassertr(this != NULL, 0);
 
   // If this assertion fails, we're trying to ref a pointer that was
   // just deleted.  Probably you used a real pointer instead of a
@@ -201,30 +172,14 @@ ref() const {
   // PointerTo went out of scope.  Either that, or you forgot to
   // define a copy constructor for a class that contains
   // PointerTo's.
-  nassertv(_ref_count != -100);
+  nassertr(_ref_count != -100, 0);
 
   // If this assertion fails, the reference counts are all screwed
   // up altogether.  Maybe some errant code stomped all over memory
   // somewhere.
-  nassertv(_ref_count >= 0);
-
-#if 0
-  // This is an SGI-specific hack.  Maybe this isn't a valid test at
-  // all.  This is supposed to fail if the 'this' pointer is on the
-  // stack, instead of on the heap--I assume if the first two hex
-  // digits of the pointer of 0x7f it's on the stack, possibly a bad
-  // assumption.  In any case, if you ref-count a pointer on the
-  // stack, you just goofed.  Don't assign a PointerTo to refer to
-  // any local variables!
-  nassertv(((long)this & 0xff000000) != 0x7f000000);
-#endif
+  nassertr(_ref_count >= 0, 0);
 
-  ((ReferenceCount *)this)->_ref_count++;
-
-  // If this assertion fails, we have just wrapped!  Either there
-  // are actually 2^32 pointers to this thing somewhere, or
-  // something is really screwy.
-  nassertv(_ref_count > 0);
+  return AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -233,7 +188,10 @@ ref() const {
 //  Description: Explicitly decrements the reference count.  Note that
 //               the object will not be implicitly deleted by unref()
 //               simply because the reference count drops to zero.
-//               However, see the helper function unref_delete().
+//               (Having a member function delete itself is
+//               problematic; plus, we don't have a virtual destructor
+//               anyway.) However, see the helper function
+//               unref_delete().
 //
 //               User code should avoid using ref() and unref()
 //               directly, which can result in missed reference
@@ -246,10 +204,12 @@ ref() const {
 //               with the object.  An object might be const in other
 //               ways, but we still need to accurately count the
 //               number of references to it.
+//
+//               The return value is the new reference count.
 ////////////////////////////////////////////////////////////////////
-INLINE void ReferenceCount::
+INLINE int ReferenceCount::
 unref() const {
-  nassertv(this != NULL);
+  nassertr(this != NULL, false);
 
   // If this assertion fails, we're trying to unref a pointer that
   // was just deleted.  Probably you used a real pointer instead of
@@ -257,18 +217,18 @@ unref() const {
   // PointerTo went out of scope.  Either that, or you forgot to
   // define a copy constructor for a class that contains
   // PointerTo's.
-  nassertv(_ref_count != -100);
+  nassertr(_ref_count != -100, false);
 
   // If this assertion fails, the reference counts are all screwed
   // up altogether.  Maybe some errant code stomped all over memory
   // somewhere.
-  nassertv(_ref_count >= 0);
+  nassertr(_ref_count >= 0, false);
 
   // If this assertion fails, you tried to unref an object with a
   // zero reference count.  Are you using ref() and unref()
   // directly?  Are you sure you can't use PointerTo's?
-  nassertv(_ref_count > 0);
-  ((ReferenceCount *)this)->_ref_count--;
+  nassertr(_ref_count > 0, false);
+  return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
 }
 
 
@@ -280,7 +240,7 @@ unref() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void ReferenceCount::
 test_ref_count_integrity() const {
- #ifndef NDEBUG
+#ifndef NDEBUG
   nassertv(this != NULL);
 
   // If this assertion fails, we're trying to access a pointer that
@@ -295,7 +255,7 @@ test_ref_count_integrity() const {
   // up altogether.  Maybe some errant code stomped all over memory
   // somewhere.
   nassertv(_ref_count >= 0);
- #endif
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -311,7 +271,7 @@ test_ref_count_integrity() const {
 template<class RefCountType>
 INLINE void
 unref_delete(RefCountType *ptr) {
-  if (((ReferenceCount *)ptr)->unref_consider_delete()) {
+  if (((ReferenceCount *)ptr)->unref() == 0) {
 #ifndef NDEBUG
     if (get_leak_memory()) {
       // In leak-memory mode, we don't actually delete the pointer,
@@ -319,9 +279,9 @@ unref_delete(RefCountType *ptr) {
       // exactly the same effect as deleting it, without actually
       // freeing up the memory it uses.
 
+      // Furthermore, if we have never-destruct set, we don't even
+      // call the destructor.
       if (!get_never_destruct()) {
-        // Furthermore, if we have never-destruct set, we don't even
-        // call the destructor.
         ptr->~RefCountType();
       }
       return;

+ 3 - 8
panda/src/express/referenceCount.h

@@ -24,6 +24,7 @@
 #include "typedObject.h"
 #include "memoryUsage.h"
 #include "config_express.h"
+#include "atomicAdjust.h"
 
 #include <stdlib.h>
 
@@ -45,16 +46,10 @@ protected:
   INLINE void operator = (const ReferenceCount &);
   INLINE ~ReferenceCount();
 
-public:
-  // These functions are not part of the normal API, but they have to
-  // be public.  You shouldn't generally call these directly.
-  INLINE void prepare_delete();
-  INLINE bool unref_consider_delete();
-
 PUBLISHED:
   INLINE int get_ref_count() const;
-  INLINE void ref() const;
-  INLINE void unref() const;
+  INLINE int ref() const;
+  INLINE int unref() const;
 
   INLINE void test_ref_count_integrity() const;
 

+ 49 - 0
panda/src/express/selectIpcImpl.h

@@ -0,0 +1,49 @@
+// Filename: selectIpcImpl.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SELECTIPCIMPL_H
+#define SELECTIPCIMPL_H
+
+#include "pandabase.h"
+
+////////////////////////////////////////////////////////////////////
+// This file decides which of the core implementations of the various
+// ipc (actually, threading) implementations we should use, based on
+// platform and/or available libraries.
+////////////////////////////////////////////////////////////////////
+
+#if !defined(HAVE_IPC)
+
+// With IPC disabled, use the do-nothing implementation.
+#define IPC_DUMMY_IMPL 1
+
+#elif defined(HAVE_NSPR)
+
+// If NSPR is available, use that.
+#define IPC_NSPR_IMPL 1
+
+#else
+
+// This is a configuration error.  For some reason, HAVE_IPC is
+// defined but we don't have any way to implement it.
+#error No ipc implementation defined for platform.
+
+#endif
+
+
+#endif

+ 90 - 0
panda/src/express/test_threaddata.cxx

@@ -0,0 +1,90 @@
+// Filename: test_threaddata.cxx
+// Created by:  cary (16Sep98)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandabase.h"
+#include "thread.h"
+#include "mutex.h"
+#include "mutexHolder.h"
+#include "pointerTo.h"
+
+Mutex *cout_mutex = (Mutex *)NULL;
+
+// Test forking a thread with some private data.
+class ThreadWithData : public Thread {
+public:
+  ThreadWithData(const string &name, int parameter);
+
+  virtual void thread_main();
+
+private:
+  int _parameter;
+};
+
+
+ThreadWithData::
+ThreadWithData(const string &name, int parameter) : 
+  Thread(name),
+  _parameter(parameter)
+{
+  MutexHolder holder(cout_mutex);
+  cout << "Creating thread " << get_name() << " with parameter " << _parameter
+       << "\n";
+}
+
+void ThreadWithData::
+thread_main() {
+  for (int i = 0; i < _parameter; i++) {
+    {
+      MutexHolder holder(cout_mutex);
+      cout << "Running thread " << get_name()
+           << " with parameter " << _parameter
+           << ", i = " << i << "\n" << flush;
+      Thread *thread = get_current_thread();
+      nassertv(thread == this);
+    }
+    Thread::sleep((double) i / 10.0);
+  }
+}
+
+int
+main() {
+  cout << "main beginning.\n";
+  for (int i = 0; i < 10; i++) {
+    string name = string("thread_") + (char)(i + 'a');
+    PT(Thread) thread = new ThreadWithData(name, i);
+    if (!thread->start(TP_low, false, false)) {
+      MutexHolder holder(cout_mutex);
+      cout << "Unable to start " << name << ".\n";
+    } else {
+      MutexHolder holder(cout_mutex);
+      cout << "Started " << name << ", count = " 
+           << thread->get_ref_count() << "\n";
+    }
+  }
+
+  {
+    MutexHolder holder(cout_mutex);
+    cout << "main preparing to exit.\n";
+  }
+
+  Thread::prepare_for_exit();
+
+  cout << "main exiting.\n";
+
+  return 0;
+}

+ 158 - 0
panda/src/express/thread.I

@@ -0,0 +1,158 @@
+// Filename: thread.I
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::Constructor
+//       Access: Public
+//  Description: Creates a new Thread object, but does not
+//               immediately start executing it.  This gives the
+//               caller a chance to store it in a PT(Thread) object,
+//               if desired, before the thread gets a chance to
+//               terminate and destruct itself.
+//
+//               Call start() to begin thread execution.
+////////////////////////////////////////////////////////////////////
+INLINE Thread::
+Thread(const string &name) : _name(name), _impl(this) {
+  _started = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::Copy Constructor
+//       Access: Private
+//  Description: Do not attempt to copy threads.
+////////////////////////////////////////////////////////////////////
+INLINE Thread::
+Thread(const Thread &copy) : _impl(this) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::Copy Assignment Operator
+//       Access: Private
+//  Description: Do not attempt to copy threads.
+////////////////////////////////////////////////////////////////////
+INLINE void Thread::
+operator = (const Thread &copy) {
+  nassertv(false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::get_name
+//       Access: Public
+//  Description: Returns the name of the thread.
+////////////////////////////////////////////////////////////////////
+INLINE const string &Thread::
+get_name() const {
+  return _name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::start
+//       Access: Public
+//  Description: Starts the thread executing.  It is only valid to
+//               call this once.
+//
+//               The thread will begin executing its thread_main()
+//               function, and will terminate when thread_main()
+//               returns.
+//
+//               priority is intended as a hint to the relative
+//               importance of this thread, and global should be set
+//               true if the thread will perform a lot of blocking
+//               I/O, or false otherwise (see the NSPR documentation
+//               on global vs. local threads for more on this).  Both
+//               of these parameters may be ignored by the thread
+//               implementation.
+//
+//               joinable should be set true if you intend to call
+//               join() to wait for the thread to terminate, or false
+//               if you don't care and you will never call join().
+//
+//               The return value is true if the thread is
+//               successfully started, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Thread::
+start(ThreadPriority priority, bool global, bool joinable) {
+  nassertr(!_started, false);
+  _started = _impl.start(priority, global, joinable);
+  return _started;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::join
+//       Access: Public
+//  Description: Blocks the calling process until the thread
+//               terminates.  If the thread has already terminated,
+//               this returns immediately.
+////////////////////////////////////////////////////////////////////
+INLINE void Thread::
+join() {
+  _impl.join();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::prepare_for_exit
+//       Access: Public
+//  Description: Should be called by the main thread just before
+//               exiting the program, this blocks until any remaining
+//               thread cleanup has finished.
+////////////////////////////////////////////////////////////////////
+INLINE void Thread::
+prepare_for_exit() {
+  ThreadImpl::prepare_for_exit();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::get_current_thread
+//       Access: Public, Static
+//  Description: Returns a pointer to the currently-executing Thread
+//               object, or NULL if the main thread (or some system
+//               thread other than one started from the Panda
+//               interface) is currently executing.
+////////////////////////////////////////////////////////////////////
+INLINE Thread *Thread::
+get_current_thread() {
+  return ThreadImpl::get_current_thread();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::is_threading_supported
+//       Access: Public, Static
+//  Description: Returns true if a real threading library is available
+//               that supports threads, or false if no threading
+//               library is available (and Thread::start() will always
+//               fail).
+////////////////////////////////////////////////////////////////////
+INLINE bool Thread::
+is_threading_supported() {
+  return ThreadImpl::is_threading_supported();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::sleep
+//       Access: Public, Static
+//  Description: Suspends the current thread for at least the
+//               indicated amount of time.  It might be suspended for
+//               longer.
+////////////////////////////////////////////////////////////////////
+INLINE void Thread::
+sleep(double seconds) {
+  ThreadImpl::sleep(seconds);
+}

+ 29 - 0
panda/src/express/thread.cxx

@@ -0,0 +1,29 @@
+// Filename: thread.cxx
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "thread.h"
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+Thread::
+~Thread() {
+}

+ 73 - 0
panda/src/express/thread.h

@@ -0,0 +1,73 @@
+// Filename: thread.h
+// Created by:  cary (16Sep98)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef THREAD_H
+#define THREAD_H
+
+#include "pandabase.h"
+#include "referenceCount.h"
+#include "threadPriority.h"
+#include "threadImpl.h"
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Thread
+// Description : A thread; that is, a lightweight process.  This is an
+//               abstract base class; to use it, you must subclass
+//               from it and redefine thread_main().
+//
+//               The thread itself will keep a reference count on the
+//               Thread object while it is running; when the thread
+//               returns from its root function, the Thread object
+//               will automatically be destructed if no other pointers
+//               are referencing it.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA Thread : public ReferenceCount {
+public:
+  INLINE Thread(const string &name);
+  virtual ~Thread();
+
+private:
+  INLINE Thread(const Thread &copy);
+  INLINE void operator = (const Thread &copy);
+
+protected:
+  virtual void thread_main()=0;
+
+public:
+  INLINE const string &get_name() const;
+
+  INLINE bool start(ThreadPriority priority, bool global, bool joinable);
+  INLINE void join();
+
+  INLINE static void prepare_for_exit();
+
+  INLINE static Thread *get_current_thread();
+  INLINE static bool is_threading_supported();
+  INLINE static void sleep(double seconds);
+
+private:
+  bool _started;
+  string _name;
+  ThreadImpl _impl;
+  friend ThreadImpl;
+};
+
+#include "thread.I"
+
+#endif

+ 93 - 0
panda/src/express/threadDummyImpl.I

@@ -0,0 +1,93 @@
+// Filename: threadDummyImpl.I
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ThreadDummyImpl::
+ThreadDummyImpl(Thread *) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ThreadDummyImpl::
+~ThreadDummyImpl() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::start
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool ThreadDummyImpl::
+start(ThreadPriority, bool, bool) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::join
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadDummyImpl::
+join() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::prepare_for_exit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadDummyImpl::
+prepare_for_exit() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE Thread *ThreadDummyImpl::
+get_current_thread() {
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::is_threading_supported
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool ThreadDummyImpl::
+is_threading_supported() {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadDummyImpl::sleep
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadDummyImpl::
+sleep(double) {
+}

+ 25 - 0
panda/src/express/threadDummyImpl.cxx

@@ -0,0 +1,25 @@
+// Filename: threadDummyImpl.cxx
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+
+#include "threadDummyImpl.h"
+
+#endif  // IPC_DUMMY_IMPL

+ 64 - 0
panda/src/express/threadDummyImpl.h

@@ -0,0 +1,64 @@
+// Filename: threadDummyImpl.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef THREADDUMMYIMPL_H
+#define THREADDUMMYIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_DUMMY_IMPL
+
+#include "notify.h"
+#include "threadPriority.h"
+#include "mutex.h"
+
+#include <prthread.h>
+
+class Thread;
+
+////////////////////////////////////////////////////////////////////
+//       Class : ThreadDummyImpl
+// Description : A fake thread implementation for single-threaded
+//               applications.  This simply fails whenever you try to
+//               start a thread.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA ThreadDummyImpl {
+public:
+  INLINE ThreadDummyImpl(Thread *parent_obj);
+  INLINE ~ThreadDummyImpl();
+
+  INLINE bool start(ThreadPriority priority, bool global, bool joinable);
+  INLINE void join();
+
+  INLINE static void prepare_for_exit();
+
+  INLINE static Thread *get_current_thread();
+  INLINE static bool is_threading_supported();
+  INLINE static void sleep(double seconds);
+
+  INLINE int atomic_inc(int &var);
+  INLINE int atomic_dec(int &var);
+  INLINE int atomic_set(int &var, int new_value);
+};
+
+#include "threadDummyImpl.I"
+
+#endif // IPC_DUMMY_IMPL
+
+#endif

+ 37 - 0
panda/src/express/threadImpl.h

@@ -0,0 +1,37 @@
+// Filename: threadImpl.h
+// Created by:  drose (09Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef THREADIMPL_H
+#define THREADIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#if defined(IPC_DUMMY_IMPL)
+
+#include "threadDummyImpl.h"
+typedef ThreadDummyImpl ThreadImpl;
+
+#elif defined(IPC_NSPR_IMPL)
+
+#include "threadNsprImpl.h"
+typedef ThreadNsprImpl ThreadImpl;
+
+#endif
+
+#endif

+ 74 - 0
panda/src/express/threadNsprImpl.I

@@ -0,0 +1,74 @@
+// Filename: threadNsprImpl.I
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ThreadNsprImpl::
+ThreadNsprImpl(Thread *parent_obj) :
+  _parent_obj(parent_obj)
+{
+  _thread = (PRThread *)NULL;
+  _joinable = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::prepare_for_exit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadNsprImpl::
+prepare_for_exit() {
+  PR_Cleanup();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::Constructor
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE Thread *ThreadNsprImpl::
+get_current_thread() {
+  if (!_got_pt_ptr_index) {
+    return (Thread *)NULL;
+  }
+  return (Thread *)PR_GetThreadPrivate(_pt_ptr_index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::is_threading_supported
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool ThreadNsprImpl::
+is_threading_supported() {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::sleep
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadNsprImpl::
+sleep(double seconds) {
+  PR_Sleep((int)(PR_TicksPerSecond() * seconds));
+}

+ 196 - 0
panda/src/express/threadNsprImpl.cxx

@@ -0,0 +1,196 @@
+// Filename: threadNsprImpl.cxx
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "threadNsprImpl.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "pointerTo.h"
+#include "config_express.h"
+#include "mutexHolder.h"
+
+PRUintn ThreadNsprImpl::_pt_ptr_index = 0;
+bool ThreadNsprImpl::_got_pt_ptr_index = false;
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+ThreadNsprImpl::
+~ThreadNsprImpl() {
+  if (ipc_cat.is_debug()) {
+    ipc_cat.debug() << "Deleting thread " << _parent_obj->get_name() << "\n";
+  }
+
+  // If the thread object is destructing, it means the last pointer
+  // has gone away.  This can happen in one of three cases:
+
+  // (1) start() was never called, and the last user reference has
+  // gone away.  In this case, we should do nothing.
+
+  // (2) There are no more user references, and the thread is still
+  // running but is about to exit root_func().  In this case, no one
+  // will ever call join().
+
+  // (3) The thread terminated a while ago, and the last user
+  // reference has just gone away.  In this case, we should call
+  // join() if no one else has, to clean up whatever internal
+  // structures NSPR might keep around for a non-detached thread.
+
+
+  if (_thread == (PRThread *)NULL) {
+    // Since the _thread pointer is still NULL, we must either be in
+    // case (1), or case (3) but someone else has already called
+    // join().  Do nothing.
+    return;
+  }
+
+  PRThread *current_thread = PR_GetCurrentThread();
+  if (current_thread == _thread) {
+    // Since we are currently executing *this* thread, we must be in
+    // case (2).  Unfortunately, we cannot now indicate we need to
+    // clean up the thread, since NSPR doesn't have an interface to
+    // make a thread unjoinable after it has been created, and a
+    // thread can't join itself (can it?).
+    if (_joinable) {
+      ipc_cat.warning()
+        << "thread " << _parent_obj->get_name() << " was never joined.\n";
+    }
+    return;
+  }
+
+  // This is case (3).  The pointer went away and the thread has
+  // already terminated; furthermore, no one has called join() yet.
+  // We should do it.
+  join();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::start
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool ThreadNsprImpl::
+start(ThreadPriority priority, bool global, bool joinable) {
+  MutexHolder holder(_mutex);
+  if (ipc_cat.is_debug()) {
+    ipc_cat.debug() << "Starting thread " << _parent_obj->get_name() << "\n";
+  }
+  nassertr(_thread == (PRThread *)NULL, false);
+  _joinable = joinable;
+
+  if (!_got_pt_ptr_index) {
+    // Allocate a new index to store the Thread parent pointer as a
+    // piece of per-thread private data.
+    PRStatus result = PR_NewThreadPrivateIndex(&_pt_ptr_index, NULL);
+    if (result == PR_SUCCESS) {
+      _got_pt_ptr_index = true;
+    } else {
+      ipc_cat.error()
+        << "Unable to associate Thread pointers with threads.\n";
+      return false;
+    }
+  }
+
+  PRThreadPriority nspr_pri;
+
+  switch (priority) {
+  case TP_low:
+    nspr_pri = PR_PRIORITY_LOW;
+    break;
+
+  case TP_normal:
+    nspr_pri = PR_PRIORITY_NORMAL;
+    break;
+
+  case TP_high:
+    nspr_pri = PR_PRIORITY_HIGH;
+    break;
+
+  case TP_urgent:
+    nspr_pri = PR_PRIORITY_URGENT;
+    break;
+
+  default:
+    nassertr(false, false);
+  }
+
+  PRThreadScope nspr_scope = (global) ? PR_GLOBAL_THREAD : PR_LOCAL_THREAD;
+
+  PRThreadState nspr_state = (_joinable) ? PR_JOINABLE_THREAD : PR_UNJOINABLE_THREAD;
+
+  // Increment the parent object's reference count first.  The thread
+  // will eventually decrement it when it terminates.
+  _parent_obj->ref();
+  _thread = 
+    PR_CreateThread(PR_USER_THREAD, &root_func, (void *)_parent_obj,
+                    nspr_pri, nspr_scope, nspr_state, 0);
+
+  if (_thread == (PRThread *)NULL) {
+    // Oops, we couldn't start the thread.  Be sure to decrement the
+    // reference count we incremented above, and return false to
+    // indicate failure.
+    unref_delete(_parent_obj);
+    return false;
+  }
+
+  // Thread was successfully started.
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::join
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void ThreadNsprImpl::
+join() {
+  MutexHolder holder(_mutex);
+  if (_joinable && _thread != (PRThread *)NULL) {
+    PR_JoinThread(_thread);
+    _thread = (PRThread *)NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadNsprImpl::root_func
+//       Access: Private, Static
+//  Description: The entry point of each thread.
+////////////////////////////////////////////////////////////////////
+void ThreadNsprImpl::
+root_func(void *data) {
+  Thread *parent_obj = (Thread *)data;
+  PRStatus result = PR_SetThreadPrivate(_pt_ptr_index, parent_obj);
+  nassertv(result == PR_SUCCESS);
+  parent_obj->thread_main();
+
+  if (ipc_cat.is_debug()) {
+    ipc_cat.debug()
+      << "Terminating thread " << parent_obj->get_name() 
+      << ", count = " << parent_obj->get_ref_count() << "\n";
+  }
+
+  // Now drop the parent object reference that we grabbed in start().
+  // This might delete the parent object, and in turn, delete the
+  // ThreadNsprImpl object.
+  unref_delete(parent_obj);
+}
+
+#endif  // IPC_NSPR_IMPL

+ 70 - 0
panda/src/express/threadNsprImpl.h

@@ -0,0 +1,70 @@
+// Filename: threadNsprImpl.h
+// Created by:  drose (08Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef THREADNSPRIMPL_H
+#define THREADNSPRIMPL_H
+
+#include "pandabase.h"
+#include "selectIpcImpl.h"
+
+#ifdef IPC_NSPR_IMPL
+
+#include "notify.h"
+#include "threadPriority.h"
+#include "mutex.h"
+
+#include <prthread.h>
+#include <prinit.h>
+
+class Thread;
+
+////////////////////////////////////////////////////////////////////
+//       Class : ThreadNsprImpl
+// Description : Uses NSPR to implement a thread.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA ThreadNsprImpl {
+public:
+  INLINE ThreadNsprImpl(Thread *parent_obj);
+  INLINE ~ThreadNsprImpl();
+
+  bool start(ThreadPriority priority, bool global, bool joinable);
+  void join();
+
+  INLINE static void prepare_for_exit();
+
+  INLINE static Thread *get_current_thread();
+  INLINE static bool is_threading_supported();
+  INLINE static void sleep(double seconds);
+
+private:
+  static void root_func(void *data);
+  static void pt_ptr_destructor(void *data);
+
+  Mutex _mutex;
+  Thread *_parent_obj;
+  PRThread *_thread;
+  bool _joinable;
+  static PRUintn _pt_ptr_index;
+  static bool _got_pt_ptr_index;
+};
+
+#include "threadNsprImpl.I"
+
+#endif  // IPC_NSPR_IMPL
+
+#endif

+ 15 - 20
panda/src/ipc/ipc_library.h → panda/src/express/threadPriority.h

@@ -1,5 +1,5 @@
-// Filename: ipc_library.h
-// Created by:  frang (10Feb00)
+// Filename: threadPriority.h
+// Created by:  drose (08Aug02)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -16,26 +16,21 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef __IPC_LIBRARY_H__
-#define __IPC_LIBRARY_H__
+#ifndef THREADPRIORITY_H
+#define THREADPRIORITY_H
 
-#include <pandabase.h>
+#include "pandabase.h"
 
-#include "ipc_traits.h"
-
-class base_library {
-public:
-  typedef ipc_traits traits;
-  typedef traits::library_class library_class;
-
-  static base_library* const Null;
-  INLINE base_library(std::string& lib) : _lib(traits::make_library(lib)) {}
-  INLINE ~base_library(void) { delete _lib; }
-  INLINE void* get_symbol(std::string& sym) { return _lib->get_symbol(sym); }
-private:
-  library_class* _lib;
+////////////////////////////////////////////////////////////////////
+// An enumerated type used by Thread to specify a suggested relative
+// priority for a particular thread.
+////////////////////////////////////////////////////////////////////
+enum ThreadPriority {
+  TP_low,
+  TP_normal,
+  TP_high,
+  TP_urgent
 };
 
-typedef base_library library;
 
-#endif /* __IPC_LIBRARY_H__ */
+#endif

+ 0 - 33
panda/src/ipc/Sources.pp

@@ -1,33 +0,0 @@
-#define LOCAL_LIBS express pandabase
-#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
-                   dtoolutil:c dtoolbase:c dtool:m
-#define USE_PACKAGES nspr ipc
-#define BUILD_DIRECTORY $[HAVE_IPC]
-
-#begin lib_target
-  #define TARGET ipc
-  
-  #define COMBINED_SOURCES $[TARGET]_composite1.cxx  
-  
-  #define SOURCES                                                       \
-    ipc_atomics.h ipc_condition.h ipc_file.I ipc_file.h \
-    ipc_library.h ipc_mach_traits.h ipc_mutex.h ipc_nspr_traits.h \
-    ipc_nt_traits.h ipc_posix_traits.h \
-    ipc_ps2_traits.h ipc_semaphore.h ipc_solaris_traits.h ipc_thread.h \
-    ipc_traits.h
-    
-  #define INCLUDED_SOURCES                                                       \
-    ipc.cxx ipc_traits.cxx
-
-  #define INSTALL_HEADERS                                       \
-    ipc_mutex.h ipc_condition.h ipc_semaphore.h ipc_thread.h \
-    ipc_traits.h ipc_mach_traits.h ipc_nt_traits.h ipc_posix_traits.h \
-    ipc_solaris_traits.h ipc_nspr_traits.h ipc_ps2_traits.h \
-    ipc_atomics.h ipc_library.h ipc_file.h ipc_file.I
-
-#end lib_target
-
-// There needs to be a way to compile this into the ipc library only
-// when appropriate.  Perhaps as simple as compiling it all the time,
-// but protecting the code itself within #ifdefs.
-#define EXTRA_DIST ipc_nt_traits.cxx

+ 0 - 90
panda/src/ipc/ipc.cxx

@@ -1,90 +0,0 @@
-// Filename: ipc.cxx
-// Created by:  frang (06Apr00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "ipc_condition.h"
-
-base_condition_variable* const base_condition_variable::Null =
-  (base_condition_variable*)0L;
-
-#include "ipc_library.h"
-
-base_library* const base_library::Null = (base_library*)0L;
-
-#include "ipc_file.h"
-
-base_file* const base_file::Null = (base_file*)0L;
-
-#include "ipc_mutex.h"
-
-base_mutex* const base_mutex::Null = (base_mutex*)0L;
-
-#include "ipc_semaphore.h"
-
-base_semaphore* const base_semaphore::Null = (base_semaphore*)0L;
-
-#include "ipc_thread.h"
-
-base_thread* const base_thread::Null = (base_thread*)0L;
-base_thread::mutex* base_thread::_next_id_mutex = base_thread::mutex::Null;
-
-int base_thread::_next_id = 0;
-
-void* base_thread::thread_wrapper(void* data)
-{
-   base_thread* me = (base_thread *) data;
-
-   me->_thread->start_in();
-
-   // now invoke the thread functin with the given argument
-
-   if (me->_fn_void != NULL)
-   {
-     (*me->_fn_void)(me->_thread_arg);
-     base_thread::exit();
-   }
-
-   if (me->_fn_ret != NULL)
-   {
-     void* return_value = (*me->_fn_ret)(me->_thread_arg);
-     base_thread::exit(return_value);
-   }
-
-   if (me->_detached)
-   {
-     me->run(me->_thread_arg);
-     base_thread::exit();
-   }
-   else
-   {
-     void* return_value = me->run_undetached(me->_thread_arg);
-     base_thread::exit(return_value);
-   }
-
-   // we should never get here, but this makes the compilers happy
-
-   return (void *) NULL;
-}
-
-void base_thread::run(void*) {
-}
-
-void* base_thread::run_undetached(void*) {
-  return (void*)0L;
-}
-
-

+ 0 - 4
panda/src/ipc/ipc_composite1.cxx

@@ -1,4 +0,0 @@
-
-#include "ipc.cxx"
-#include "ipc_traits.cxx"
-

+ 0 - 52
panda/src/ipc/ipc_condition.h

@@ -1,52 +0,0 @@
-// Filename: ipc_condition.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_CONDITION_H__
-#define __IPC_CONDITION_H__
-
-#include <pandabase.h>
-
-#include "ipc_traits.h"
-#include "ipc_mutex.h"
-
-class EXPCL_PANDAEXPRESS base_condition_variable {
-   public:
-      typedef ipc_traits traits;
-      typedef traits::condition_class condition_class;
-      typedef base_mutex mutex;
-
-      static base_condition_variable* const Null;
-      INLINE base_condition_variable(mutex& m) : _mutex(m),
-        _condition(traits::make_condition(m.get_mutex())) {}
-      INLINE ~base_condition_variable(void) { delete _condition; }
-      INLINE void wait(void) { _condition->wait(); }
-      INLINE int timedwait(const unsigned long secs,
-                           const unsigned long nsecs = 0) {
-         return _condition->timedwait(secs, nsecs);
-      }
-      INLINE void signal(void) { _condition->signal(); }
-      INLINE void broadcast(void) { _condition->broadcast(); }
-      INLINE condition_class* get_condition(void) { return _condition; }
-   private:
-      mutex& _mutex;
-      condition_class *_condition;
-};
-
-typedef base_condition_variable condition_variable;
-
-#endif /* __IPC_CONDITION_H__ */

+ 0 - 54
panda/src/ipc/ipc_file.h

@@ -1,54 +0,0 @@
-// Filename: ipc_file.h
-// Created by:  jason (05Jun00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_FILE_H__
-#define __IPC_FILE_H__
-
-#include <pandabase.h>
-#include <datagramGenerator.h>
-#include <datagramSink.h>
-#include "ipc_traits.h"
-
-class base_file {
-public:
-  enum file_mode {FILE_READ, FILE_WRITE, FILE_BOTH, FILE_APPEND};
-
-  typedef ipc_traits traits;
-  typedef traits::file_class file_class;
-
-  static base_file* const Null;
-
-  INLINE base_file(const string& file = "") : _file(traits::make_file(file)) {}
-  virtual ~base_file(void) { delete _file; };
-  INLINE void setFile(const string& file) {_file->setFile(file);}
-  INLINE bool open(file_mode mode) {return _file->open(mode);}
-  INLINE void close(void) {_file->close();}
-  INLINE bool empty(void) { return _file->empty();}
-  INLINE int readin(string& buffer, int numBytes) {return _file->readin(buffer, numBytes);}
-  INLINE int writeout(const string& buffer) {return _file->writeout(buffer);}
-private:
-  file_class* _file;
-};
-
-typedef base_file file;
-typedef file::file_mode file_mode;
-
-#include "ipc_file.I"
-
-#endif /* __IPC_FILE_H__ */
-

+ 0 - 297
panda/src/ipc/ipc_mach_traits.h

@@ -1,297 +0,0 @@
-// Filename: ipc_mach_traits.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_MACH_TRAITS_H__
-#define __IPC_MACH_TRAITS_H__
-
-#include <pandabase.h>
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <mach/cthreads.h>
-
-class EXPCL_PANDAEXPRESS ipc_traits {
-   public:
-      class mutex_class;
-      class condition_class;
-      class semaphore_class;
-      class thread_class;
-      class library_class;
-      class mutex_class {
-         private:
-            struct mutex _mutex;
-         public:
-            // interface to mutex
-            static const mutex_class* Null;
-            INLINE mutex_class(void) { mutex_init(&_mutex); }
-            INLINE ~mutex_class(void) { mutex_clear(&_mutex); }
-            INLINE void lock(void) { mutex_lock(&_mutex); }
-            INLINE void unlock(void) { mutex_unlock(&_mutex); }
-            INLINE struct mutex* get_mutex(void) { return &_mutex; }
-      };
-      class condition_class {
-         private:
-            struct condition _condition;
-            mutex_class *_mutex;
-            typedef struct alarmclock_args {
-               unsigned long secs;
-               unsigned long nsecs;
-               bool wakeup;
-               condition_class* condition;
-               mutex_class* mutex;
-            };
-            INLINE any_t alarmclock(any_t arg) {
-               alarmclock_args* alarm = (alarmclock_args*)arg;
-               thread_ipc_traits::sleep(alarm->secs, alarm->nsecs);
-               alarm->mutex->lock();
-               alarm->wakeup = TRUE;
-               alarm->condition->signal();
-               alarm->mutex->unlock();
-               return (any_t)TRUE;
-            }
-         public:
-            // interface to condition variables
-            static const condition_class* Null;
-            INLINE condition_class(mutex_class* m) : _mutex(m) {
-              condition_init(&_condition);
-            }
-            INLINE ~condition_class(void) { condition_clear(&_condition); }
-            INLINE void wait(void) {
-               condition_wait(&_condition, _mutex->get_mutex());
-            }
-            INLINE int timedwait(const unsigned long secs,
-                                 const unsigned long nsecs) {
-               alarmclock_args alarm;
-
-               thread_ipc_traits::get_time(&alarm.secs, &alarm.nsecs, 0, 0);
-               if (secs < alarm.secs || (secs == alarm.secs &&
-                                         nsecs <= alarm.nsecs))
-                  return ETIMEDOUT;
-               alarm.secs = secs - alarm.secs;
-               if (nsecs <= alarm.nsecs) {
-                  alarm.nsecs = 1000000 - alarm.nsecs + nsecs;
-                  --alarm.secs;
-               } else
-                  alarm.nsecs = nsecs - alarm.nsecs;
-               alarm.mutex = _mutex;
-               alarm.condition = this;
-               alarm.wakeup = FALSE;
-               cthread_t ct = cthread_fork((cthread_fn_t)alarmclock,
-                                           (any_t)&alarm);
-               cthread_detach(ct);
-
-               condition_wait(&_condition, _mutex->get_mutex());
-
-               if (alarm.wakeup)
-                  return 0;
-
-               // interrupt the alarmclock thread sleep
-               cthread_abort(ct);
-
-               // wait until it has signalled the condition
-               condition_wait(&_condition, _mutex->get_mutex());
-               return 1;
-            }
-            INLINE void signal(void) { condition_signal(&_condition); }
-            INLINE void broadcast(void) { condition_signal(&_condition); }
-      };
-      class semaphore_class {
-         private:
-            mutex_class _mutex;
-            condition_class _condition;
-            int _value;
-         public:
-            // interface to semaphores
-            static const semaphore_class* Null;
-            INLINE semaphore_class(const unsigned int initial) : _mutex(),
-               _condition(&_mutex), _value(initial) {}
-            INLINE ~semaphore_class(void) {}
-            INLINE void wait(void) {
-               _mutex->lock();
-               while (_value == 0)
-                  _condition.wait(&_mutex);
-               --_value;
-               _mutex->unlock();
-            }
-            INLINE int trywait(void) {
-               _mutex->lock();
-               if (_value == 0) {
-                  _mutex->unlock();
-                  return 0;
-               }
-               --_value;
-               _mutex->unlock();
-               return 1;
-            }
-            INLINE void post(void) {
-               _mutex->lock();
-               if (_value == 0)
-                  _condition.signal();
-               ++_value;
-               _mutex->unlock();
-            }
-      };
-      class thread_class {
-         private:
-            chread_d _thread;
-            void* _b_ptr; // a handle to hang a pointer back to the high-level
-                          // thread class on.  Gross, but I couldn't think of
-                          // a better way to do this reverse lookup.
-            void* (*_fn)(void*);
-            INLINE int priority_map(const int pri) {
-               switch (pri) {
-               case 0:
-                  return 0;
-               case 1:
-                  return normal_priority;
-               case 2:
-                  return high_priority;
-               default:
-                  return -1;
-               }
-            }
-            static void* thread_wrapper(void*);
-         public:
-            // interface to threads
-            static const thread_class* Null;
-            INLINE thread_class(void* data) : _b_ptr(data) {}
-            INLINE ~thread_class(void) {}
-            INLINE void manual_init(void) {
-               _thread = cthread_self();
-            }
-            INLINE void start_pre(void* (*fn)(void*), const bool, const int) {
-               _fn = fn;
-               _thread = cthread_fork(thread_wrapper, (any_t)this);
-            }
-            INLINE void start_in(void) {
-               cthread_set_data(cthread_self(), (any_t)this);
-            }
-            INLINE void start_post(const bool det, const int) {
-               if (det)
-                  cthread_detach(_thread);
-            }
-            INLINE void join(void** status) {
-               *status = cthread_join(_thread);
-            }
-            INLINE void set_priority(const int pri) {
-               kern_return_t rc = cthread_priority(_thread, priority_map(pri),
-                                                   FALSE);
-               if (rc != KERN_SUCCESS)
-                  throw thread_fatal(errno);
-            }
-            INLINE void* back_ptr(void) { return _b_ptr; }
-            static INLINE void exit(void* return_value) {
-               cthread_exit(return_value);
-            }
-            static INLINE thread_class* self(void) {
-               thread_class* me = (thread_class*)cthread_data(cthread_self());
-               // if (me == thread_class::Null)  not one of ours
-               return me;
-            }
-            static INLINE void yield(void) {
-               cthread_yield();
-            }
-      };
-      class library_class {
-      public:
-        static library_class* const Null;
-        INLINE library_class(str&) {
-          throw lib_load_invalid();
-        }
-        INLINE ~library_class(void) {
-          throw lib_load_invalid();
-        }
-        INLINE void* get_symbol(str&) {
-          throw lib_load_invalid();
-        }
-      };
-      static INLINE mutex_class *make_mutex(void) {
-         return new mutex_class;
-      }
-      static INLINE condition_class *make_condition(mutex_class* m) {
-         return new condition_class(m);
-      }
-      static INLINE semaphore_class *make_semaphore(const unsigned int initial) {
-         return new semaphore_class(initial);
-      }
-      static INLINE thread_class *make_thread(void* data) {
-         return new thread_class(data);
-      }
-      static INLINE library_class *make_library(str&) {
-        throw lib_load_invalid();
-      }
-      static INLINE void sleep(const unsigned long secs,
-                               const unsigned long nsecs = 0) {
-         const unsigned MAX_SLEEP_SECONDS=(unsigned)4294966;  // (2**32-2)/1000
-         if (secs <= MAX_SLEEP_SECONDS) {
-            thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT,
-                          secs * 1000 + nsecs / 1000000);
-            return;
-         }
-         unsigned no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;
-         for (unsigned i=0; i<no_of_max_sleeps; ++i)
-            thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT,
-                          MAX_SLEEP_SECONDS * 1000);
-         thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT,
-                       (secs % MAX_SLEEP_SECONDS) * 1000 + nsecs / 1000000);
-      }
-      static INLINE void get_time(unsigned long& abs_secs,
-                                  unsigned long& abs_nsecs,
-                                  const unsigned long rel_secs = 0,
-                                  const unsigned long rel_nsecs = 0) {
-         int rc;
-         unsigned long tv_sec;
-         unsigned long tv_nsec;
-         struct timeval tv;
-
-         rc = gettimeofday(&tv, NULL);
-         if (rc)
-            throw thread_fatal(rc);
-         tv_sec = tv.tv_sec;
-         tv_nsec = tv.tv_usec * 1000;
-         tv_nsec += rel_nsecs;
-         tv_sec += rel_secs + tv_nsec / 1000000000;
-         tv_nsec = tv_nsec % 1000000000;
-         abs_secs = tv_sec;
-         abs_nsecs = tv_nsec;
-      }
-      static INLINE int set_atomic(int&, int) {
-        throw set_atomic_invalid();
-      }
-      static INLINE int inc_atomic(int&) {
-        throw inc_atomic_invalid();
-      }
-      static INLINE int dec_atomic(int&) {
-        throw dec_atomic_invalid();
-      }
-      // these really should be private, but it's annoying to make config a
-      // friend
-      static INLINE __set_normal_priority(int p) {
-        normal_priority = p;
-      }
-      static INLINE __set_highest_priority(int p) {
-        highest_priority = p;
-      }
-   private:
-      // other data specific to this implementation
-      static int normal_priority;
-      static int highest_priority;
-};
-
-#endif /* __IPC_MACH_TRAITS_ */

+ 0 - 53
panda/src/ipc/ipc_mutex.h

@@ -1,53 +0,0 @@
-// Filename: ipc_mutex.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_MUTEX_H__
-#define __IPC_MUTEX_H__
-
-#include <pandabase.h>
-
-#include "ipc_traits.h"
-
-class EXPCL_PANDAEXPRESS base_mutex {
-   public:
-      typedef ipc_traits traits;
-      typedef traits::mutex_class mutex_class;
-
-      static base_mutex* const Null;
-      INLINE base_mutex(void) : _mutex(traits::make_mutex()) {}
-      INLINE ~base_mutex(void) { delete _mutex; }
-      INLINE void lock(void) { _mutex->lock(); }
-      INLINE void unlock(void) { _mutex->unlock(); }
-      INLINE mutex_class* get_mutex(void) { return _mutex; }
-   private:
-      mutex_class* _mutex;
-};
-
-class base_mutex_lock {
-   public:
-      typedef base_mutex mutex;
-      INLINE base_mutex_lock(mutex& m) : _mutex(m) { _mutex.lock(); }
-      INLINE ~base_mutex_lock(void) { _mutex.unlock(); }
-   private:
-      mutex& _mutex;
-};
-
-typedef base_mutex mutex;
-typedef base_mutex_lock mutex_lock;
-
-#endif /* __IPC_MUTEX_H__ */

+ 0 - 350
panda/src/ipc/ipc_nspr_traits.h

@@ -1,350 +0,0 @@
-// Filename: ipc_nspr_traits.h
-// Created by:  cary (12Jan00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_NSPR_TRAITS_H__
-#define __IPC_NSPR_TRAITS_H__
-
-#include <pandabase.h>
-#include <nspr.h>
-
-#include "datagram.h"
-
-class EXPCL_PANDAEXPRESS ipc_traits {
-public:
-  class mutex_class;
-  class condition_class;
-  class semaphore_class;
-  class thread_class;
-  class library_class;
-
-  class EXPCL_PANDAEXPRESS mutex_class {
-  private:
-    PRLock* _mutex;
-  public:
-    // interface to mutex
-    static mutex_class* const Null;
-    INLINE mutex_class(void) : _mutex(PR_NewLock()) {
-      if (_mutex == (PRLock*)0L)
-        cerr << "COULD NOT GET A MUTEX!" << endl;
-    }
-    INLINE ~mutex_class(void) {
-      PR_DestroyLock(_mutex);
-    }
-    INLINE void lock(void) {
-      PR_Lock(_mutex);
-    }
-    INLINE void unlock(void) {
-      PR_Unlock(_mutex);
-    }
-    INLINE PRLock* get_mutex(void) {
-      return _mutex;
-    }
-  };
-  class EXPCL_PANDAEXPRESS condition_class {
-  private:
-    mutex_class* _mutex;
-    PRCondVar* _condition;
-  public:
-    static condition_class* const Null;
-    INLINE condition_class(mutex_class* m)
-      : _mutex(m), _condition(PR_NewCondVar(m->get_mutex())) {}
-    INLINE ~condition_class(void) {
-      PR_DestroyCondVar(_condition);
-    }
-    INLINE void wait(void) {
-      PR_WaitCondVar(_condition, PR_INTERVAL_NO_TIMEOUT);
-    }
-    INLINE int timedwait(const unsigned long secs, const unsigned long nsecs) {
-      unsigned long s, n;
-      ipc_traits::get_time(s, n);
-      PRIntervalTime i = PR_SecondsToInterval(secs - s) +
-        PR_MicrosecondsToInterval((nsecs - n) / 1000);
-      PR_WaitCondVar(_condition, i);
-      return 1;
-    }
-    INLINE void signal(void) {
-      PR_NotifyCondVar(_condition);
-    }
-    INLINE void broadcast(void) {
-      PR_NotifyAllCondVar(_condition);
-    }
-  };
-  class EXPCL_PANDAEXPRESS semaphore_class {
-  private:
-    mutex_class _mutex;
-    condition_class _condition;
-    int _value;
-    class EXPCL_PANDAEXPRESS mutex_class_lock {
-    public:
-      INLINE mutex_class_lock(mutex_class& m) : _mutex(m) {
-        _mutex.lock();
-      }
-      INLINE ~mutex_class_lock(void) {
-        _mutex.unlock();
-      }
-    private:
-      mutex_class& _mutex;
-    };
-  public:
-    static semaphore_class* const Null;
-    INLINE semaphore_class(const unsigned int initial)
-      : _mutex(), _condition(&_mutex), _value(initial) {}
-    INLINE ~semaphore_class(void) {}
-    INLINE void wait(void) {
-      mutex_class_lock l(_mutex);
-      while (_value == 0)
-        _condition.wait();
-      --_value;
-    }
-    INLINE int trywait(void) {
-      mutex_class_lock l(_mutex);
-      if (_value == 0)
-        return 0;
-      --_value;
-      return 1;
-    }
-    INLINE void post(void) {
-      mutex_class_lock l(_mutex);
-      if (_value == 0)
-        _condition.signal();
-      ++_value;
-    }
-  };
-  class EXPCL_PANDAEXPRESS thread_class {
-  private:
-    PRThread* _thread;
-    void* _b_ptr;  // a handle to hang a pointer back to the high-level
-                   // thread class on.  Gross, but I couldn't think of a
-                   // better way to do this reverse lookup.
-    void* (*_fn)(void*);
-    void* _return_value;
-    INLINE PRThreadPriority priority_map(const int pri) {
-      switch (pri) {
-      case 0:
-        return PR_PRIORITY_LOW;
-      case 1:
-        return PR_PRIORITY_NORMAL;
-      case 2:
-        return PR_PRIORITY_HIGH;
-      }
-      return PR_PRIORITY_NORMAL;
-    }
-    static void thread_wrapper(void*);
-  public:
-    static thread_class* const Null;
-    INLINE thread_class(void* data) : _b_ptr(data) {}
-    INLINE ~thread_class(void) {}
-    INLINE void manual_init(void) {
-      _thread = PR_GetCurrentThread();
-    }
-    INLINE void start_pre(void* (*fn)(void*), const bool det, const int pri) {
-      _fn = fn;
-      // create the thread, decide it's priority, if it's detached, and if it's
-      // a kernel thread, etc
-      _thread = PR_CreateThread(PR_SYSTEM_THREAD, thread_wrapper, this,
-                                priority_map(pri), PR_GLOBAL_BOUND_THREAD,
-                                det?PR_UNJOINABLE_THREAD:PR_JOINABLE_THREAD,
-                                256*1024);
-    }
-    INLINE void start_in(void) {
-      PR_SetThreadPrivate(__get_data_index(), this);
-    }
-    INLINE void start_post(const bool, const int) {}
-    INLINE void join(void** status) {
-      PR_JoinThread(_thread);
-      if (status)
-        *status = _return_value;
-    }
-    INLINE void set_priority(const int pri) {
-      PR_SetThreadPriority(_thread, priority_map(pri));
-    }
-    INLINE void* back_ptr(void) { return _b_ptr; }
-    static INLINE void exit(void* return_value) {
-      thread_class* me = self();
-      if (me != thread_class::Null)
-        me->_return_value = return_value;
-      // This gives us a seg fault upon exit - NSPR wants us to return from
-      // the callback function rather than exit()
-      //exit(0);  // assuming that this is really a kernel thread.  NSPR offers
-                // no 'thread exit' facility
-    }
-    static INLINE thread_class* self(void) {
-      return (thread_class*)PR_GetThreadPrivate(__get_data_index());
-    }
-    static INLINE void yield(void) {
-      PR_Sleep(PR_INTERVAL_NO_WAIT);
-    }
-  };
-  class EXPCL_PANDAEXPRESS library_class {
-  private:
-    PRLibrary* _lib;
-  public:
-    static library_class* const Null;
-    INLINE library_class(const std::string& lib) {
-      _lib = PR_LoadLibrary(lib.c_str());
-      if (_lib == (PRLibrary*)0L) {
-        nout << "failed to load library '" << lib << "'" << endl;
-      }
-    }
-    INLINE ~library_class(void) {
-      if (_lib != (PRLibrary*)0L) {
-        PRStatus stat = PR_UnloadLibrary(_lib);
-        if (stat == PR_FAILURE)
-          nout << "failed to unload library" << endl;
-      }
-    }
-    INLINE void* get_symbol(const std::string& sym) {
-      if (_lib == (PRLibrary*)0L) {
-        nout << "library not correctly loaded" << endl;
-        return (void *)0L;
-      }
-      return PR_FindSymbol(_lib, sym.c_str());
-    }
-  };
-  class EXPCL_PANDAEXPRESS file_class {
-      //interface to file IO
-      public:
-        INLINE file_class(const std::string& file = "") : _filename(file), _fhandle((PRFileDesc*)NULL){}
-        INLINE ~file_class() { close(); }
-        INLINE void setFile(const std::string& file) { _filename = file; close(); }
-        INLINE bool open(const int mode) {
-          close();
-          switch(mode){
-          case 0: _fhandle = PR_Open(_filename.c_str(), PR_RDONLY, 00666); break;
-          case 1: _fhandle = PR_Open(_filename.c_str(),
-                                     PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 00666); break;
-          case 2: _fhandle = PR_Open(_filename.c_str(),
-                                     PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00666); break;
-          case 3: _fhandle = PR_Open(_filename.c_str(), PR_APPEND | PR_CREATE_FILE, 00666); break;
-          default: _fhandle = PR_Open(_filename.c_str(), PR_RDONLY, 00666); break;
-          }
-          return (_fhandle != (PRFileDesc *)NULL);
-        }
-        INLINE void close(void) {
-          if (_fhandle != (PRFileDesc *)NULL) { PR_Close(_fhandle); _fhandle = (PRFileDesc *)NULL; }
-        }
-    INLINE bool empty(void){ return (PR_Available(_fhandle) <= 0); }
-
-    INLINE int readin(string &block, int numBytes) {
-           //Don't try and read less than nothing
-           if (_fhandle == (PRFileDesc *)NULL)
-              return 0;
-
-           nassertr(numBytes >= 0, 0);
-
-           char* temp = new char[numBytes];
-           int numRead = PR_Read(_fhandle, temp, numBytes);
-           if(numRead < 0) {
-                cerr << "PR_Read() in libnspr failed!\n";
-                delete temp;
-                return 0;
-           }
-           block.assign(temp, numRead);
-           delete temp;
-           return numRead;
-    }
-
-        INLINE int writeout(const string &block) {
-        nassertr(block.size() > 0, 0);      //Make sure there is something to write out
-        nassertr(block.data() != NULL, 0);
-
-        if (_fhandle == (PRFileDesc *)NULL)
-           return 0;
-            return PR_Write(_fhandle, (void*)block.data(), block.size());
-        }
-
-  private:
-    string _filename;
-        PRFileDesc* _fhandle;
-  };
-
-  static INLINE mutex_class* make_mutex(void) {
-    return new mutex_class;
-  }
-  static INLINE condition_class* make_condition(mutex_class* m) {
-    return new condition_class(m);
-  }
-  static INLINE semaphore_class* make_semaphore(const unsigned int initial) {
-    return new semaphore_class(initial);
-  }
-  static INLINE thread_class* make_thread(void* data) {
-    return new thread_class(data);
-  }
-  static INLINE library_class *make_library(const std::string& lib) {
-    return new library_class(lib);
-  }
-  static INLINE file_class *make_file(const std::string& file) {
-    return new file_class(file);
-  }
-  static INLINE void sleep(const unsigned long secs,
-                           const unsigned long nsecs = 0) {
-    PRIntervalTime i = PR_SecondsToInterval(secs) +
-      PR_MicrosecondsToInterval(nsecs / 1000);
-    PR_Sleep(i);
-  }
-  static INLINE void get_time(unsigned long& abs_secs,
-                              unsigned long& abs_nsecs,
-                              const unsigned long rel_secs = 0,
-                              const unsigned long rel_nsecs = 0) {
-    PRTime t = PR_Now();
-    PRTime t_offset;
-    PRTime usec_convert;
-    PRTime rel_time;
-    PRTime w, x, y;
-    PRTime s, n;
-
-    // really this step should only ever be done once
-    LL_UI2L(usec_convert, PR_USEC_PER_SEC);
-
-    LL_UI2L(w, rel_secs);
-    LL_UI2L(x, (rel_nsecs / 1000));
-    LL_MUL(y, usec_convert, w);
-    LL_ADD(rel_time, x, y);  // the PRTime representing the rel componant
-
-    LL_ADD(t_offset, t, rel_time);
-
-    LL_DIV(s, t_offset, usec_convert);
-    LL_MOD(n, t_offset, usec_convert);
-
-    LL_L2UI(abs_secs, s);
-    LL_L2UI(abs_nsecs, n);
-    abs_nsecs *= 1000;
-  }
-  static INLINE int set_atomic(int& var, int val) {
-    return PR_AtomicSet(&var, val);
-  }
-  static INLINE int inc_atomic(int& var) {
-    return PR_AtomicIncrement(&var);
-  }
-  static INLINE int dec_atomic(int& var) {
-    return PR_AtomicDecrement(&var);
-  }
-  // this really should be private, but it's annoying to make config a
-  // friend
-  static INLINE void __set_data_index(PRUintn d) {
-    _data_index = d;
-  }
-  static INLINE PRUintn __get_data_index(void) {
-    return _data_index;
-  }
-private:
-  // other data specific to this implementation
-  static PRUintn _data_index;
-};
-
-#endif /* __IPC_NSPR_TRAITS_H__ */

+ 0 - 569
panda/src/ipc/ipc_nt_traits.h

@@ -1,569 +0,0 @@
-// Filename: ipc_nt_traits.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_NT_TRAITS_H__
-#define __IPC_NT_TRAITS_H__
-
-#include <pandabase.h>
-
-#include <stdlib.h>
-#include <errno.h>
-#define WINDOWS_LEAN_AND_MEAN
-#include <windows.h>
-#undef WINDOWS_LEAN_AND_MEAN
-#include <process.h>
-
-#ifdef WIN32_VC
-const unsigned long SEMAPHORE_MAX = 0x7fffffff;
-#endif
-
-// much of the *next and *prev linked list stuff in here should probably be
-// done with STL containers.  Examine this when time permits.
-class EXPCL_PANDAEXPRESS ipc_traits {
-   public:
-      class mutex_class;
-      class condition_class;
-      class semaphore_class;
-      class thread_class;
-      class library_class;
-      class file_class;
-      class mutex_class {
-         private:
-            CRITICAL_SECTION _mutex;
-         public:
-            // interface to mutex
-            static const mutex_class* Null;
-            INLINE mutex_class(void) { InitializeCriticalSection(&_mutex); }
-            INLINE ~mutex_class(void) { DeleteCriticalSection(&_mutex); }
-            INLINE void lock(void) { EnterCriticalSection(&_mutex); }
-            INLINE void unlock(void) { LeaveCriticalSection(&_mutex); }
-      };
-      class thread_class {
-         private:
-            HANDLE _handle;
-            DWORD _id;
-            void* _return_value;
-            HANDLE _condition;
-            thread* _tnext;
-            thread* _tprev;
-            BOOL _waiting;
-            void* _b_ptr; // a handle to hang a pointer back to the high-level
-                          // thread class on.  Gross, but I couldn't think of
-                          // a better way to do this reverse lookup.
-            void* (*_fn)(void*);
-            INLINE int priority_map(const int pri) {
-              switch (pri) {
-              case 0:
-                 return THREAD_PRIORITY_LOWEST;
-              case 1:
-                 return THREAD_PRIORITY_NORMAL;
-              case 2:
-                 return THREAD_PRIORITY_HIGHEST;
-              }
-              throw thread_invalid();
-              // never gets here, but keeps the compiler happy
-              return 0;
-            }
-#ifndef __BCPLUSPLUS__
-            static unsigned _stdcall thread_wrapper(void*);
-#else
-            static void _USERENTRY thread_wrapper(void*);
-#endif
-         public:
-            // interface to threads
-            static const thread_class* Null;
-            INLINE thread_class(void* data) : _b_ptr(data),
-              _tnext(thread_class::Null), _tprev(thread_class::Null),
-              _waiting(FALSE), _handle(NULL) {
-               _condition = CreateSemaphore(NULL, 0, SEMAPHORE_MAX, NULL);
-               if (_condition == NULL)
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE ~thread_class(void) {
-               if (!CloseHandle(_handle))
-                  throw thread_fatal(GetLastError());
-               if (!CloseHandle(_condition))
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE void manual_init(void) {
-               if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-                                    GetCurrentProcess(), &_handle, 0, FALSE,
-                                    DUPLICATE_SAME_ACCESS))
-                  throw thread_fatal(GetLastError());
-               _id = GetCurrentThreadId();
-               if (!SetThreadPriority(_handle, priority_map(PRIORITY_NORMAL)))
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE void start_pre(void* (*fn)(void*), const bool, const int) {
-               _fn = fn;
-#ifndef __BCPLUSPLUS__
-               // MSVC++ or compatable
-               unsigned int t;
-               _handle = (HANDLE)_beginthreadex(NULL, 0, thread_wrapper,
-                                                (LPVOID)this, CREATE_SUSPENDED,
-                                                &t);
-               _id = t;
-               if (_handle == NULL)
-                  throw thread_fatal(GetLastError());
-#else
-               // Borland C++
-               _handle = (HANDLE)_beginthreadNT(thread_wrapper, 0, (void*)this,
-                                                NULL, CREATE_SUSPENDED, &_id);
-               if (_handle == INVALID_HANDLE_VALUE)
-                  throw thread_fatal(errno);
-#endif
-            }
-            INLINE void start_in(void) {
-               if (!TlsSetValue(self_tls_index, (LPVOID)this))
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE void start_post(const bool, const int pri) {
-               if (!SetThreadPriority(_handle, pri))
-                  throw thread_fatal(GetLastError());
-               if (ResumeThread(_handle) == 0xffffffff)
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE void join(void** status) {
-               if (WaitForSingleObject(_handle, INFINITE) != WAIT_OBJECT_0)
-                  throw thread_fatal(GetLastError());
-               if (status)
-                  *status = _return_value;
-            }
-            INLINE void set_priority(const int pri) {
-               if (!SetThreadPriority(_handle, priority_map(pri)))
-                  throw thread_fatal(GetLastError());
-            }
-            INLINE void* back_ptr(void) { return _b_ptr; }
-            static INLINE void exit(void* return_value) {
-               thread_class* me = self();
-               if (me != thread_class::Null)
-                  me->_return_val = return_value;
-#ifndef __BCPLUSPLUS__
-               _endthreadex(0);
-#else
-               _endthread();
-#endif
-            }
-            static INLINE thread_class* self(void) {
-               LPVOID me = TlsGetValue(self_tls_index);
-               if (me == NULL)
-                  return thread_class::Null;
-               return (thread_class*)me;
-            }
-            static INLINE void yield(void) {
-               Sleep(0);
-            }
-      };
-      // Condition variables are rather annoying to implement using NT
-      // synchronisation primitives, since none of them have the atomic
-      // "release mutex and wait to be signalled" which is central to the
-      // idea of a condition variable.  To get around this the solution is to
-      // record which threads are waiting and explicitly wake up those threads.
-      //
-      // Here we implement a condition variable using a list of waiting threads
-      // (protected by a critical section), and a per-thread semaphore (which
-      // actually only needs to be a binary semaphore).
-      //
-      // To wait on the cv, a thread puts itself on the list of waiting threads
-      // for that xv, then releases the mutex and waits on its own personal
-      // semaphore.  A signalling thread simply takes a thread from the head of
-      // the list and kicks that thread's semaphore.  Broadcast is simply
-      // implemented by kicking the semaphore of each waiting thread.
-      //
-      // The only other tricky part comes when a thread gets a timeout from a
-      // timed wait on it's semaphore.  Between returning with a timeout from
-      // the wait and entering the critical section, a signalling thread could
-      // get in, kick the waiting thread's semaphore and remove it from the
-      // list.  If this happens, the waiting thread's semaphore is now out of
-      // step so it needs resetting, and the thread should indicate that it was
-      // signalled reather than that it timed out.
-      //
-      // It is possible that the thread calling wait or timedwait is not one
-      // of our threads.  In this case we have to provide a temporary data
-      // structure, i.e. for the duration of the call, for the thread to link
-      // itself on the list of waiting threads.  _internal_thread_dummy
-      // provides such a data structure and _internal_thread_helper is a helper
-      // class to deal with this special case for wait() and timedwait().  Once
-      // created, the _internal_thread_dummy is cached for use by the next
-      // wait() or timedwait() call from a thread that is not one of ours.
-      // This is probably worth doing because creating a Semaphore is quite
-      // heavy weight.
-      class condition_class {
-         private:
-            CRITICAL_SECTION _condition;
-            thread_class* waiting_head;
-            thread_class* waiting_tail;
-            mutex_class* _mutex;
-            class _internal_thread_helper;
-            class _internal_thread_dummy : public thread_class {
-               public:
-                  INLINE _internal_thread_dummy(void) :
-                    next((_internal_thread_dummy*)0L) {}
-                  INLINE ~_internal_thread_dummy(void) {}
-                  friend class _internal_thread_helper;
-               private:
-                  _internal_thread_dummy* next;
-            };
-            class _internal_thread_helper {
-               public:
-                  INLINE _internal_thread_helper(void) :
-                    d((_internal_thread_dummy*)0L),
-                    t(thread_class::self()) {
-                     if (cachelock == mutex_class::Null)
-                        cachelock = new mutex_class;
-                     if (t == thread_class::Null) {
-                        cachelock->lock();
-                        if (cache) {
-                           d = cache;
-                           cache = cache->next;
-                        } else
-                           d = new _internal_tread_dummy;
-                        t = d;
-                        cachelock->unlock();
-                     }
-                  }
-                  INLINE ~_internal_thread_helper(void) {
-                     if (d != (_internal_thread_dummy*)0L) {
-                        cachelock->lock();
-                        d->next = cache;
-                        cache = d;
-                        cachelock->unlock();
-                     }
-                  }
-                  INLINE operator thread_class*(void) { return t; }
-                  INLINE thread_class* operator->(void) { return t; }
-                  static _internal_thread_dummy* cache;
-                  static mutex_class* cachelock;
-               private:
-                  _internal_thread_dummy* d;
-                  thread_class* t;
-            };
-         public:
-            // interface to condition variables
-            static const condition_class* Null;
-            INLINE condition_class(mutex_class*) : _mutex(m) {
-               InitializeCriticalSection(&_condition);
-               waiting_head = waiting_tail = thread_class::Null;
-            }
-            INLINE ~condition_class(void) {
-               DeleteCriticalSection(&_condition);
-               if (waiting_head != thread_class::Null)
-                  DEBUG() << "thread_ipc_traits<\"nt\">::condition_class::~condition_class : list of waiting threads is not empty" << nend;
-            }
-            INLINE void wait(void) {
-               _internal_thread_helper me;
-               EnterCriticalSection(&_condition);
-
-               me->cond_next = thread_class::Null;
-               me->cond_prev = waiting_tail;
-               if (waiting_head == thread_class::Null)
-                  waiting_head = me;
-               else
-                  waiting_tail->cond_next = me;
-               waiting_tail = me;
-               me->cond_waiting = TRUE;
-
-               LeaveCriticalSection(&_condition);
-               _mutex->unlock();
-               DWORD result = WaitForSingleObject(me->cond_semaphore, INFINITE);
-               _mutex->lock();
-               if (result != WAIT_OBJECT_0)
-                  throw condition_fatal(GetLastError());
-            }
-            INLINE int timedwait(const unsigned long secs,
-                                 const unsigned long nsecs) {
-               _internal_thread_helper me;
-               EnterCriticalSection(&_condition);
-
-               me->cond_next = thread_class::Null;
-               me->cond_pref = waiting_tail;
-               if (waiting_tail == thread_class::Null)
-                  waiting_head = me;
-               else
-                  waiting_tail->cond_next = me;
-               waiting_tail = me;
-               me->cond_waiting = TRUE;
-
-               LeaveCriticalSection(&_condition);
-               _mutex->unlock();
-               unsigned long now_sec, now_nsec;
-               thread_ipc_traits::get_time_now(now_sec, now_nsec);
-               DWORD timeout = (secs - now_sec) * 1000 +
-                 (nsecs - now_nsecs) / 1000000;
-               if ((secs <= new_sec) && ((secs < now_sec) ||
-                                         (nsecs < now_nsecs)))
-                  timeout = 0;
-               DWORD result = WaitForSingleObject(me->cond_semaphore, timeout);
-               if (result == WAIT_TIMEOUT) {
-                  EnterCriticalSection(&_condition);
-                  if (me->cond_waiting) {
-                     if (me->cond_prev != thread_class::Null)
-                        me->cond_prev->cond_next = me->cond_next;
-                     else
-                        waiting_head = me->cond_next;
-                     if (me->cond_next != thread_class::Null)
-                        me->cond_next->cond_prev = me->cond_prev;
-                     else
-                        waiting_tail = me->cond_prev;
-                     me->cond_waiting = FALSE;
-                     LeaveCriticalSection(&_condition);
-                     _mutex->lock();
-                     return 0;
-                  }
-                  // We timed out but another thread still signalled us.  Wait
-                  // for the semaphore (it _must_ have been signalled) to
-                  // decrement it again.  Return that we were signalled, not
-                  // that we timed out.
-                  LeaveCriticalSection(&_condition);
-                  result = WaitForSingleObject(me->cond_semaphore, INFINITE);
-               }
-               if (result != WAIT_OBJECT_0)
-                  throw condition_fatal(GetLastError());
-               _mutex->lock();
-               return 1;
-            }
-            INLINE void signal(void) {
-               EnterCriticalSection(&_condition);
-               if (waiting_head != thread_class::Null) {
-                  thread_class* t = waiting_head;
-                  waiting_head = t->cond_next;
-                  if (waiting_head == thread_class::Null)
-                     waiting_tail = thread_class::Null;
-                  else
-                     waiting_head->cond_prev = thread_class::Null;
-                  t->cond_waiting = FALSE;
-                  if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) {
-                     int rc = GetLastError();
-                     LeaveCriticalSection(&_condition);
-                     throw condition_fatal(rc);
-                  }
-               }
-               LeaveCriticalSection(&_condition);
-            }
-            INLINE void broadcast(void) {
-               EnterCriticalSection(&_condition);
-               while (waiting_head != thread_class::Null) {
-                  thread_class* t = waiting_head;
-                  waiting_head = t->cond_next;
-                  if (waiting_head == thread_class::Null)
-                     waiting_tail = thread_class::Null;
-                  else
-                     waiting_head->cond_prev = thread_class::Null;
-                  t->cond_waiting = FALSE;
-                  if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) {
-                     int rc = GetLastError();
-                     LeaveCriticalSection(&_condition);
-                     throw condition_fatal(rc);
-                  }
-               }
-               LeaveCriticalSection(&_condition);
-            }
-      };
-      class semaphore_class {
-         private:
-            HANDLE _semaphore;
-#ifndef WIN32_VC
-            const unsigned long SEMAPHORE_MAX = 0x7fffffff;
-#endif
-         public:
-            // interface to semaphores
-            static const semaphore_class* Null;
-            INLINE semaphore_class(const unsigned int initial) :
-              _semaphore(CreateSemaphore(NULL, initial, SEMAPHORE_MAX, NULL)) {
-               if (_semaphore == NULL) {
-                  DEBUG() << "thread_ipc_traits<\"nt\">::semaphore_class::semaphore_class : CreateSemaphore error "
-                          << GetLastError() << nend;
-                  throw semaphore_fatal(GetLastError());
-               }
-            }
-            INLINE ~semaphore_class(void) {
-               if (!CloseHandle(_semaphore)) {
-                  DEBUG() << "thread_ipc_traits<\"nt\">::semaphore_class::~semaphore_class : CloseHandle error "
-                          << GetLastError() << nend;
-                  throw semaphore_fatal(GetLastError());
-               }
-            }
-            INLINE void wait(void) {
-               if (WaitForSingleObject(_semaphore, INFINITE) != WAIT_OBJECT_0)
-                  throw semaphore_fatal(GetLastError());
-            }
-            INLINE int trywait(void) {
-               switch (WaitForSingleObject(_semaphore, 0)) {
-               case WAIT_OBJECT_0: return 1;
-               case WAIT_TIMEOUT: return 0;
-               }
-               throw semaphore_fatal(GetLastError());
-               return 0;  // never really gets here, but the compilers like it
-            }
-            INLINE void post(void) {
-               if (!ReleaseSemaphore(_semaphore, 1, NULL))
-                  throw semaphore_fatal(GetLastError());
-            }
-      };
-      class library_class {
-      public:
-        // interface to dynamically loaded libraries
-        static library_class* const Null;
-        INLINE library_class(std::string&) {
-          throw lib_load_invalid();
-        }
-        INLINE ~library_class(void) {
-          throw lib_load_invalid();
-        }
-        INLINE void* get_symbol(std::string&) {
-          throw lib_load_invalid();
-        }
-      };
-      // BROKEN!!  NOT FINISHED
-      class file_class {
-        //interface to file IO
-      public:
-        INLINE file_class(std::string& file) : _filename(file), _fhandle(NULL){};
-        INLINE file_class() : _filename(NULL), _fhandle(NULL) {};
-        INLINE ~file_class() { close(); }
-        INLINE void setFile(std::string& file) { _filename = file; close(); }
-        INLINE bool open(const int mode) {
-          close();
-          if (_filename.data() != NULL) {
-            switch(mode){
-            case 0: _fhandle = fopen(_filename.data(), "rb"); break;
-            case 1: _fhandle = fopen(_filename.data(), "wb"); break;
-            case 2: _fhandle = fopen(_filename.data(), "rwb"); break;
-            default: _fhandle = fopen(_filename.data(), "rb"); break;
-            }
-            if (_fhandle != NULL) return true;
-          }
-          return false;
-        }
-        INLINE void close(void) {
-          if (_fhandle != NULL) { fclose(_fhandle); _fhandle = NULL; }
-        }
-        /*
-        INLINE bool readin(MemBuf& buffer, int numBytes) {
-          BYTE* block = new BYTE[numBytes];
-          if (_fhandle != NULL){
-            fread(block, sizeof(BYTE), numBytes, _fhandle);
-            if (!ferror(_fhandle)){ buffer.addBack(block); delete [] block; return true; }
-          }
-          delete [] block;
-          return false;
-        }
-        INLINE bool writeout(MemBuf& buffer, int numBytes) {
-          BYTE* block = buffer.getBlock(0, numBytes);
-          if (_fhandle != NULL) {
-            fwrite(block, sizeof(BYTE), numBytes, _fhandle);
-            if (!ferror(_fhandle)) { delete [] block; return true; }
-          }
-          delete [] block;
-          return false;
-        }
-        INLINE bool readin(BYTE* block, int numBytes) {
-          if (_fhandle != NULL){
-            fread(block, sizeof(BYTE), numBytes, _fhandle);
-            if (!ferror(_fhandle)){ return true; }
-          }
-          return false;
-        }
-        INLINE bool writeout(BYTE* block, int numBytes) {
-          if (_fhandle != NULL) {
-            fwrite(block, sizeof(BYTE), numBytes, _fhandle);
-            if (!ferror(_fhandle)) { return true; }
-          }
-          return false;
-        }
-        */
-      private:
-        string _filename;
-        FILE* fhandle;
-      };
-      static INLINE mutex_class *make_mutex(void) {
-         return new mutex_class;
-      }
-      static INLINE condition_class *make_condition(mutex_class* m) {
-         return new condition_class(m);
-      }
-      static INLINE semaphore_class *make_semaphore(const unsigned int initial) {
-         return new semaphore_class(initial);
-      }
-      static INLINE thread_class *make_thread(void* data) {
-         return new thread_class(data);
-      }
-      static INLINE library_class *make_thread(std::string&) {
-        throw lib_load_invalid();
-      }
-      static INLINE file_class *make_file(std::string& file) {
-        return new file_class(file);
-      }
-      static INLINE void sleep(const unsigned long secs,
-                               const unsigned long nsecs = 0) {
-         const DWORD MAX_SLEEP_SECONDS = (DWORD)4294966; // (2**32-2)/1000
-         if (secs <= MAX_SLEEP_SECONDS) {
-            Sleep(secs * 1000 + nsecs / 1000000);
-            return;
-         }
-         DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;
-         for (DWORD i=0; i<no_of_max_sleeps; ++i)
-            Sleep(MAX_SLEEP_SECONDS * 1000);
-         Sleep((secs % MAX_SLEEP_SECONDS) * 1000 + nsecs / 1000000);
-      }
-      static INLINE void get_time(unsigned long& abs_secs,
-                                  unsigned long& abs_nsecs,
-                                  const unsigned long rel_secs = 0,
-                                  const unsigned long rel_nsecs = 0) {
-         get_time_now(&abs_secs, &abs_nsecs);
-         abs_nsecs += rel_nsecs;
-         abs_secs += rel_secs + abs_nsecs / 1000000000;
-         abs_nsecs = abs_nsecs % 1000000000;
-      }
-      static INLINE int set_atomic(int&, int) {
-        throw set_atomic_invalid();
-      }
-      static INLINE int inc_atomic(int&, int) {
-        throw inc_atomic_invalid();
-      }
-      static INLINE int dec_atomic(int&, int) {
-        throw dec_atomic_invalid();
-      }
-      // this really should be private, but it is annoying to make config a
-      // friend
-      static INLINE void __set_self_tls_index(DWORD i) {
-        self_tls_index = i;
-      }
-   private:
-      // other data specific to this implementation
-      static DWORD self_tls_index;
-      // and a special, bonus, NT implementation function
-      static const int days_in_preceding_months[12];
-      static const int days_in_preceding_months_leap[12];
-      static INLINE void get_time_now(unsigned long& abs_sec,
-                                      unsigned long& abs_nsec) {
-         SYSTEMTIME st;
-         GetSystemTime(&st);
-         abs_nsec = st.wMilliseconds * 1000000;
-         // this formula should work until the 1st of March 2100.  If this code
-         // is still in use by then, I pitty us all.
-         DWORD days = ((st.wYear - 1970) * 365 + (st.wYear - 1969) / 4
-                       + ((st.wYear % 4)
-                          ? days_in_preceding_months[st.wMonth - 1]
-                          : days_in_preceding_months_leap[st.wMonth - 1])
-                       + st.wDay - 1);
-         abs_sec = st.wSecond + 60 * (st.wMinute + 60 * (st.wHour + 24 * days));
-      }
-};
-
-#endif /* __IPC_NT_TRAITS_H__ */

+ 0 - 457
panda/src/ipc/ipc_posix_traits.h

@@ -1,457 +0,0 @@
-// Filename: ipc_posix_traits.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_POSIX_TRAITS_H__
-#define __IPC_POSIX_TRAITS_H__
-
-#include <pandabase.h>
-
-#if defined(__alpha__) && defined(__osf1__) || defined(__hpux__)
-// stop unnecessary definitions of TRY, etc on OSF
-#ifndef EXC_HANDLING
-#define EXC_HANDLING
-#endif /* EXC_HANDLING */
-#endif /* __alpha__, __hpux__ */
-
-// hack alert!
-#ifdef __GNUC__
-#define _MIT_POSIX_THREADS 1
-#define PthreadDraftVersion 7
-#define NoNanoSleep
-
-#include <unistd.h>
-/*
-extern "C" {
-void usleep(unsigned long);
-}
-*/
-#endif /* __GNUC__ */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-#include <pthread.h>
-
-#if (defined(__GLIBC__) && __GLIBC__ >= 2)
-// typedef of struct timeval and gettimeofday();
-#include <sys/time.h>
-#include <unistd.h>
-#endif /* __GLIBC__ */
-
-// #if defined(__linux__) && defined(_MIT_POSIX_THREADS)
-// #include <sys/timers.h>
-// #endif /* __linux__ & _MIT_POSIX_THREADS */
-
-#if defined(__sgi)
-#define PthreadSupportThreadPriority
-// this next is just a guess
-#define PthreadDraftVersion 10
-#include <sched.h>
-#endif
-
-#define THROW_FATAL(x, t) throw t##_fatal(x)
-#if (PthreadDraftVersion <= 6)
-#define ERRNO(x) (((x) != 0) ? (errno) : 0)
-#ifdef __VMS
-// pthread_setprio returns old priority on success (draft version 4:
-// OpenVms version < 7)
-#define THROW_ERRORS(x, t) { if ((x) == -1) THROW_FATAL(errno, t); }
-#else
-#define THROW_ERRORS(x, t) { if ((x) != 0) THROW_FATAL(errno, t); }
-#endif /* __VMS */
-#else
-#define ERRNO(x) (x)
-#define THROW_ERRORS(x, t) { int rc = (x); \
-                             if (rc != 0) THROW_FATAL(rc, t); }
-#endif /* PthreadDraftVersion 6 */
-#define THROW_ERRORS_G(x) THROW_ERRORS(x, ipc)
-#define THROW_ERRORS_M(x) THROW_ERRORS(x, mutex)
-#define THROW_ERRORS_C(x) THROW_ERRORS(x, condition)
-#define THROW_ERRORS_S(x) THROW_ERRORS(x, semaphore)
-#define THROW_ERRORS_T(x) THROW_ERRORS(x, thread)
-
-class EXPCL_PANDAEXPRESS ipc_traits {
-   public:
-      class mutex_class;
-      class condition_class;
-      class semaphore_class;
-      class thread_class;
-      class library_class;
-      class mutex_class {
-         private:
-            pthread_mutex_t _mutex;
-         public:
-            // interface to mutex
-            static mutex_class* const Null;
-            INLINE mutex_class(void) {
-#if (PthreadDraftVersion == 4)
-               THROW_ERRORS_M(pthread_mutex_init(&_mutex, pthread_mutexattr_default));
-#else
-               THROW_ERRORS_M(pthread_mutex_init(&_mutex, 0));
-#endif
-            }
-            INLINE ~mutex_class(void) {
-               THROW_ERRORS_M(pthread_mutex_destroy(&_mutex));
-            }
-            INLINE void lock(void) {
-               THROW_ERRORS_M(pthread_mutex_lock(&_mutex));
-            }
-            INLINE void unlock(void) {
-               THROW_ERRORS_M(pthread_mutex_unlock(&_mutex));
-            }
-            INLINE pthread_mutex_t* get_mutex(void) { return &_mutex; }
-      };
-      class condition_class {
-         private:
-            pthread_cond_t _condition;
-            mutex_class* _mutex;
-         public:
-            // interface to condition variables
-            static condition_class* const Null;
-            INLINE condition_class(mutex_class* m) : _mutex(m) {
-#if (PthreadDraftVersion == 4)
-               THROW_ERRORS_C(pthread_cond_init(&_condition, pthread_condattr_default));
-#else
-               THROW_ERRORS_C(pthread_cond_init(&_condition, 0));
-#endif
-            }
-            INLINE ~condition_class(void) {
-               THROW_ERRORS_C(pthread_cond_destroy(&_condition));
-            }
-            INLINE void wait(void) {
-               THROW_ERRORS_C(pthread_cond_wait(&_condition,
-                                                _mutex->get_mutex()));
-            }
-            INLINE int timedwait(const unsigned long secs,
-                                 const unsigned long nsecs) {
-               timespec rqts = { (long)secs, (long)nsecs };
-               int rc = ERRNO(pthread_cond_timedwait(&_condition,
-                                                     _mutex->get_mutex(),
-                                                     &rqts));
-               if (rc == 0)
-                  return 1;
-#if (PthreadsDraftVersion <= 6)
-               if (rc == EAGAIN)
-                  return 0;
-#endif
-               if (rc == ETIMEDOUT)
-                  return 0;
-               throw condition_fatal(rc);
-            }
-            INLINE void signal(void) {
-               THROW_ERRORS_C(pthread_cond_signal(&_condition));
-            }
-            INLINE void broadcast(void) {
-               THROW_ERRORS_C(pthread_cond_broadcast(&_condition));
-            }
-      };
-      class semaphore_class {
-         private:
-            mutex_class _mutex;
-            condition_class _condition;
-            int _value;
-            class mutex_class_lock {
-               public:
-                  INLINE mutex_class_lock(mutex_class& m) : _mutex(m) {
-                     _mutex.lock();
-                  }
-                  INLINE ~mutex_class_lock(void) { _mutex.unlock(); }
-               private:
-                  mutex_class& _mutex;
-            };
-         public:
-            // interface to semaphores
-            static semaphore_class* const Null;
-            INLINE semaphore_class(const unsigned int initial) : _mutex(),
-              _condition(&_mutex), _value(initial) {}
-            INLINE ~semaphore_class(void) {}
-            INLINE void wait(void) {
-               mutex_class_lock l(_mutex);
-               while (_value == 0)
-                  _condition.wait(&_mutex);
-               --_value;
-            }
-            INLINE int trywait(void) {
-               mutex_class_lock l(_mutex);
-               if (_value == 0) {
-                  return 0;
-               }
-               --_value;
-               return 1;
-            }
-            INLINE void post(void) {
-               mutex_class_lock l(_mutex);
-               if (_value == 0)
-                  _condition.signal();
-               ++_value;
-            }
-      };
-      class thread_class {
-         private:
-            pthread_t _thread;
-            void* _b_ptr; // a handle to hang a pointer back to the high-level
-                          // thread class on.  Gross, but I couldn't think of
-                          // a better way to do this reverse lookup.
-            void* (*_fn)(void*);
-            INLINE int priority_map(const int pri) {
-#ifdef PthreadSupportThreadPriority
-               switch (pri) {
-               case 0:
-                  return lowest_priority;
-               case 1:
-                  return normal_priority;
-               case 2:
-                  return highest_priority;
-               }
-#endif /* PthreadSupportThreadPriority */
-               throw thread_invalid();
-            }
-            static void* thread_wrapper(void*);
-         public:
-            // interface to threads
-            static thread_class* const Null;
-            INLINE thread_class(void* data) : _b_ptr(data) {}
-            INLINE ~thread_class(void) {}
-            INLINE void manual_init(void) {
-               _thread = pthread_self();
-#ifdef PthreadSupportPriority
-#if (PthreadDraftVersion == 4)
-               THROW_ERRORS_T(pthread_setprio(_thread,
-                                              priority_map(PRIORITY_NORMAL)));
-#elif (PthreadDraftVersion == 6)
-               pthread_attr_t attr;
-               pthread_attr_init(&attr);
-               THROW_ERRORS_T(pthread_attr_setprio(&attr,
-                                                   priority_map(PRIORITY_NORMAL)));
-               THROW_ERRORS_T(pthread_setschedattr(_thread, attr));
-#else
-               struct sched_param sparam;
-               sparam.sched_priority = priority_map(PRIORITY_NORMAL);
-               THROW_ERRORS_T(pthread_setschedparam(_thread, SCHED_OTHER,
-                                                    &param));
-#endif /* PthreadDraftVersion */
-#endif /* PthreadSupportPriority */
-            }
-            INLINE void start_pre(void* (*fn)(void*), const bool,
-                                  const int pri) {
-               _fn = fn;
-               pthread_attr_t attr;
-#if (PthreadDraftVersion == 4)
-               pthread_attr_create(&attr);
-#else
-               pthread_attr_init(&attr);
-#endif
-#if (PthreadDraftVersion == 8)
-               pthread_attr_setdetachedstate(&attr, PTHREAD_CREATE_UNDETACHED);
-#endif
-#ifdef PthreadSupportThreadPriority
-#if (PthreadDraftVersion <= 6)
-               THROW_ERRORS_T(pthread_attr_setprio(&attr, priority_map(pri)));
-#else
-               struct sched_param sparam;
-               sparam.sched_priority = priority_map(pri);
-               THROW_ERRORS_T(pthread_attr_setschedparam(&attr, &sparam));
-#endif
-#endif /* PthreadSupportThreadPriority */
-#if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
-               // we're going to require a larger stack size then the default
-               // (21120) on OSF/1
-               THROW_ERRORS_T(pthread_attr_setstacksize(&attr, 32768));
-#endif
-#if (PthreadDraftVersion == 4)
-               THROW_ERRORS_T(pthread_create(&_thread, attr, thread_wrapper,
-                                             (void*)this));
-               pthread_attr_delete(&attr);
-#else
-               THROW_ERRORS_T(pthread_create(&_thread, &attr, thread_wrapper,
-                                             (void*)this));
-               pthread_attr_destroy(&attr);
-#endif
-            }
-            INLINE void start_in(void) {
-               THROW_ERRORS_T(pthread_setspecific(self_key, this));
-            }
-            INLINE void start_post(const bool det, const int) {
-               if (det) {
-#if (PthreadDraftVersion <= 6)
-                  THROW_ERRORS_T(pthread_detach(&_thread));
-#else
-                  THROW_ERRORS_T(pthread_detach(_thread));
-#endif
-               }
-            }
-            INLINE void join(void** status) {
-               THROW_ERRORS_T(pthread_join(_thread, status));
-#if (PthreadDraftVersion == 4)
-               // With draft 4 pthreads implementations (HPUS 10.x and Digital
-               // Unix 3.2), you have to detach the thread after join.  If not,
-               // the storage for the thread will not be reclaimed.
-               THROW_ERRORS_T(pthread_detach(&_thread));
-#endif
-            }
-            INLINE void set_priority(const int pri) {
-#ifdef PthreadSupportThreadPriority
-#if (PthreadDraftVersion == 4)
-               THROW_ERRORS_T(pthread_setprio(_thread, priority_map(pri)));
-#elif (PthreadDraftVersion == 6)
-               pthread_attr_t attr;
-               pthread_attr_init(&attr);
-               THROW_ERRORS_T(pthread_attr_setprio(&attr, priority_map(pri)));
-               THROW_ERRORS_T(pthread_setschedattr(_thread, attr));
-#else
-               struct sched_param sparam;
-               sparam.sched_priority = priority_map(pri);
-               THROW_ERRORS_T(pthread_setschedparam(_thread, SCHED_OTHER,
-                                                    &sparam));
-#endif
-#endif /* PthreadSupportThreadPriority */
-            }
-            INLINE void* back_ptr(void) { return _b_ptr; }
-            static INLINE void exit(void* return_value) {
-               pthread_exit(return_value);
-            }
-            static INLINE thread_class* self(void) {
-               thread_class* me(thread_class::Null);
-#if (PthreadDraftVersion <= 6)
-               THROW_ERRORS_T(pthread_getspecific(self_key, (void**)&me));
-#else
-               me = (thread_class*)pthread_getspecific(self_key);
-#endif
-               return me;
-            }
-            static INLINE void yield(void) {
-#if (PthreadDraftVersion == 6)
-               pthread_yield(NULL);
-#elif (PthreadDraftVersion < 9)
-               pthread_yield();
-#else
-               THROW_ERRORS_T(sched_yield());
-#endif
-            }
-      };
-      class library_class {
-      public:
-        static library_class* const Null;
-        INLINE library_class(ConfigString&) {
-          throw lib_load_invalid();
-        }
-        INLINE ~library_class(void) {
-          throw lib_load_invalid();
-        }
-        INLINE void* get_symbol(ConfigString&) {
-          throw lib_load_invalid();
-        }
-      };
-      static INLINE mutex_class *make_mutex(void) {
-         return new mutex_class;
-      }
-      static INLINE condition_class *make_condition(mutex_class* m) {
-         return new condition_class(m);
-      }
-      static INLINE semaphore_class *make_semaphore(const unsigned int initial) {
-         return new semaphore_class(initial);
-      }
-      static INLINE thread_class *make_thread(void* data) {
-         return new thread_class(data);
-      }
-      static INLINE library_class *make_library(ConfigString&) {
-        throw lib_load_invalid();
-      }
-      static INLINE void sleep(const unsigned long secs,
-                               const unsigned long nsecs = 0) {
-         timespec rqts = { (long)secs, (long)nsecs};
-#ifndef NoNanoSleep
-         if (nanosleep(&rqts, (timespec*)NULL) != 0) {
-            throw ipc_fatal(errno);
-         }
-#else
-#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__)
-         if (pthread_delay_np(&rqts) != 0) {
-            throw ipc_fatal(errno);
-         }
-#elif defined(__linux__) || defined(__aix__)
-         // this seems terribly inaccurate, and should be re-examined
-         if (secs > 2000)
-            sleep(secs);
-         else
-            usleep(secs * 1000000 + (nsecs / 1000));
-#else
-         throw ipc_invalid();
-#endif
-#endif /* NoNanoSleep */
-      }
-      static INLINE void get_time(unsigned long& abs_secs,
-                                  unsigned long& abs_nsecs,
-                                  const unsigned long rel_secs = 0,
-                                  const unsigned long rel_nsecs = 0) {
-         timespec abs;
-#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__)
-         timespec rel;
-         rel.tv_sec = rel_secs;
-         rel.tv_nsec = rel_nsecs;
-         THROW_ERRORS_G(pthread_get_expiration_np(&rel, &abs));
-#else
-#if defined(__linux__) || defined(__aix__)
-         struct timeval tv;
-         gettimeofday(&tv, NULL);
-         abs.tv_sec = tv.tv_sec;
-         abs.tv_nsec = tv.tv_usec * 1000;
-#else
-         clock_gettime(CLOCK_REALTIME, &abs);
-#endif /* __linux__, __aix__, ... */
-         abs.tv_nsec += rel_nsecs;
-         abs.tv_sec += rel_secs + abs.tv_nsec / 1000000000;
-         abs.tv_nsec = abs.tv_nsec & 1000000000;
-#endif /* __osf1__, __alpha__, ... */
-         abs_secs = abs.tv_sec;
-         abs_nsecs = abs.tv_nsec;
-      }
-      static INLINE int set_atomic(int&, int) {
-        throw set_atomic_invalid();
-      }
-      static INLINE int inc_atomic(int&) {
-        throw inc_atomic_invalid();
-      }
-      static INLINE int dec_atomic(int&) {
-        throw dec_atomic_invalid();
-      }
-      // These should be private, but is annoying to make config a
-      // friend
-      static INLINE void __set_self_key(pthread_key_t k) {
-        self_key = k;
-      }
-      static INLINE void __set_lowest_priority(int p) {
-        lowest_priority = p;
-      }
-      static INLINE void __set_normal_priority(int p) {
-        normal_priority = p;
-      }
-      static INLINE void __set_highest_priority(int p) {
-        highest_priority = p;
-      }
-   private:
-      // other data specific to this implementation
-      static pthread_key_t self_key;
-#ifdef PthreadSupportThreadPriority
-      static int lowest_priority;
-      static int normal_priority;
-      static int highest_priority;
-#endif /* PthreadSupportThreadPriority */
-};
-
-#endif /* __IPC_POSIX_TRAITS_H__ */

+ 0 - 487
panda/src/ipc/ipc_ps2_traits.h

@@ -1,487 +0,0 @@
-// Filename: ipc_ps2_traits.h
-// Created by:  
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __ipc_ps2_traits_h__
-#define __ipc_ps2_traits_h__
-
-#include <stdio.h>
-#include <pandabase.h>
-#include <stdlib.h>
-#include <eekernel.h>
-#include "plist.h"
-#include "pvector.h"
-#include "pmap.h"
-
-// OK.  The deal with the PS2 is that there is native library thread support
-// for threads and semaphors.  Nothing else.  This is why mutex and condition
-// are based off of semaphore_class- there's no other way to have threads sleep
-// (instead of spin).
-
-// Spinning is VERY BAD on the PS2.  There's no time-sharing- it's based off of
-// priority.  Threads are tasked out when they enter WAIT (sleep) mode.  Threads
-// are NOT tasked out when they're banging a while loop.  If a thread is waiting
-// for a variable, but not sleeping, deadlock.
-
-class EXPCL_PANDAEXPRESS ipc_traits
-  {
-  public:
-
-    // prototype all of the classes here
-
-    class mutex_class;
-    class condition_class;
-    class semaphore_class;
-    class thread_class;
-    class library_class;
-
-    //// semaphore_class definition
-
-    class semaphore_class
-    {
-      private:
-
-        SemaParam m_sema_param;
-        int m_sema_id;
-
-        static const int sema_max_size = 32;
-
-      public:
-
-        static semaphore_class* const Null;
-
-        INLINE semaphore_class(const unsigned int initial = 1) {
-          m_sema_param.initCount = initial;
-          m_sema_param.maxCount = sema_max_size;
-          m_sema_param.option = 0;
-
-          m_sema_id = CreateSema(&m_sema_param);
-
-          if (m_sema_id < 0)
-            throw semaphore_fatal(-1);
-        }
-
-        INLINE ~semaphore_class(void) {
-          DeleteSema(m_sema_id);
-        }
-
-        INLINE void wait(void) {
-          int result;
-
-          result = WaitSema(m_sema_id);
-
-          // see if we overflowed the semaphore's queue
-
-          if (result != m_sema_id)
-            throw semaphore_fatal(-1);
-        }
-
-        INLINE int trywait(void) {
-          SemaParam sema_param;
-
-          // query the semaphor in question directly
-          // we can't use poll here, because if the semaphor is
-          // grabbable, poll will grab it.
-
-          ReferSemaStatus(m_sema_id, &sema_param);
-
-          if (sema_param.currentCount == 0)
-            return 1;
-
-          return 0;
-        }
-
-        INLINE void post(void) {
-          SignalSema(m_sema_id);
-        }
-    };
-
-    //// mutex_class definition
-
-    class mutex_class
-    {
-      private:
-
-        semaphore_class m_semaphore;
-
-      public:
-
-        static mutex_class* const Null;
-
-        inline mutex_class(void) {}
-        inline ~mutex_class(void) {}
-
-        inline void lock(void) {
-          m_semaphore.wait();
-        }
-
-        inline void unlock(void) {
-          m_semaphore.post();
-        }
-    };
-
-    //// condition_class definition
-
-    class condition_class
-    {
-      private:
-
-      // for an explanation of this bloody mess, see ipc_nt_traits.h
-      // cary's rant is more than sufficient.
-
-        class WaitingThread
-        {
-          public:
-
-          // note that the semaphor is being initialized to 0,
-          // meaning that a wait() on it will fail until someone
-          // else posts to it.
-
-            int semaphore_id;
-            int thread_id;
-        };
-
-        plist<WaitingThread> waiting_thread_list;
-        mutex_class list_access_lock;
-        mutex_class* _mutex;
-
-      public:
-
-        static condition_class* const Null;
-
-        INLINE condition_class(mutex_class *m) : _mutex(m) {}
-        INLINE ~condition_class(void) {}
-
-        INLINE void wait(void)
-        {
-          WaitingThread waiting_thread;
-          SemaParam sp;
-
-          sp.initCount = 0;
-          sp.maxCount = 1;
-
-          waiting_thread.semaphore_id = CreateSema(&sp);
-          waiting_thread.thread_id = GetThreadId();
-
-          // get the lock and add the current thread to the list.
-
-          list_access_lock.lock();
-          waiting_thread_list.push_back(waiting_thread);
-          list_access_lock.unlock();
-
-          // lock this thread away
-
-          _mutex->unlock();
-          WaitSema(waiting_thread.semaphore_id);
-          _mutex->lock();
-
-          // the thread is now sitting.
-          //
-          //
-          // when it gets here, it will have been released by signal/broadcast
-
-          DeleteSema(waiting_thread.semaphore_id);
-        }
-
-        INLINE int timedwait(const unsigned long secs,
-                             const unsigned long nsecs) {
-          return -1;
-        }
-
-        INLINE void signal(void)
-        {
-          WaitingThread first_in_line = waiting_thread_list.front();
-          waiting_thread_list.pop_front();
-
-          // release this node.
-
-          SignalSema(first_in_line.semaphore_id);
-        }
-
-        INLINE void broadcast(void)
-        {
-          plist<WaitingThread>::iterator begin = waiting_thread_list.begin();
-          plist<WaitingThread>::iterator end = waiting_thread_list.end();
-          plist<WaitingThread>::iterator cur = begin;
-
-          int s_id;
-
-          while (cur != end)
-          {
-            // touch/release this node
-
-            s_id = (*cur).semaphore_id;
-            SignalSema(s_id);
-
-            cur++;
-          }
-
-          // and now clear the list out.
-
-          waiting_thread_list.erase(begin, end);
-        }
-    };
-
-    //// thread_class definition
-
-    class thread_class
-    {
-      private:
-
-        void *_b_ptr;  // for reverse lookup
-        void *(*_fn)(void *);
-
-        struct ThreadParam m_thread_param;
-        int m_thread_id;
-        int m_priority;
-
-        static const int m_thread_stacksize = 16384;
-        char m_thread_stack[m_thread_stacksize] __attribute__ ((aligned(16)));
-
-        INLINE int priority_map(const int pri) {
-          switch (pri) {
-            case 2:
-              return 0;
-
-            case 0:
-              return 2;
-
-            case 1:
-            default:
-              return 1;
-          }
-        }
-
-        class pointer_lookup
-        {
-          public:
-
-            int thread_id;
-            thread_class *thread_ptr;
-        };
-
-        static pvector<pointer_lookup> thread_addr_vector;
-        static void thread_wrapper(void *);
-
-      public:
-
-        static thread_class *m_root_thread;
-
-        static void BuildRootThread(void)
-        {
-          static bool initialized = false;
-
-          // this will run once, and only once.  Config calls it.
-
-          if (initialized == true)
-            return;
-
-          // create the new root_thread placeholder
-
-          m_root_thread = new thread_class(NULL);
-
-          m_root_thread->_fn = NULL;
-          m_root_thread->m_thread_id = 1;
-          m_root_thread->m_priority = 0;
-
-          // now add it to the pointer lookup table
-
-          pointer_lookup root_pl;
-          root_pl.thread_id = 1;
-          root_pl.thread_ptr = m_root_thread;
-
-          thread_addr_vector.push_back(root_pl);
-          initialized = true;
-        }
-
-        static thread_class* const Null;
-
-        INLINE thread_class(void *data) : _b_ptr(data) {}
-
-        INLINE ~thread_class(void) {
-          cout.flush();
-          DeleteThread(GetThreadId());
-        }
-
-        INLINE void manual_init(void)
-        {
-          m_thread_id = GetThreadId();
-          set_priority(1);
-        }
-
-        INLINE void start_pre(void *(*fn)(void *), const bool, const int pri)
-        {
-          _fn = fn;
-          m_priority = priority_map(pri);
-
-          // set up the thread_param structure
-
-          m_thread_param.entry = thread_wrapper;
-          m_thread_param.stack = m_thread_stack;
-          m_thread_param.stackSize = m_thread_stacksize;
-          m_thread_param.initPriority = m_priority;
-          m_thread_param.gpReg = &_gp;
-
-          // write this info back to the cache.
-
-          FlushCache(0);
-
-          // create and register the thread
-
-          m_thread_id = CreateThread(&m_thread_param);
-
-          if (m_thread_id < 0)
-            throw thread_fatal(-1);
-
-          pointer_lookup pl;
-          pl.thread_id = m_thread_id;
-          pl.thread_ptr = this;
-
-          thread_addr_vector.push_back(pl);
-
-          // start the thread
-
-          StartThread(m_thread_id, (void *) this);
-        }
-
-        INLINE void start_in(void) {}
-        INLINE void start_post(const bool det, const int) {}
-        INLINE void *back_ptr(void) { return _b_ptr; }
-
-        static INLINE void exit(void *)
-        {
-          int id = GetThreadId();
-
-          pvector<pointer_lookup>::iterator cur;
-
-          for (cur = thread_addr_vector.begin(); cur != thread_addr_vector.end();
-               cur++)
-          {
-            if ((*cur).thread_id == id)
-            {
-              thread_addr_vector.erase(cur);
-              break;
-            }
-          }
-
-          ExitThread();
-        }
-
-      // WRITE ME (or maybe ... don't?)
-
-        INLINE void join(void **status) {}
-
-        INLINE void set_priority(const int pri)
-        {
-          m_priority = priority_map(pri);
-          ChangeThreadPriority(m_thread_id, m_priority);
-        }
-
-        static INLINE thread_class *self(void)
-        {
-          int id, result;
-
-          struct ThreadParam thread_param;
-          pvector<pointer_lookup>::iterator cur;
-
-          id = GetThreadId();
-
-          for (cur = thread_addr_vector.begin(); cur != thread_addr_vector.end();
-               cur++)
-          {
-            if ((*cur).thread_id == id)
-              return (*cur).thread_ptr;
-          }
-
-          return NULL;
-        }
-
-        static INLINE void yield(void)
-        {
-          int id, result, priority;
-          struct ThreadParam thread_param;
-
-          id = GetThreadId();
-          result = ReferThreadStatus(id, &thread_param);
-
-          // make sure this thread isn't thrashed.
-
-          if (result != id)
-            throw thread_fatal(-1);
-
-          priority = thread_param.currentPriority;
-          RotateThreadReadyQueue(priority);
-        }
-    };
-
-    //// library_class definition
-
-    class library_class
-    {
-      public:
-
-        static library_class* const Null;
-
-        INLINE library_class(ConfigString&) {
-          throw lib_load_invalid();
-        }
-
-        INLINE ~library_class(void) {
-          throw lib_load_invalid();
-        }
-
-        INLINE void* get_symbol(ConfigString&) {
-          throw lib_load_invalid();
-        }
-    };
-
-    //// timing stuff
-
-    static INLINE void sleep(const unsigned long secs,
-                             const unsigned long nsecs) {
-    }
-
-    static INLINE void get_time(unsigned long& abs_secs,
-                                unsigned long& abs_nsecs,
-                                const unsigned long rel_secs = 0,
-                                const unsigned long rel_nsecs = 0) {
-    }
-
-    //// generator stuff
-
-    static INLINE mutex_class *make_mutex(void) {
-      return new mutex_class;
-    }
-
-    static INLINE condition_class *make_condition(mutex_class *m) {
-      return new condition_class(m);
-    }
-
-    static INLINE semaphore_class *make_semaphore(unsigned int initial) {
-      return new semaphore_class(initial);
-    }
-
-    static INLINE thread_class *make_thread(void *data) {
-      return new thread_class(data);
-    }
-
-    static INLINE library_class *make_library(ConfigString& str) {
-      return new library_class(str);
-    }
-};
-
-#endif // __IPC_PS2_TRAITS_H__

+ 0 - 57
panda/src/ipc/ipc_semaphore.h

@@ -1,57 +0,0 @@
-// Filename: ipc_semaphore.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_SEMAPHORE_H__
-#define __IPC_SEMAPHORE_H__
-
-#include <pandabase.h>
-
-#include "ipc_traits.h"
-
-class EXPCL_PANDAEXPRESS base_semaphore {
-   public:
-      typedef ipc_traits traits;
-      typedef ipc_traits::semaphore_class semaphore_class;
-
-      static base_semaphore* const Null;
-      INLINE base_semaphore(const unsigned int initial = 1) :
-        _semaphore(traits::make_semaphore(initial)) {}
-      INLINE ~base_semaphore(void) { delete _semaphore; }
-      INLINE void wait(void) { _semaphore->wait(); }
-      INLINE int trywait(void) { return _semaphore->trywait(); }
-      INLINE void post(void) { _semaphore->post(); }
-      INLINE semaphore_class* get_semaphore(void) { return _semaphore; }
-   private:
-      semaphore_class *_semaphore;
-};
-
-class base_semaphore_lock {
-   public:
-      typedef base_semaphore semaphore;
-      INLINE base_semaphore_lock(semaphore& s) : _semaphore(s) {
-         _semaphore.wait();
-      }
-      INLINE ~base_semaphore_lock(void) { _semaphore.post(); }
-   private:
-      semaphore& _semaphore;
-};
-
-typedef base_semaphore semaphore;
-typedef base_semaphore_lock semaphore_lock;
-
-#endif /* __IPC_SEMAPHORE_H__ */

+ 0 - 249
panda/src/ipc/ipc_solaris_traits.h

@@ -1,249 +0,0 @@
-// Filename: ipc_solaris_traits.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_SOLARIS_TRAITS_H__
-#define __IPC_SOLARIS_TRAITS_H__
-
-#include <pandabase.h>
-
-#include <stdlib.h>
-#include <errno.h>
-#include <thread.h>
-
-#define THROW_FATAL(x, t) throw t##_fatal(x)
-#define THROW_ERRORS(x, t) { int rc = (x); \
-                             if (rc != 0) THROW_FATAL(rc, t); }
-#define THROW_ERRORS_G(x) THROW_ERRORS(x, ipc)
-#define THROW_ERRORS_M(x) THROW_ERRORS(x, mutex)
-#define THROW_ERRORS_C(x) THROW_ERRORS(x, condition)
-#define THROW_ERRORS_S(x) THROW_ERRORS(x, semaphore)
-#define THROW_ERRORS_T(x) THROW_ERRORS(x, thread)
-
-class EXPCL_PANDAEXPRESS ipc_traits {
-   public:
-      class mutex_class;
-      class condition_class;
-      class semaphore_class;
-      class thread_class;
-      class library_class;
-      class mutex_class {
-         private:
-            mutex_t _mutex;
-         public:
-            // interface to mutex
-            static const mutex_class* Null;
-            INLINE mutex_class(void) {
-               THROW_ERRORS_M(mutex_init(&_mutex, USYNC_THREAD, 0));
-            }
-            INLINE ~mutex_class(void) {
-               THROW_ERRORS_M(mutex_destroy(&_mutex));
-            }
-            INLINE void lock(void) {
-               THROW_ERRORS_M(mutex_lock(&_mutex));
-            }
-            INLINE void unlock(void) {
-               THROW_ERRORS_M(mutex_unlock(&_mutex));
-            }
-      };
-      class condition_class {
-         private:
-            cond_t _condition;
-            mutex_class *_mutex;
-         public:
-            // interface to condition variables
-            static const condition_class* Null;
-            INLINE condition_class(mutex_class* m) : _mutex(m) {
-               THROW_ERRORS_C(cond_init(&_condition, USYNC_THREAD, 0));
-            }
-            INLINE ~condition_class(void) {
-               THROW_ERRORS_C(cond_destroy(&_condition));
-            }
-            INLINE void wait(void) {
-               THROW_ERRORS_C(cond_wait(&_condition, _mutex->get_mutex()));
-            }
-            INLINE int timedwait(const unsigned long secs,
-                                 const unsigned long nsecs) {
-               timespec rqts = { secs, nsecs };
-               int rc = cond_timedwait(&_condition, _mutexm->get_mutex(),
-                                       &rqts);
-               if (rc == 0)
-                  return 1;
-               if (rc == ETIME)
-                  return 0;
-               throw condition_fatal(rc);
-            }
-            INLINE void signal(void) {
-               THROW_ERRORS_C(cond_signal(&_condition));
-            }
-            INLINE void broadcast(void) {
-               THROW_ERRORS_C(cond_broadcast(&_condition));
-            }
-      };
-      class semaphore_class {
-         private:
-            sema_t _semaphore;
-         public:
-            // interface to semaphores
-            static const semaphore_class* Null;
-            INLINE semaphore_class(const unsigned int initial) {
-               THROW_ERRORS_S(sema_init(&_semaphore, initial, USYNC_THREAD
-                                        NULL));
-            }
-            INLINE ~semaphore_class(void) {
-               THROW_ERRORS_S(sema_destroy(&_semaphore));
-            }
-            INLINE void wait(void) {
-               THROW_ERRORS_S(sema_wait(&_semaphore));
-            }
-            INLINE int trywait(void) {
-               // this is way not right, but I need access to a solaris box to
-               // see what it really should be.
-               THROW_ERRORS_S(sema_trywait(&_semaphore));
-            }
-            INLINE void post(void) {
-               THROW_ERRORS_S(sema_post(&_semaphore));
-            }
-      };
-      class thread_class {
-         private:
-            thread_t _thread;
-            void* _b_ptr; // a handle to hang a pointer back to the high-level
-                          // thread class on.  Gross, but I couldn't think of
-                          // a better way to do this reverse lookup.
-            void* (*_fn)(void*);
-            INLINE int priority_map(const int pri) {
-               switch (pri) {
-               case 0:
-               case 1:
-               case 2:
-                  return pri;
-               }
-               throw thread_invalid();
-               // shouldn't get here, but keeps the compiler happy
-               return 0;
-            }
-            static void* thread_wrapper(void*);
-         public:
-            // interface to threads
-            static const thread_class* Null;
-            INLINE thread_class(void* data) : _b_ptr(data) {}
-            INLINE ~thread_class(void) {}
-            INLINE void manual_init(void) {
-               _thread = thr_self();
-               THROW_ERRORS_T(thr_setprio(_thread, priority_map(PRIORITY_NORMAL)));
-            }
-            INLINE void start_pre(void* (*fn)(void*), const bool det,
-                                  const int) {
-               _fn = fn;
-               long flags = 0;
-               if (det)
-                  flags |= THR_DETACHED;
-               THROW_ERRORS_T(thr_create(0, 0, thread_wrapper, (void*)this,
-                                         flags, &_thread));
-            }
-            INLINE void start_in(void) {
-               THROW_ERRORS_T(thr_setspecific(self_key, this));
-            }
-            INLINE void start_post(const bool, const int pri) {
-               THROW_ERRORS_T(thr_setprio(_thread, priority_map(pri)));
-            }
-            INLINE void join(void** status) {
-               THROW_ERRORS_T(thr_join(_thread, (thraed_t*)NULL, status));
-            }
-            INLINE void set_priority(const int pri) {
-               THROW_ERRORS_T(thr_setprio(_thread, priority_map(pri)));
-            }
-            INLINE void* back_ptr(void) { return _b_ptr; }
-            static INLINE void exit(void* return_value) {
-               thr_exit(return_value);
-            }
-            static INLINE thread_class* self(void) {
-               thread_class* me = thread_class::Null;
-               THROW_ERRORS_T(thr_getspecific(self_key, (void**)&me));
-               return me;
-            }
-            static INLINE void yield(void) {
-               thr_yield();
-            }
-      };
-      class library_class {
-      public:
-        static library_class* const Null;
-        INLINE library_class(str&) {
-          throw lib_load_invalid();
-        }
-        INLINE ~library_class(void) {
-          throw lib_load_invalid();
-        }
-        INLINE void* get_symbol(str&) {
-          throw lib_load_invalid();
-        }
-      };
-      static INLINE mutex_class *make_mutex(void) {
-         return new mutex_class;
-      }
-      static INLINE condition_class *make_condition(mutex_class* m) {
-         return new condition_class(m);
-      }
-      static INLINE semaphore_class *make_semaphore(const unsigned int initial) {
-         return new semaphore_class(initial);
-      }
-      static INLINE thread_class *make_thread(void* data) {
-         return new thread_class(data);
-      }
-      static INLINE library_class *make_library(str&) {
-        throw lib_load_invalid();
-      }
-      static INLINE void sleep(const unsigned long secs,
-                               const unsigned long nsecs = 0) {
-         timespec rqts = { secs, nsecs };
-         if (nanosleep(&rqts, (timespec*)NULL) != 0)
-            throw ipc_fatal(errno);
-      }
-      static INLINE void get_time(unsigned long& abs_secs,
-                                  unsigned long& abs_nsecs,
-                                  const unsigned long rel_secs = 0,
-                                  const unsigned long rel_nsecs = 0) {
-         timespec abs;
-         clock_gettime(CLOCK_REALTIME, &abs);
-         abs.tv_nsec += rel_nsecs;
-         abs.tv_sec += rel_secs + abs.tv_nsec / 1000000000;
-         abs.tv_nsec = abs.tv_nsec & 1000000000;
-         abs_secs = abs.tv_sec;
-         abs_nsecs = abs.tv_nsec;
-      }
-      static INLINE int set_atomic(int&, int) {
-        throw set_atomic_invalid();
-      }
-      static INLINE int inc_atomic(int&) {
-        throw inc_atomic_invalid();
-      }
-      static INLINE int dec_atomic(int&) {
-        throw dec_atomic_invalid();
-      }
-      // This should probably be private, but it is annoying to make config a
-      // friend
-      static INLINE void __set_self_key(thread_key_t k) {
-        self_key = k;
-      }
-   private:
-      // other data specific to this implementation
-      static thread_key_t self_key;
-};
-
-#endif /* __IPC_SOLARIS_TRAITS_H__ */

+ 0 - 281
panda/src/ipc/ipc_thread.h

@@ -1,281 +0,0 @@
-// Filename: ipc_thread.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_THREAD_H__
-#define __IPC_THREAD_H__
-
-#include <pandabase.h>
-#include <stdio.h>
-
-#include "ipc_traits.h"
-#include "ipc_mutex.h"
-
-class EXPCL_PANDAEXPRESS base_thread {
-   public:
-      typedef ipc_traits traits;
-      typedef traits::thread_class thread_class;
-      typedef base_mutex mutex;
-      typedef base_mutex_lock mutex_lock;
-
-      // expand this to allow real priorities and scheduling.  determine the
-      // priority limits based on the scheduling.  If scheduling is not
-      // allowed, silently ignore those requests.
-      enum priority_t {
-         PRIORITY_LOW,
-         PRIORITY_NORMAL,
-         PRIORITY_HIGH
-      };
-
-      enum state_t {
-         STATE_NEW,       // thread exists, but hasn't started yet.
-         STATE_RUNNING,   // thread is running
-         STATE_TERMINATED // thread is done, but storage hasn't been reclaimed
-      };
-
-      static base_thread* const Null;
-      // Constructors set up the thread object but the thread won't start until
-      // start() is called.  The create(...) functions can be used to construct
-      // and start a thread in a single call.
-      //
-      // should be able to get rid of the voids here with clever templating.
-      INLINE base_thread(void (*fn)(void*), void* arg = (void*)0L,
-                         const priority_t pri = PRIORITY_NORMAL) :
-        _thread(thread_class::Null), _fn_void(fn), _fn_ret(0L), _mutex(),
-        _state(STATE_NEW), _priority(pri), _thread_arg(arg), _detached(true) {
-         common_constructor();
-      }
-      INLINE base_thread(void* (*fn)(void*), void* arg = (void*)0L,
-                         const priority_t pri = PRIORITY_NORMAL) :
-        _thread(thread_class::Null), _fn_void(0L), _fn_ret(fn), _mutex(),
-        _state(STATE_NEW), _priority(pri), _thread_arg(arg), _detached(false) {
-         common_constructor();
-      }
-      // causes this thread to start executing
-      INLINE void start(void) {
-         mutex_lock l(_mutex);
-         if (_state != STATE_NEW) {
-            cerr << "base_thread::start throwing thread_invalid()" << endl;
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         }
-         _thread = traits::make_thread(this);
-         _thread->start_pre(thread_wrapper, _detached, _priority);
-         _state = STATE_RUNNING;
-         _thread->start_post(_detached, _priority);
-      }
-      // causes the calling thread to wait for this thread's completion,
-      // putting the return value in the space passed by the parameter.  Only
-      // undetached threads may be joined.  Storage for the thread will be
-      // reclaimed when it exits.
-      // Again, clever templating should be able to eliminate this void
-      // nonsense.  It's gross!
-      INLINE void join(void** status) {
-         _mutex.lock();
-         if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
-            _mutex.unlock();
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         }
-         _mutex.unlock();
-         if (this == self())
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         if (_detached)
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         _thread->join(status);
-         delete this;
-      }
-      // set the priority of this thread
-      INLINE void set_priority(const priority_t pri) {
-         mutex_lock l(_mutex);
-         if (_state != STATE_RUNNING)
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         _thread->set_priority(pri);
-         _priority = pri;
-      }
-      // return this thread's priority
-      INLINE priority_t get_priority(void) {
-         mutex_lock l(_mutex);
-         // in a more general priority system, we should check that the thread
-         // is running at the priority we think it is.
-         return _priority;
-      }
-      // return this thread's state
-      INLINE state_t get_state(void) {
-         mutex_lock l(_mutex);
-         return _state;
-      }
-      // return this thread's id within the current process
-      INLINE int get_id(void) {
-         return _id;  // presumably this doesn't change
-      }
-      // causes the calling thread to exit, again the void action here is
-      // unhappy.
-      static INLINE void exit(void* return_value = (void*)0L) {
-        cout.flush();
-         base_thread* me = self();
-         if (me != (base_thread*)0L) {
-            me->_mutex.lock();
-            // if (me->_state != STATE_RUNNING)  non-fatal error
-            me->_state = STATE_TERMINATED;
-            me->_mutex.unlock();
-            if (me->_detached)
-               delete me;
-         }
-         thread_class::exit(return_value);
-      }
-      // returns the caller's thread object.  If the calling thread is not the
-      // main thread or created by us, thread_class::Null is returned
-      static INLINE base_thread* self(void) {
-        cout.flush();
-         thread_class* tclass=thread_class::self();
-         base_thread* ret=(base_thread*)0L;
-         if (tclass != thread_class::Null)
-            ret = (base_thread*)(tclass->back_ptr());
-         return ret;
-      }
-      // calling task releasing control to the scheduler
-      static INLINE void yield(void) {
-         thread_class::yield();
-      }
-      // sleep for the specified amount of time
-      static INLINE void sleep(const unsigned long secs,
-                               const unsigned long nsecs = 0) {
-         traits::sleep(secs, nsecs);
-      }
-      // calculates an absolute time in seconds and nanoseconds, suitable for
-      // use in timed_waits on condition variables, which is the current time
-      // plus the given relative offset.
-      static INLINE void get_time(unsigned long& abs_secs,
-                                  unsigned long& abs_nsecs,
-                                  const unsigned long rel_secs = 0,
-                                  const unsigned long rel_nsecs = 0) {
-         traits::get_time(abs_secs, abs_nsecs, rel_secs, rel_nsecs);
-      }
-      // shortcut function to create and start a thread in one call
-      static INLINE base_thread* create(void (*fn)(void*),
-                                        void* arg = (void*)0L,
-                                        const priority_t pri=PRIORITY_NORMAL) {
-         base_thread* t = new base_thread(fn, arg, pri);
-         t->start();
-         return t;
-      }
-      static INLINE base_thread* create(void* (*fn)(void*),
-                                        void* arg = (void*)0L,
-                                        const priority_t pri=PRIORITY_NORMAL) {
-         base_thread* t = new base_thread(fn, arg, pri);
-         t->start();
-         return t;
-      }
-      // a handle to the implementation specific thread, this really should
-      // NEVER be called from user code.
-      INLINE thread_class* get_thread(void) { return _thread; }
-   protected:
-      // this constructor is used in a derived class.  The thread will execute
-      // the run() or run_undetached() member functions depending on whether
-      // start() or start_undetached() is called, respectively.
-      INLINE base_thread(void* arg = (void*)0L,
-                         const priority_t pri = PRIORITY_NORMAL) :
-        _thread(thread_class::Null), _fn_void(0L), _fn_ret(0L), _mutex(),
-        _state(STATE_NEW), _priority(pri), _thread_arg(arg), _detached(true) {
-         common_constructor();
-      }
-      // can be used with the above constructor in a derived class to cause the
-      // thread to be undetached.  In this case the thread executes the
-      // run_undetached member function.
-      INLINE void start_undetached(void) {
-         if ((_fn_void != NULL) || (_fn_ret != NULL))
-#ifdef BROKEN_EXCEPTIONS
-            return;
-#else
-            throw thread_invalid();
-#endif /* BROKEN_EXCEPTIONS */
-         _detached = false;
-         start();
-      }
-      // destructor cannot be called by user (except via a derived class).
-      // Use exit() instead.  This also means a thread object must be allocated
-      // with new, it cannot be statically or automatically allocated.  The
-      // destructor of a class that inherits from thread<...> shouldn't be
-      // public either (otherwise the thread object can be destroyed while the
-      // underlying thread is still running (this is Bad(tm))).
-   virtual ~base_thread(void) {
-     delete _thread;
-   }
-
-   private:
-      thread_class *_thread;  // the implementation specific thread
-      void (*_fn_void)(void*);
-      void* (*_fn_ret)(void*);
-      mutex _mutex;  // used to protect members which can change after
-                     // construction.  ie: _state and _priority
-      state_t _state;
-      priority_t _priority;
-      int _id;
-      void* _thread_arg;
-      bool _detached;
-      static mutex* _next_id_mutex;
-      static int _next_id;
-
-      // can be overridden in a derived class.  When constructed using the
-      // constructor thread(void*, priority_t), these functions are called by
-      // start() and start_undetached() respectively.
-      virtual void run(void*);
-      virtual void* run_undetached(void*);
-      // implements the common parts of the constructors
-      INLINE void common_constructor(void) {
-         if (_next_id_mutex == (mutex *)0L) {
-            // ok, we're the first in here.
-            _next_id_mutex = new mutex;
-            base_thread* t = new base_thread;
-            if (t->_state != STATE_NEW) {
-               // FATAL() << "thread initialization: problem creating initial thread object" << nend;
-               ::exit(1);
-            }
-            t->_state = STATE_RUNNING;
-            t->_thread = traits::make_thread(t);
-            t->_thread->manual_init();
-            t->_thread->start_in();
-         }
-
-         mutex_lock l(*_next_id_mutex);
-         _id = _next_id++;
-      }
-      static void *thread_wrapper(void*);
-};
-
-typedef base_thread thread;
-
-#endif /* __IPC_THREAD_H__ */

+ 0 - 268
panda/src/ipc/ipc_traits.cxx

@@ -1,268 +0,0 @@
-// Filename: ipc_traits.cxx
-// Created by:  frang (06Apr00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "ipc_traits.h"
-
-Configure(ipc_trait);
-
-#if (__IPC_FLAVOR_DUJOUR_TOKEN__ == 0)
-
-// mach
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class*)0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class*)0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class*)0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class*)0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class*)0L;
-
-int ipc_traits::normal_priority;
-int ipc_traits::highest_priority;
-
-ConfigureFn(ipc_trait) {
-  // find base and max priority.  This is the inital thread, so the max
-  // priority of this thread also applies to any newly created thread.
-  kern_return_t error;
-  struct thread_sched_info info;
-  unsigned int info_count = THREAD_SCHED_INFO_COUNT;
-
-  error = thread_info(thread_self(), THREAD_SCHED_INFO, (thread_info_t)&info,
-                      &info_count);
-  if (error != KERN_SUCCESS) {
-    FATAL() << "ipc_traits(mach) initialization: error determining thread_info"
-            << nend;
-    ::exit(1);
-  } else {
-    ipc_traits::__set_normal_priority(info.base_priority);
-    ipc_traits::__set_highest_priority(info.max_priority);
-  }
-}
-
-void* ipc_traits::thread_class::thread_wrapper(void* data) {
-   ipc_traits::thread_class* me = (ipc_traits::thread_class*)data;
-   return (*me->_fn)(me->_b_ptr);
-}
-
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 1)
-
-// NT
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class*)0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class*)0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class*)0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class*)0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class*)0L;
-
-DWORD ipc_traits::self_tls_index;
-ipc_traits::condition_class::_internal_thread_dummy*
-  ipc_traits::condition_class::_internal_thread_helper::cache =
-    (ipc_traits::condition_class::_internal_thread_dummy*)0L;
-ipc_traits::mutex_class*
-  ipc_traits::condition_class::_internal_thread_helper::cachelock =
-    (ipc_traits::mutex_class*)0L;
-
-ConfigureFn(ipc_trait) {
-  DWORD tmp = TlsAlloc();
-  if (tmp == 0xffffffff)
-    throw ipc_fatal(GetLastError());
-  ipc_traigs::__set_self_tls_index(tmp);
-}
-
-#ifndef __BCPLUSPLUS__
-unsigned _stdcall ipc_traits::thread_class::thread_wrapper(void* data) {
-#else /* __BCPLUSPLUS__ */
-void _USERENTRY ipc_traits::thread_class::thread_wrapper(void* data) {
-#endif /* __BCPLUSPLUS__ */
-  ipc_traits::thread_class* me = (ipc_traits::thread_class*)data;
-  me->_return_value = (*me->_fn)(me->_b_ptr);
-#ifndef __BCPLUSPLUS__
-  return 0;
-#endif /* __BCPLUSPLUS__ */
-}
-
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 2)
-
-// posix
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class*)0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class*)0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class*)0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class*)0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class*)0L;
-
-pthread_key_t ipc_traits::self_key;
-#ifdef PthreadSupportThreadPriority
-int ipc_traits::lowest_priority;
-int ipc_traits::normal_priority;
-int ipc_traits::highest_priority;
-#endif /* PthreadSupportThreadPriority */
-
-ConfigureFn(ipc_trait) {
-#ifdef NeedPthreadInit
-  pthread_init();
-#endif /* NeedPthreadInit */
-
-  pthread_key_t ktmp;
-#if (PthreadDraftVersion == 4)
-  THROW_ERRORS_G(pthread_keycreate(&ktmp, NULL));
-#else /* PthreadDraftVersion 4 */
-  THROW_ERRORS_G(pthread_key_create(&ktmp, NULL));
-#endif /* PthreadDraftVersion 4 */
-  ipc_traits::__set_self_key(ktmp);
-
-#ifdef PthreadSupportThreadPriority
-  int plow, pnorm, phigh;
-#if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
-  plow = PRI_OTHER_MIN;
-  phigh = PRI_OTHER_MAX;
-#elif defined(__hpux__)
-  plow = PRI_OTHER_MIN;
-  phigh = PRI_OTHER_MAX;
-#elif defined(__sunos__) && (__OSVERSION__ == 5)
-  // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0
-  plow = 1;
-  phigh = 3;
-#else /* os testing */
-  plow = sched_get_priority_min(SCHED_FIFO);
-  phigh = sched_get_priority_max(SCHED_FIFO);
-#endif /* os testing */
-  switch (phigh - plow) {
-  case 0:
-  case 1:
-    pnorm = plow;
-    break;
-  default:
-    pnorm = plow + 1;
-    break;
-  }
-  ipc_traits::__set_lowest_priority(plow);
-  ipc_traits::__set_normal_priority(pnorm);
-  ipc_traits::__set_highest_priority(phigh);
-#endif /* PthreadSupportThreadPriority */
-}
-
-void* ipc_traits::thread_class::thread_wrapper(void* data) {
-  ipc_traits::thread_class* me = (ipc_traits::thread_class*)data;
-  return (*me->_fn)(me->_b_ptr);
-}
-
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 3)
-
-// solaris
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class*)0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class*)0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class*)0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class*)0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class*)0L;
-
-thread_key_t ipc_traits::self_key;
-
-ConfigureFn(ipc_trait) {
-  thread_key_t ktmp;
-  THROW_ERRORS_G(thr_keycreate(&ktmp, NULL));
-  ipc_traits::__set_self_key(ktmp);
-}
-
-void* ipc_traits::thread_class::thread_wrapper(void* data) {
-  ipc_traits::thread_class* me = (ipc_traits::thread_class*)data;
-  return (*me->_fn)(me->_b_ptr);
-}
-
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 4)
-
-// NSPR
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class*)0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class*)0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class*)0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class*)0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class*)0L;
-
-PRUintn ipc_traits::_data_index;
-
-ConfigureFn(ipc_trait) {
-  PRUintn tmp;
-  PR_NewThreadPrivateIndex(&tmp, (PRThreadPrivateDTOR)0L);
-  ipc_traits::__set_data_index(tmp);
-}
-
-void ipc_traits::thread_class::thread_wrapper(void* data) {
-  ipc_traits::thread_class* me = (ipc_traits::thread_class*)data;
-  me->_return_value = (*me->_fn)(me->_b_ptr);
-}
-
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 5)
-
-// PS2
-
-#include <eekernel.h>
-#include "pmap.h"
-
-ConfigureFn(ipc_trait) {
-  ipc_traits::thread_class::BuildRootThread();
-}
-
-pvector<ipc_traits::thread_class::pointer_lookup> ipc_traits::thread_class::thread_addr_vector;
-ipc_traits::thread_class *ipc_traits::thread_class::m_root_thread;
-
-ipc_traits::mutex_class* const ipc_traits::mutex_class::Null =
-  (ipc_traits::mutex_class *) 0L;
-ipc_traits::condition_class* const ipc_traits::condition_class::Null =
-  (ipc_traits::condition_class *) 0L;
-ipc_traits::semaphore_class* const ipc_traits::semaphore_class::Null =
-  (ipc_traits::semaphore_class *) 0L;
-ipc_traits::thread_class* const ipc_traits::thread_class::Null =
-  (ipc_traits::thread_class *) 0L;
-ipc_traits::library_class* const ipc_traits::library_class::Null =
-  (ipc_traits::library_class *) 0L;
-
-void ipc_traits::thread_class::thread_wrapper(void *data) {
-  ipc_traits::thread_class *me = (ipc_traits::thread_class *) data;
-  (*me->_fn)(me->_b_ptr);
-}
-
-#else /* out of flavor tokens */
-#error "invalid ipc flavor token"
-#endif /* out of flavor tokens */
-
-

+ 0 - 229
panda/src/ipc/ipc_traits.h

@@ -1,229 +0,0 @@
-// Filename: ipc_traits.h
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __IPC_TRAITS_H__
-#define __IPC_TRAITS_H__
-
-#include <pandabase.h>
-#include <string>
-
-// decide which IPC implementation to use.  This is so much fun, I just can't
-// hardly stand it.
-
-// Flavor tokens:
-//    0 - mach
-//    1 - nt
-//    2 - posix
-//    3 - solaris
-//    4 - NSPR
-//    5 - PS2
-
-
-// I threw PS2 in first because sometimes other env vars are set, but if PENV is PS2,
-// we're NEVER building anything else... CSN
-
-#if defined(PENV_PS2)
-
-#define __IPC_FLAVOR_DUJOUR__ PS2
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 5
-
-#elif defined(HAVE_NSPR)
-
-#define __IPC_FLAVOR_DUJOUR__ nspr
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 4
-
-#elif defined(__arm__) && defined(__atmos__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__alpha__) && defined(__osf1__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__powerpc__) && defined(__aix__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__hpux__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(WIN32_VC)
-
-#define __IPC_FLAVOR_DUJOUR__ nt
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 1
-
-#elif defined(__sun__)
-
-#ifdef UsePthreads
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-#else
-#define __IPC_FLAVOR_DUJOUR__ solaris
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 3
-#endif /* UsePthreads */
-
-#elif defined(__linux__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__nextstep__)
-
-#define __IPC_FLAVOR_DUJOUR__ mach
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 0
-
-#elif defined(__VMS)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__SINIX__)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#elif defined(__sgi)
-
-#define __IPC_FLAVOR_DUJOUR__ posix
-#define __IPC_FLAVOR_DUJOUR_TOKEN__ 2
-
-#else
-
-#error "Unable to determine which IPC implementation to use"
-#endif /* OS identification */
-
-// this exception is a general fatal exception from the IPC code
-class EXPCL_PANDAEXPRESS ipc_fatal {
-   public:
-      int error;
-      INLINE ipc_fatal(const int e = 0) : error(e) {}
-};
-
-// this exception is a general invalid value/function call exception for the
-// IPC code
-class EXPCL_PANDAEXPRESS ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the mutex code
-class EXPCL_PANDAEXPRESS mutex_fatal : public ipc_fatal {
-   public:
-      INLINE mutex_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when a mutex is called in an invalid state, or the
-// arguments to the call are invalid
-class EXPCL_PANDAEXPRESS mutex_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the condition
-// variable code
-class EXPCL_PANDAEXPRESS condition_fatal : public ipc_fatal {
-   public:
-      INLINE condition_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when a condition variable is called in an
-// invalid state, or the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS condition_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the semaphore code
-class EXPCL_PANDAEXPRESS semaphore_fatal : public ipc_fatal {
-   public:
-      INLINE semaphore_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when a semaphore is called in an invalid state, or
-// the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS semaphore_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the thread code
-class EXPCL_PANDAEXPRESS thread_fatal : public ipc_fatal {
-   public:
-      INLINE thread_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when a thread is called in an invalid state, or
-// the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS thread_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the atomic set
-// code
-class EXPCL_PANDAEXPRESS set_atomic_fatal : public ipc_fatal {
-public:
-  INLINE set_atomic_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when an atomic set is called in an invalid state,
-// or the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS set_atomic_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the atomic
-// increment code
-class EXPCL_PANDAEXPRESS inc_atomic_fatal : public ipc_fatal {
-public:
-  INLINE inc_atomic_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when an atomic increment is called in an invalid
-// state, or the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS inc_atomic_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the atomic
-// decrement code
-class EXPCL_PANDAEXPRESS dec_atomic_fatal : public ipc_fatal {
-public:
-  INLINE dec_atomic_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when an atomic decrement is called in an invalid
-// state, or the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS dec_atomic_invalid : public ipc_invalid {};
-
-// this exception is thrown in the event of a fatal error in the library load
-// code
-class EXPCL_PANDAEXPRESS lib_load_fatal : public ipc_fatal {
-public:
-  INLINE lib_load_fatal(const int e = 0) : ipc_fatal(e) {}
-};
-
-// this exception is thrown when a library load is called in an invalid state,
-// or the arguments to the call are invalid
-class EXPCL_PANDAEXPRESS lib_load_invalid : public ipc_invalid {};
-
-#include <dconfig.h>
-
-#if (__IPC_FLAVOR_DUJOUR_TOKEN__ == 0)
-#include "ipc_mach_traits.h"
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 1)
-#include "ipc_nt_traits.h"
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 2)
-#include "ipc_posix_traits.h"
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 3)
-#include "ipc_solaris_traits.h"
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 4)
-#include "ipc_nspr_traits.h"
-#elif (__IPC_FLAVOR_DUJOUR_TOKEN__ == 5)
-#include "ipc_ps2_traits.h"
-#else
-#error "invalid ipc flavor token"
-#endif /* loading trait specializations */
-
-#endif /* __IPC_TRAITS_H__ */

+ 0 - 85
panda/src/ipc/loom.cxx

@@ -1,85 +0,0 @@
-// Filename: loom.cxx
-// Created by:  cary (23Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "loom_internal.h"
-#include <algo.h>
-
-void app_service::DoIt(void* data)
-{
-   Action ret;
-   app_service* me = (app_service*)data;
-   unsigned long s = 0, n = 0;
-   condition_variable* c = condition_variable::Null;
-
-   me->_thread = thread::self();
-   if (me->_init != NULL)
-      (*me->_init)();
-   while ((ret = (*me->_service)(s, n, c)) != DONE) {
-      switch (ret) {
-      case RESERVICE:
-         break;  // we're about to do this anyway
-      case YIELD:
-         thread::yield();
-         break;
-      case SLEEP:
-         thread::sleep(s, n);
-         s = n = 0;
-         break;
-      case WAIT:
-         c->wait();
-         c = condition_variable::Null;
-         break;
-      }
-   }
-   if (me->_cleanup != NULL)
-      (*me->_cleanup)();
-   {
-      mutex_lock l(*main_thread_mutex);
-      me->_thread = thread::Null;
-      service_list::iterator i=find(task_list->begin(), task_list->end(), me);
-      if (i == task_list->end())
-         throw thread_fatal(-1);
-      task_list->erase(i);
-   }
-   thread::exit(NULL);
-}
-
-void RegisterAppService(vv_func init, av_func service, vv_func cleanup,
-                        vv_func info)
-{
-   app_service* app = new app_service(init, service, cleanup, info);
-   if (task_list == (service_list *)0L) {
-      task_list = new service_list;
-      main_thread_mutex = new mutex;
-   }
-   mutex_lock l(*main_thread_mutex);
-   task_list->push_back(app);
-}
-
-void SendMainThreadMessage(main_thread_message& m)
-{
-   main_thread_message *mess = new main_thread_message(m);
-   {
-      mutex_lock l(*message_mutex);
-      while (!main_thread_empty_flag)
-         main_thread_empty->wait();
-      message_to_main_thread = mess;
-      main_thread_empty_flag = false;
-      main_thread_full->signal();
-   }
-}

+ 0 - 74
panda/src/ipc/loom.h

@@ -1,74 +0,0 @@
-// Filename: loom.h
-// Created by:  cary (23Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __LOOM_H__
-#define __LOOM_H__
-
-#include <pandabase.h>
-
-#include "ipc_mutex.h"
-#include "ipc_condition.h"
-
-extern mutex main_thread_print_mutex;
-
-// interface to modules for being runable from app.
-
-enum Action { RESERVICE, DONE, YIELD, SLEEP, WAIT };
-
-typedef void (*vv_func)(void);
-typedef Action (*av_func)(unsigned long&, unsigned long&, condition_variable*&);
-
-// parameters in order are:
-//    initialization function - setup and data that the service function might
-//                              need in order to run
-//    service function - perform the task of this thing.  Either incrementally
-//                       (thus returning RESERVICE), or all at once (handling
-//                       yielding and waiting internally and returning DONE
-//                       when all it's work is complete).
-//    cleanup function - when the service function returns DONE, if this is not
-//                       NULL, this function will be called to cleanup whatever
-//                       is left to be done by this task.
-//    info function - if not NULL and the main thread is asked to tell about
-//                    what's running, this function will be called.  It is
-//                    expected that it will output something usefull about what
-//                    the task is and what it's doing.
-extern void RegisterAppService(vv_func, av_func, vv_func = (vv_func)0L,
-                               vv_func = (vv_func)0L);
-
-
-template <class str = std::string>
-class main_thread_message_base {
-   public:
-      enum message_t { LOAD, RESCAN, INFO };
-      INLINE main_thread_message_base(const message_t message, str s = "") :
-        _m(message), _lib(s) {}
-      INLINE main_thread_message_base(const main_thread_message_base& m) :
-        _m(m._m), _lib(m._lib) {}
-      INLINE ~main_thread_message_base(void) {}
-      INLINE message_t get_message(void) const { return _m; }
-      INLINE str get_lib(void) const { return _lib; }
-   private:
-      message_t _m;
-      str _lib;
-};
-
-typedef main_thread_message_base<> main_thread_message;
-
-extern void SendMainThreadMessage(main_thread_message&);
-
-#endif /* __LOOM_H__ */

+ 0 - 88
panda/src/ipc/loom_internal.h

@@ -1,88 +0,0 @@
-// Filename: loom_internal.h
-// Created by:  cary (23Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef __LOOM_INTERNAL_H__
-#define __LOOM_INTERNAL_H__
-
-#include <pandabase.h>
-
-#include "loom.h"
-#include "ipc_mutex.h"
-#include "ipc_condition.h"
-#include "ipc_thread.h"
-#include "plist.h"
-
-class app_service;
-
-typedef std::plist<app_service*> service_list;
-
-extern service_list *task_list;
-extern mutex *main_thread_mutex;
-
-class app_service {
-   private:
-      vv_func _init, _cleanup, _info;
-      av_func _service;
-      thread* _thread;
-
-      INLINE app_service(void) {}
-      INLINE ~app_service(void) {}
-      static void DoIt(void*);
-   public:
-      INLINE app_service(vv_func init, av_func service, vv_func cleanup,
-                         vv_func info) : _init(init), _service(service),
-                         _cleanup(cleanup), _info(info), _thread(thread::Null)
-         {}
-      INLINE bool started() {
-         return (_thread != thread::Null);
-      }
-      INLINE void start(void) {
-         if (!this->started())
-            thread::create(DoIt, (void*)this);
-      }
-      INLINE void info(void) {
-         // this probably should mutex lock the task_list while checking things
-         if (_info != (vv_func)0L)
-            (*_info)();
-         if (_thread != thread::Null) {
-            cerr << "thread is currently running.  Id = " << _thread->get_id()
-                 << ".  Current state = ";
-            switch (_thread->get_state()) {
-            case thread::STATE_NEW:
-               cerr << "New.";
-               break;
-            case thread::STATE_RUNNING:
-               cerr << "Running.";
-               break;
-            case thread::STATE_TERMINATED:
-               cerr << "Terminated";
-               break;
-            }
-            cerr << endl;
-         } else
-            cerr << "thread not started or created yet." << endl;
-      }
-};
-
-extern main_thread_message* message_to_main_thread;
-extern mutex* message_mutex;
-extern condition_variable* main_thread_full;
-extern condition_variable* main_thread_empty;
-extern bool main_thread_empty_flag;
-
-#endif /* __LOOM_INTERNAL_H__ */

+ 0 - 97
panda/src/ipc/loom_main.cxx

@@ -1,97 +0,0 @@
-// Filename: loom_main.cxx
-// Created by:  cary (23Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "loom_internal.h"
-#include <dconfig.h>
-#include <load_dso.h>
-#include <filename.h>
-
-#include <string>
-
-mutex main_thread_print_mutex;
-
-service_list *task_list = (service_list *)0L;
-mutex *main_thread_mutex = mutex::Null;
-main_thread_message* message_to_main_thread = (main_thread_message*)0L;
-mutex *message_mutex;
-condition_variable* main_thread_full = condition_variable::Null;
-condition_variable* main_thread_empty = condition_variable::Null;
-bool main_thread_empty_flag;
-
-int main(int argc, char** argv)
-{
-   for (int i=0; i<argc; ++i)
-      if (argv[i] != (char*)0L) {
-         Filename filename = argv[i];
-         if (filename.get_extension() == ".so") {
-           filename.set_type(Filename::T_dso);
-           load_dso(filename);
-         }
-      }
-   if (task_list == (service_list*)0L) {
-      // really, this shouldn't happen.  But if none of the loaded SOs do
-      // anything, well, we should just exit.
-      cerr << "None of the loaded SOs had any work to do." << endl;
-      return 0;
-   }
-
-   message_mutex = new mutex;
-   main_thread_full = new condition_variable(*message_mutex);
-   main_thread_empty = new condition_variable(*message_mutex);
-   main_thread_empty_flag = true;
-
-   main_thread_mutex->lock();
-   service_list::iterator j;
-   for (j=task_list->begin(); j!=task_list->end(); ++j)
-      (*j)->start();
-   main_thread_mutex->unlock();
-
-   while (!task_list->empty()) {
-      unsigned long s, n;
-      mutex_lock l(*message_mutex);
-      thread::get_time(s, n, 2, 0);  // 2 seconds from now
-      main_thread_full->timedwait(s, n);
-      if (!main_thread_empty_flag) {
-         switch (message_to_main_thread->get_message()) {
-         case main_thread_message::LOAD:
-            {
-              Filename filename = message_to_main_thread->get_lib();
-              filename.set_type(Filename::F_dso);
-              load_dso(filename);
-            }
-         case main_thread_message::RESCAN:
-            for (j=task_list->begin(); j!=task_list->end(); ++j)
-               (*j)->start();
-            break;
-         case main_thread_message::INFO:
-            for (j=task_list->begin(); j!=task_list->end(); ++j)
-               (*j)->info();
-            break;
-         default:
-            // really should never be here
-            break;
-         }
-         delete message_to_main_thread;
-         message_to_main_thread = (main_thread_message*)0L;
-         main_thread_empty_flag = true;
-         main_thread_empty->signal();
-      }
-   }
-   thread::sleep(0, 500000000); // give some time for cleanup (1/2 sec)
-   thread::exit(NULL);
-}

+ 0 - 163
panda/src/ipc/loom_test1.cxx

@@ -1,163 +0,0 @@
-// Filename: loom_test1.cxx
-// Created by:  cary (30Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "loom.h"
-#include <dconfig.h>
-
-static int test1_phase;
-static int test1_phase2;
-static mutex loom_test1_mutex;
-static condition_variable loom_test1_cond(loom_test1_mutex);
-
-#define PRINT(x) { mutex_lock l(main_thread_print_mutex); x; }
-
-void loom_test1_init2(void)
-{
-   PRINT(cerr << "In loom_test1_init2" << endl);
-   test1_phase2 = 0;
-}
-
-Action loom_test1_service2(unsigned long& s, unsigned long& n,
-                           condition_variable*&)
-{
-   if (test1_phase2 == 0) {
-      test1_phase2 = 1;
-      s = 4;
-      PRINT(cerr << "loom_test1_service2: sleeping for 4 seconds" << endl);
-      return SLEEP;
-   } else if (test1_phase2 == 1) {
-      test1_phase2 = 2;
-      PRINT(cerr << "loom_test1_service2: signaling loom_test1_service to continue" << endl);
-      loom_test1_cond.signal();
-      n = 500000000;
-      PRINT(cerr << "loom_test1_service2: sleeping for 1/2 second" << endl);
-      return SLEEP;
-   } else if (test1_phase2 == 2) {
-      test1_phase2 = 3;
-      PRINT(cerr << "loom_test1_service2: sending INFO message to main thread" << endl);
-      main_thread_message m(main_thread_message::INFO);
-      SendMainThreadMessage(m);
-      PRINT(cerr << "loom_test1_service2: returning RESERVICE" << endl);
-      return RESERVICE;
-   } else if (test1_phase2 == 3) {
-      if (test1_phase < 19) {
-         PRINT(cerr << "loom_test1_service2: returning RESERVICE" << endl);
-         return RESERVICE;
-      } else {
-         test1_phase2 = 4;
-         PRINT(cerr << "loom_test1_service2: sending INFO message to main thread" << endl);
-         main_thread_message m(main_thread_message::INFO);
-         SendMainThreadMessage(m);
-         PRINT(cerr << "loom_test1_service2: sleeping for 3/4 second" << endl);
-         n = 750000000;
-         return SLEEP;
-      }
-   } else {
-      PRINT(cerr << "loom_test1_service2: returning DONE" << endl);
-      return DONE;
-   }
-}
-
-void loom_test1_cleanup2(void)
-{
-   PRINT(cerr << "In loom_test1_cleanup2" << endl);
-}
-
-void loom_test1_init(void)
-{
-   PRINT(cerr << "In loom_test1_init" << endl);
-   test1_phase = 0;
-}
-
-Action loom_test1_service(unsigned long& s, unsigned long& n,
-                          condition_variable*& c)
-{
-   ++test1_phase;
-   switch (test1_phase) {
-   case 5:
-      PRINT(cerr << "loom_test1_service: returning YIELD to service manager" << endl);
-      return YIELD;
-   case 7:
-      s = 5;
-      PRINT(cerr << "loom_test1_service: returning SLEEP to service manager (s=5)" << endl);
-      return SLEEP;
-   case 9:
-      PRINT(cerr << "loom_test1_service: registering loom_test1_service2, etc, and returning YIELD" << endl);
-      RegisterAppService(loom_test1_init2, loom_test1_service2, loom_test1_cleanup2);
-      return YIELD;
-   case 11:
-      {
-         PRINT(cerr << "loom_test1_service: sending RESCAN message to main thread, returning YIELD" << endl);
-         main_thread_message m(main_thread_message::RESCAN);
-         SendMainThreadMessage(m);
-         return YIELD;
-      }
-   case 13:
-      PRINT(cerr << "loom_test1_service: returning WAIT to service manager" << endl);
-      loom_test1_mutex.lock();
-      c = &loom_test1_cond;
-      return WAIT;
-   case 15:
-      n = 500000000;
-      PRINT(cerr << "loom_test1_service: returning SLEEP (n=500000000)" << endl);
-      return SLEEP;
-   case 17:
-      {
-         PRINT(cerr << "loom_test1_service: sending LOAD message to main thread (libloom_test2.so)" << endl);
-         main_thread_message m(main_thread_message::LOAD, "libloom_test2.so");
-         SendMainThreadMessage(m);
-         s = 3;
-         PRINT(cerr << "loom_test1_service: returning SLEEP (s=3)" << endl);
-         return SLEEP;
-      }
-   case 19:
-      {
-         PRINT(cerr << "loom_test1_service: sending INFO message to main thread" << endl);
-         main_thread_message m(main_thread_message::INFO);
-         SendMainThreadMessage(m);
-         n = 500000000;
-         PRINT(cerr << "loom_test1_service: returning SLEEP (s=3)" << endl);
-         return SLEEP;
-      }
-   case 23:
-      PRINT(cerr << "loom_test1_service: returning DONE to service manager" << endl);
-      return DONE;
-   default:
-      PRINT(cerr << "loom_test1_service: returning RESERVICE to service manager" << endl);
-      return RESERVICE;
-   };
-}
-
-void loom_test1_cleanup(void)
-{
-   PRINT(cerr << "In loom_test1_cleanup" << endl);
-}
-
-void loom_test1_info(void)
-{
-   PRINT(cerr << "Loom_test1_info function (phase = " << test1_phase << ")" << endl);
-}
-
-
-Configure(loom_test1);
-
-ConfigureFn(loom_test1)
-{
-   RegisterAppService(loom_test1_init, loom_test1_service, loom_test1_cleanup,
-                      loom_test1_info);
-}

+ 0 - 54
panda/src/ipc/loom_test2.cxx

@@ -1,54 +0,0 @@
-// Filename: loom_test2.cxx
-// Created by:  cary (30Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "loom.h"
-#include <dconfig.h>
-
-static int test2_phase;
-
-#define PRINT(x) { mutex_lock l(main_thread_print_mutex); x; }
-
-void loom_test2_init(void)
-{
-   PRINT(cerr << "In loom_test2_init" << endl);
-   test2_phase = 0;
-}
-
-Action loom_test2_service(unsigned long& s, unsigned long&,
-                          condition_variable*&)
-{
-   ++test2_phase;
-   switch (test2_phase) {
-   case 0:
-      s = 5;
-      PRINT(cerr << "loom_test2_service: sleeping for 5 seconds" << endl);
-      return SLEEP;
-   case 3:
-      PRINT(cerr << "loom_test2_service: returning DONE" << endl);
-      return DONE;
-   default:
-      PRINT(cerr << "loom_test2_service: returning RESERVICE" << endl);
-      return RESERVICE;
-   }
-}
-
-Configure(loom_test2);
-ConfigureFn(loom_test2)
-{
-   RegisterAppService(loom_test2_init, loom_test2_service);
-}

+ 0 - 152
panda/src/ipc/test_diners.cxx

@@ -1,152 +0,0 @@
-// Filename: test_diners.cxx
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-// A solution to the infamous dining philosophers, implemented using the
-// threading abstraction.  This program exercises thread creation and
-// destruction, mutexes, and condition variables.
-
-#include <pandabase.h>
-#include <stdlib.h>
-#include "ipc_thread.h"
-#include "ipc_condition.h"
-
-#ifdef WIN32_VC
-static int last_rand = 0;
-#endif /* __WIN32__ */
-
-static mutex rand_mutex;
-
-static int random_l(void)
-{
-   mutex_lock l(rand_mutex);
-   int i = rand();
-#ifdef WIN32_VC
-   last_rand = i;
-#endif /* __WIN32__ */
-   return i;
-}
-
-static mutex print_mutex;
-
-#define PRINTMSG(x) { mutex_lock l(print_mutex); x; }
-
-// n philosophers sharing n chopsticks.  Philosophers are poor folk and can't
-// afford luxuries like 2 chopsticks per person.
-#define N_DINERS 5
-
-static mutex chopsticks[N_DINERS];
-
-// At most n philosophers are allowed into the room, others would have to
-// wait at the door.  This restriction demonstrates the use of condition
-// variables.
-
-static mutex room_mutex;
-
-static condition_variable room_condition(room_mutex);
-static int room_occupancy = 0;
-
-static class philosopher* phils[N_DINERS];
-
-class philosopher : public thread {
-   private:
-      void run(void* arg) {
-         int id = *(int*)arg;
-         delete (int*)arg;
-#ifdef WIN32_VC
-         rand_mutex.lock();
-         srand(last_rand);
-         rand_mutex.unlock();
-#endif /* __WIN32__ */
-         int l = id;
-         int r = l+1;
-         if (r == N_DINERS)
-            r = 0;
-         if (l & 1) {
-            int t = l;
-            l = r;
-            r = t;
-         }
-         PRINTMSG(cerr << "Philosopher #" << id << " has entered the room."
-                  << endl);
-         int count = random_l() % 10 + 1;
-         while (--count) {
-            chopsticks[l].lock();
-            chopsticks[r].lock();
-            PRINTMSG(cerr << "Philosopher #" << id
-                     << " is eating spaghetti now." << endl);
-            thread::sleep(random_l()%2, random_l()%1000000000);
-            chopsticks[l].unlock();
-            chopsticks[r].unlock();
-            PRINTMSG(cerr << "Philosopher #" << id
-                     << " is pondering about life." << endl);
-            thread::sleep(random_l()%2, random_l()%1000000000);
-         }
-         room_mutex.lock();
-         --room_occupancy;
-         phils[id] = (philosopher*)0L;
-         room_mutex.unlock();
-         room_condition.signal();
-         PRINTMSG(cerr << "Philosopher #" << id << " has left the room ("
-                  << room_occupancy << " left)." << endl);
-      }
-
-      // the destructor of a class that inherits from thread should never be
-      // public (otherwise the thread object can be destroyed while the
-      // underlying thread is still running).
-      ~philosopher(void) {}
-      inline void* make_arg(const int i) { return (void*)new int(i); }
-   public:
-      philosopher(const int id) : thread(make_arg(id)) {
-         start();
-      }
-};
-
-int main(int, char**)
-{
-   int i;
-   room_mutex.lock();
-   for (i=0; i<N_DINERS; ++i)
-      phils[i] = new philosopher(i);
-   room_occupancy = N_DINERS;
-   while (1) {
-      while (room_occupancy == N_DINERS) {
-         PRINTMSG(cerr << "main thread about to block " << room_occupancy
-                  << endl);
-         room_condition.wait();
-      }
-      // hmm.. someone left the room.
-      room_mutex.unlock();
-      // sleep for a while and then create a new philosopher
-      PRINTMSG(cerr << "main thread sleep" << endl);
-      thread::sleep(1, 200000000);
-      PRINTMSG(cerr << "main thread wake up" << endl);
-      room_mutex.lock();
-      for (i=0; i<N_DINERS; ++i)
-         if (phils[i] == (philosopher*)0L)
-            break;
-      if (i == N_DINERS) {
-         PRINTMSG(cerr
-                  << "Contrary to what I was tolk, no one has left the room!!!"
-                  << endl);
-         PRINTMSG(cerr << "I give up!" << endl);
-         exit(1);
-      }
-      phils[i] = new philosopher(i);
-      ++room_occupancy;
-   }
-}

+ 0 - 81
panda/src/ipc/test_file.cxx

@@ -1,81 +0,0 @@
-// Filename: test_file.cxx
-// Created by:  jason (05Sep00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include <pandabase.h>
-#include "ipc_file.h"
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <notify.h>
-
-#define _ERROR_TEST
-
-int main(int argc, char* argv[])
-{
-  //Test the writing capabilities
-  string test_file("test.out");
-  string test_data("Jason Michael Clark");
-
-  Datagram test_out;  test_out.add_string(test_data);
-  datagram_file stream(test_file);
-
-  nout << "WRITE TEST" << endl;
-  nout << "Opening file for writing: " << test_file  << endl;
-  if (!stream.open(file::FILE_WRITE)) nout << "Didn't open!" << endl;
-  nout << "Writing datagram with data: " << test_data << endl;
-  if (!stream.put_datagram(test_out)) nout << "Error in writing!" << endl;
-  nout << "Closing file: " << test_file << endl;
-  stream.close();
-
-  //Test the reading capabilites
-  Datagram test_in;
-
-  nout << "READ TEST" << endl;
-  nout << "Opening file for reading: " << test_file << endl;
-  if (!stream.open(file::FILE_READ)) nout << "Didn't open!" << endl;
-  if (!stream.get_datagram(test_in)) nout << "Error reading!" << endl;
-  DatagramIterator scan(test_in);
-  nout << "Read datagram with data: " << scan.get_string() << endl;
-  nout << "Closing file: " << test_file << endl;
-  stream.close();
-
-#ifdef _ERROR_TEST
-  //Test error handling
-  Datagram test_error;
-
-  nout << "ERROR TEST" << endl;
-  nout << "Opening file for writing: " << test_file  << endl;
-  stream.open(file::FILE_WRITE);
-  nout << "Trying to read datagram with data: " << endl;
-  stream.get_datagram(test_error);
-  nout << "Closing file: " << test_file << endl;
-  stream.close();
-  nout << "Opening file for reading: " << test_file  << endl;
-  stream.open(file::FILE_READ);
-  nout << "Trying to write datagram with data: " << test_data << endl;
-  test_error.add_string(test_data);
-  stream.put_datagram(test_error);
-  nout << "Closing file: " << test_file << endl;
-  stream.close();
-#endif
-
-  return 1;
-}
-
-
-
-

+ 0 - 94
panda/src/ipc/test_priority.cxx

@@ -1,94 +0,0 @@
-// Filename: test_priority.cxx
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include <pandabase.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "ipc_thread.h"
-
-// test thread priorities
-
-#if defined(__arm__) && defined(__atmos__)
-#define flush ""
-#endif /* __arm__ */
-
-static void func(void*);
-
-static int loop_iterations;
-
-static mutex print_mutex;
-#define PRINTMSG(x) { mutex_lock l(print_mutex); x << flush; }
-
-int main(int argc, char** argv)
-{
-   unsigned long s1, s2, n1, n2;
-   char buf[20];
-
-   if ((argc != 2) || (argv[1][0] == '-')) {
-      cerr << "Usage: " << argv[0] << " loop_iterations" << endl;
-      exit(1);
-   }
-   loop_iterations = atoi(argv[1]);
-   thread::get_time(s1, n1);
-   for (int i=0; i<loop_iterations; ++i);
-   thread::get_time(s2, n2);
-   if (n2 > n1) {
-      n2 -= n1;
-      s2 -= s1;
-   } else {
-      n2 = n2 + 1000000000 - n1;
-      s2 = s2 - 1 - s1;
-   }
-   sprintf(buf, "%d.%03d", s2, n2/1000000);
-   cout << argv[0] << ": doing " << loop_iterations
-        << " loop itterations (approx " << buf << " seconds per loop)"
-        << endl;
-   PRINTMSG(cout << "main: creating h1" << endl);
-   thread::create(func, (void*)"h1", thread::PRIORITY_HIGH);
-   PRINTMSG(cout << "main: creating m1" << endl);
-   thread::create(func, (void*)"m1", thread::PRIORITY_NORMAL);
-   PRINTMSG(cout << "main: creating l1" << endl);
-   thread::create(func, (void*)"l1", thread::PRIORITY_LOW);
-   PRINTMSG(cout << "main: creating h2" << endl);
-   thread::create(func, (void*)"h2", thread::PRIORITY_HIGH);
-   PRINTMSG(cout << "main: creating m2" << endl);
-   thread::create(func, (void*)"m2", thread::PRIORITY_NORMAL);
-   PRINTMSG(cout << "main: creating l2" << endl);
-   thread::self()->set_priority(thread::PRIORITY_LOW);
-   func((void*)"l2");
-
-   return 0;
-}
-
-static void func(void* arg)
-{
-   char *name = (char *)arg;
-
-   while (1) {
-      PRINTMSG(cout << name << ": entering 1st compute-bound loop" << endl);
-      int i;
-      for (i=0; i<loop_iterations; ++i);
-      PRINTMSG(cout << name << ": left compute-bound loop; yielding" << endl);
-      thread::yield();
-      PRINTMSG(cout << name << ": entering 2nd compute-bound loop" << endl);
-      for (i=0; i<loop_iterations; ++i);
-      PRINTMSG(cout << name
-               << ": left compute-bound loop; sleeping for 2 seconds" << endl);
-      thread::sleep(2);
-   }
-}

+ 0 - 106
panda/src/ipc/test_prodcons.cxx

@@ -1,106 +0,0 @@
-// Filename: test_prodcons.cxx
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include <pandabase.h>
-#include <stdlib.h>
-#include "ipc_thread.h"
-#include "ipc_condition.h"
-#include "ipc_mutex.h"
-
-// test condition variables and timed waits.  makes 2 'producer' threads and
-// 3 'consumer' threads
-
-static void producer(void*);
-static void consumer(void*);
-
-mutex m;
-condition_variable full(m);
-condition_variable empty(m);
-
-bool empty_flag = true;
-const char* message;
-
-static const char* msgs[] = { "wolf", "fox", "hyena", "dingo" };
-
-int main(int, char**)
-{
-   cerr << "main: creating producer1" << endl;
-   thread::create(producer, (void*)"producer1");
-   cerr << "main: creating producer2" << endl;
-   thread::create(producer, (void*)"producer2");
-   cerr << "main: creating consumer1" << endl;
-   thread::create(consumer, (void*)"consumer1");
-   cerr << "main: creating consumer2" << endl;
-   thread::create(consumer, (void*)"consumer2");
-   cerr << "main: creating consumer3" << endl;
-   consumer((void*)"consumer3");
-   return 0;
-}
-
-static int random_l(void)
-{
-   static mutex rand_mutex;
-   mutex_lock l(rand_mutex);
-   int i = rand();
-   return i;
-}
-
-static void consumer(void* arg)
-{
-   char *name = (char *)arg;
-   unsigned long s, n;
-
-   while (1) {
-      {
-         mutex_lock l(m);
-         thread::get_time(s, n, 0, 500000000);  // 1/2 second from now
-         while (empty_flag) {
-            cerr << name << ": waiting for message" << endl;
-            if (!full.timedwait(s, n)) {
-               cerr << name << ": timed out, trying again" << endl;
-               thread::get_time(s, n, 0, 500000000);
-            } else if (empty_flag)
-               cerr << name << ": woken but message already consumed" << endl;
-         }
-         cerr << name << ": got message: '" << message << "'" << endl;
-         empty_flag = true;
-         empty.signal();
-      }
-      thread::sleep(random_l() % 2, 1000000 * (random_l() % 1000));
-   }
-}
-
-static void producer(void* arg)
-{
-   char *name = (char *)arg;
-
-   while (1) {
-      {
-         mutex_lock l(m);
-         while (!empty_flag) {
-            cerr << name << ": having to wait for consumer" << endl;
-            empty.wait();
-         }
-         message = msgs[random_l() % 4];
-         empty_flag = false;
-         full.signal();
-         cerr << name << ": put message: '" << message << "'" << endl;
-      }
-      thread::sleep(random_l() % 2, 1000000 * (random_l() % 500) + 500);
-   }
-}

+ 0 - 103
panda/src/ipc/test_thread.cxx

@@ -1,103 +0,0 @@
-// Filename: test_thread.cxx
-// Created by:  
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include <pandabase.h>
-#include <stdlib.h>
-#include "ipc_thread.h"
-#include "ipc_condition.h"
-
-static mutex print_mutex;
-
-static mutex m;
-static condition_variable cv(m);
-
-class CTestThread : public thread
-{
-  private:
-
-    void run(void *arg)
-    {
-      cout << "Hey main.  This is " << (char *) arg << ".  Wake the hell up." << endl;
-      cout.flush();
-
-      cv.signal();
-    }
-
-  public:
-
-    CTestThread(char *name) : thread(name)
-    {
-      cout << name << " LIVES!." << endl;
-      cout.flush();
-
-      start();
-    }
-
-    ~CTestThread(void) {}
-};
-
-class CTestThread2 : public thread
-{
-  private:
-
-    void run(void *arg)
-    {
-      cout << "Oh- so NOW you need me." << endl;
-      cout.flush();
-
-      cv.wait();
-      cv.signal();
-
-      cout << "bastid." << endl;
-      cout.flush();
-    }
-
-  public:
-
-    CTestThread2(char *name) : thread(name)
-    {
-      cout << name << " LIVES!." << endl;
-      cout.flush();
-
-      start();
-    }
-
-    ~CTestThread2(void) {}
-};
-
-int main(int, char **)
-{
-  CTestThread *test_thread = new CTestThread("test_thread");
-  CTestThread2 *test_thread2 = new CTestThread2("test_thread2");
-
-  cout << "My name is main, and i'm going to go to sleep." << endl;
-  cout.flush();
-
-  cv.wait();
-
-  cout << "I hate you test_thread." << endl;
-  cout.flush();
-
-  cv.signal();
-  cv.wait();
-
-  cout << "I hate you test_thread2." << endl;
-  cout.flush();
-
-  return 0;
-}

+ 0 - 57
panda/src/ipc/test_threaddata.cxx

@@ -1,57 +0,0 @@
-// Filename: test_threaddata.cxx
-// Created by:  cary (16Sep98)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include <pandabase.h>
-#include "ipc_thread.h"
-
-// test a derived class from thread with thread specific data, as well as the
-// joining mechanism.
-
-class thread_with_data : public thread {
-   private:
-      int _my_thread_id_plus_two;
-      void* run_undetached(void* ptr) {
-         int arg = *(int*)ptr;
-         delete (int*)ptr;
-         cerr << "Thread: run invoked with arg " << arg << endl;
-         cerr << "Thread: my id is " << get_id() << endl;
-         cerr << "Thread: my private data (id plus 2) is "
-              << _my_thread_id_plus_two << endl;
-         int* rv = new int(_my_thread_id_plus_two + 1);
-         cerr << "Thread: returning " << *rv << endl;
-         return (void*)rv;
-      }
-      ~thread_with_data(void) {}
-      static void* make_arg(const int i) { return (void*)new int(i); }
-   public:
-      thread_with_data(void) : thread(make_arg(5)) {
-         _my_thread_id_plus_two = get_id() + 2;
-         start_undetached();
-      }
-};
-
-int main(int, char**)
-{
-   thread_with_data *t = new thread_with_data;
-   cerr << "main: joining" << endl;
-   int* rv;
-   t->join((void**)&rv);
-   cerr << "main: joined - got return value " << *rv << endl;
-   delete rv;
-   return 0;
-}

+ 2 - 2
panda/src/pgraph/loader.cxx

@@ -145,7 +145,7 @@ request_load(const Filename &filename, const string &event_name) {
     }
 
     // We need to grab the lock in order to signal the condition variable
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
     _lock.lock();
 #endif
 
@@ -163,7 +163,7 @@ request_load(const Filename &filename, const string &event_name) {
       tok = new LoaderToken(_next_token++, filename, event_name);
       _token_board->_waiting.push_back(tok);
 
-#ifdef HAVE_IPC
+#ifdef OLD_HAVE_IPC
       _request_cond->signal();
     _lock.unlock();
 #endif