Browse Source

posix threads

David Rose 20 years ago
parent
commit
7fdf481b0f
40 changed files with 1043 additions and 68 deletions
  1. 0 2
      dtool/Config.Linux.pp
  2. 9 2
      dtool/Config.pp
  3. 3 0
      dtool/LocalSetup.pp
  4. 1 1
      dtool/src/parser-inc/Sources.pp
  5. 32 0
      dtool/src/parser-inc/pthread.h
  6. 12 0
      panda/src/express/Sources.pp
  7. 6 6
      panda/src/express/atomicAdjust.I
  8. 4 3
      panda/src/express/atomicAdjust.h
  9. 7 7
      panda/src/express/atomicAdjustDummyImpl.I
  10. 5 3
      panda/src/express/atomicAdjustDummyImpl.h
  11. 5 0
      panda/src/express/atomicAdjustImpl.h
  12. 6 6
      panda/src/express/atomicAdjustNsprImpl.I
  13. 4 3
      panda/src/express/atomicAdjustNsprImpl.h
  14. 61 0
      panda/src/express/atomicAdjustPosixImpl.I
  15. 27 0
      panda/src/express/atomicAdjustPosixImpl.cxx
  16. 50 0
      panda/src/express/atomicAdjustPosixImpl.h
  17. 6 15
      panda/src/express/atomicAdjustWin32Impl.I
  18. 4 3
      panda/src/express/atomicAdjustWin32Impl.h
  19. 5 0
      panda/src/express/conditionVarImpl.h
  20. 64 0
      panda/src/express/conditionVarPosixImpl.I
  21. 25 0
      panda/src/express/conditionVarPosixImpl.cxx
  22. 55 0
      panda/src/express/conditionVarPosixImpl.h
  23. 3 0
      panda/src/express/express_composite1.cxx
  24. 1 0
      panda/src/express/express_composite2.cxx
  25. 11 3
      panda/src/express/mutexImpl.h
  26. 114 0
      panda/src/express/mutexPosixImpl.I
  27. 25 0
      panda/src/express/mutexPosixImpl.cxx
  28. 68 0
      panda/src/express/mutexPosixImpl.h
  29. 2 3
      panda/src/express/reMutex.I
  30. 3 2
      panda/src/express/reMutex.cxx
  31. 4 4
      panda/src/express/reMutex.h
  32. 2 1
      panda/src/express/referenceCount.h
  33. 5 1
      panda/src/express/selectThreadImpl.h
  34. 2 1
      panda/src/express/thread.h
  35. 5 0
      panda/src/express/threadImpl.h
  36. 93 0
      panda/src/express/threadPosixImpl.I
  37. 231 0
      panda/src/express/threadPosixImpl.cxx
  38. 81 0
      panda/src/express/threadPosixImpl.h
  39. 1 1
      panda/src/putil/cachedTypedWritableReferenceCount.h
  40. 1 1
      panda/src/putil/nodeCachedReferenceCount.h

+ 0 - 2
dtool/Config.Linux.pp

@@ -142,5 +142,3 @@
 
 // The dynamic library file extension (usually .so .dll or .dylib):
 #define DYNAMIC_LIB_EXT .so
-  
-

+ 9 - 2
dtool/Config.pp

@@ -555,6 +555,10 @@
 // cause libdirect.dll to fail to load on Win98 clients.
 #define HAVE_DIRECTD
 
+// If your system supports the Posix threads interface
+// (pthread_create(), etc.), define this true.
+#define HAVE_POSIX_THREADS $[isfile /usr/include/pthread.h]
+
 // Do you want to build in support for threading (multiprocessing)?
 // Building in support for threading will enable Panda to take
 // advantage of multiple CPU's if you have them (and if the OS
@@ -562,8 +566,11 @@
 // slightly slow down Panda for the single CPU case, so this is not
 // enabled by default.
 
-// Currently, threading support requires NSPR, so you should not
-// define this true unless you have NSPR installed.
+// You should only turn this on if you have some threading library
+// available (most people will have one).  Windows has one built-in.
+// Linux uses Posix threads, which most Linuxes provide.
+// Alternatively, the NSPR library also provides a threading interface
+// that Panda can use.
 #define HAVE_THREADS
 
 // Even if threading is not defined, you might want to double-check

+ 3 - 0
dtool/LocalSetup.pp

@@ -456,6 +456,9 @@ $[cdefine HAVE_SYS_SOUNDCARD_H]
 /* Do we have RTTI (and <typeinfo>)? */
 $[cdefine HAVE_RTTI]
 
+/* Do we have Posix threads? */
+$[cdefine HAVE_POSIX_THREADS]
+
 /* Must global operator new and delete functions throw exceptions? */
 $[cdefine GLOBAL_OPERATOR_NEW_EXCEPTIONS]
 

+ 1 - 1
dtool/src/parser-inc/Sources.pp

@@ -1,6 +1,6 @@
 #define INSTALL_PARSER_INC \
     algorithm deque ft2build.h hash_map hash_set iostream list map memory \
-    pair queue set stack stdcompare.h stdtypedefs.h \
+    pair pthread.h queue set stack stdcompare.h stdtypedefs.h \
     string vector windows.h zlib.h files.h hex.h \
     md5.h evp.h bits/pthreadtypes.h \
     openssl/md5.h openssl/evp.h openssl/rand.h openssl/ssl.h openssl/x509.h openssl/err.h \

+ 32 - 0
dtool/src/parser-inc/pthread.h

@@ -0,0 +1,32 @@
+// Filename: pthread.h
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+// This file, and all the other files in this directory, aren't
+// intended to be compiled--they're just parsed by CPPParser (and
+// interrogate) in lieu of the actual system headers, to generate the
+// interrogate database.
+
+#ifndef PTHREAD_H
+#define PTHREAD_H
+
+typedef int pthread_t;
+typedef int pthread_key_t;
+typedef int pthread_mutex_t;
+typedef int pthread_cond_t;
+
+#endif

+ 12 - 0
panda/src/express/Sources.pp

@@ -12,6 +12,7 @@
     atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I atomicAdjust.h \
     atomicAdjust.I atomicAdjustImpl.h \
     atomicAdjustNsprImpl.h atomicAdjustNsprImpl.I \
+    atomicAdjustPosixImpl.h atomicAdjustPosixImpl.I \
     atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I \
     bigEndian.h buffer.I buffer.h \
     checksumHashGenerator.I checksumHashGenerator.h circBuffer.I \
@@ -19,6 +20,7 @@
     conditionVarDummyImpl.h conditionVarDummyImpl.I conditionVar.h \
     conditionVar.I conditionVarImpl.h \
     conditionVarNsprImpl.h conditionVarNsprImpl.I \
+    conditionVarPosixImpl.h conditionVarPosixImpl.I \
     conditionVarWin32Impl.h conditionVarWin32Impl.I \
     config_express.h \
     datagram.I datagram.h datagramGenerator.I \
@@ -41,6 +43,7 @@
     mutexDummyImpl.h mutexDummyImpl.I pmutex.h mutexHolder.h \
     mutexHolder.I pmutex.I mutexImpl.h \
     mutexNsprImpl.h mutexNsprImpl.I \
+    mutexPosixImpl.h mutexPosixImpl.I \
     mutexWin32Impl.h mutexWin32Impl.I \
     namable.I \
     namable.h nativeNumericData.I nativeNumericData.h \
@@ -66,6 +69,7 @@
     textEncoder.h textEncoder.I \
     threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
     threadNsprImpl.h threadNsprImpl.I \
+    threadPosixImpl.h threadPosixImpl.I \
     threadWin32Impl.h threadWin32Impl.I \
     threadPriority.h \
     tokenBoard.I \
@@ -89,10 +93,12 @@
   #define INCLUDED_SOURCES  \
     atomicAdjust.cxx atomicAdjustDummyImpl.cxx \
     atomicAdjustNsprImpl.cxx \
+    atomicAdjustPosixImpl.cxx \
     atomicAdjustWin32Impl.cxx \
     buffer.cxx checksumHashGenerator.cxx clockObject.cxx \
     conditionVar.cxx conditionVarDummyImpl.cxx \
     conditionVarNsprImpl.cxx \
+    conditionVarPosixImpl.cxx \
     conditionVarWin32Impl.cxx \
     config_express.cxx datagram.cxx datagramGenerator.cxx \
     datagramIterator.cxx \
@@ -106,6 +112,7 @@
     memoryUsagePointers.cxx multifile.cxx \
     pmutex.cxx mutexHolder.cxx mutexDummyImpl.cxx \
     mutexNsprImpl.cxx \
+    mutexPosixImpl.cxx \
     mutexWin32Impl.cxx \
     namable.cxx \
     nativeNumericData.cxx \
@@ -129,6 +136,7 @@
     textEncoder.cxx \
     thread.cxx threadDummyImpl.cxx \
     threadNsprImpl.cxx \
+    threadPosixImpl.cxx \
     threadWin32Impl.cxx \
     trueClock.cxx \
     typedReferenceCount.cxx \
@@ -149,6 +157,7 @@
     atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I atomicAdjust.h \
     atomicAdjust.I atomicAdjustImpl.h \
     atomicAdjustNsprImpl.h atomicAdjustNsprImpl.I \
+    atomicAdjustPosixImpl.h atomicAdjustPosixImpl.I \
     atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I \
     bigEndian.h buffer.I buffer.h checksumHashGenerator.I  \
     checksumHashGenerator.h circBuffer.I circBuffer.h clockObject.I \
@@ -156,6 +165,7 @@
     conditionVarDummyImpl.h conditionVarDummyImpl.I conditionVar.h \
     conditionVar.I conditionVarImpl.h \
     conditionVarNsprImpl.h conditionVarNsprImpl.I \
+    conditionVarPosixImpl.h conditionVarPosixImpl.I \
     conditionVarWin32Impl.h conditionVarWin32Impl.I \
     config_express.h datagram.I datagram.h \
     datagramGenerator.I datagramGenerator.h \
@@ -176,6 +186,7 @@
     mutexDummyImpl.h mutexDummyImpl.I pmutex.h mutexHolder.h \
     mutexHolder.I pmutex.I mutexImpl.h \
     mutexNsprImpl.h mutexNsprImpl.I \
+    mutexPosixImpl.h mutexPosixImpl.I \
     mutexWin32Impl.h mutexWin32Impl.I \
     namable.I namable.h \
     nativeNumericData.I nativeNumericData.h numeric_types.h \
@@ -200,6 +211,7 @@
     textEncoder.h textEncoder.I \
     threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
     threadNsprImpl.h threadNsprImpl.I \
+    threadPosixImpl.h threadPosixImpl.I \
     threadWin32Impl.h threadWin32Impl.I \
     threadPriority.h \
     tokenBoard.I \

+ 6 - 6
panda/src/express/atomicAdjust.I

@@ -23,8 +23,8 @@
 //  Description: Atomically increments the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjust::
-inc(int &var) {
+INLINE PN_int32 AtomicAdjust::
+inc(PN_int32 &var) {
   return AtomicAdjustImpl::inc(var);
 }
 
@@ -34,8 +34,8 @@ inc(int &var) {
 //  Description: Atomically decrements the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjust::
-dec(int &var) {
+INLINE PN_int32 AtomicAdjust::
+dec(PN_int32 &var) {
   return AtomicAdjustImpl::dec(var);
 }
 
@@ -45,7 +45,7 @@ dec(int &var) {
 //  Description: Atomically changes the indicated variable and
 //               returns the original value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjust::
-set(int &var, int new_value) {
+INLINE PN_int32 AtomicAdjust::
+set(PN_int32 &var, PN_int32 new_value) {
   return AtomicAdjustImpl::set(var, new_value);
 }

+ 4 - 3
panda/src/express/atomicAdjust.h

@@ -21,6 +21,7 @@
 
 #include "pandabase.h"
 #include "atomicAdjustImpl.h"
+#include "numeric_types.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : AtomicAdjust
@@ -31,9 +32,9 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAEXPRESS AtomicAdjust {
 public:
-  INLINE static int inc(int &var);
-  INLINE static int dec(int &var);
-  INLINE static int set(int &var, int new_value);
+  INLINE static PN_int32 inc(PN_int32 &var);
+  INLINE static PN_int32 dec(PN_int32 &var);
+  INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
 };
 
 #include "atomicAdjust.I"

+ 7 - 7
panda/src/express/atomicAdjustDummyImpl.I

@@ -23,8 +23,8 @@
 //  Description: Atomically increments the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustDummyImpl::
-inc(int &var) {
+INLINE PN_int32 AtomicAdjustDummyImpl::
+inc(PN_int32 &var) {
   return ++var;
 }
 
@@ -34,8 +34,8 @@ inc(int &var) {
 //  Description: Atomically decrements the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustDummyImpl::
-dec(int &var) {
+INLINE PN_int32 AtomicAdjustDummyImpl::
+dec(PN_int32 &var) {
   return --var;
 }
 
@@ -45,9 +45,9 @@ dec(int &var) {
 //  Description: Atomically changes the indicated variable and
 //               returns the original value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustDummyImpl::
-set(int &var, int new_value) {
-  int orig_value = var;
+INLINE PN_int32 AtomicAdjustDummyImpl::
+set(PN_int32 &var, PN_int32 new_value) {
+  PN_int32 orig_value = var;
   var = new_value;
   return orig_value;
 }

+ 5 - 3
panda/src/express/atomicAdjustDummyImpl.h

@@ -23,7 +23,9 @@
 #include "selectThreadImpl.h"
 
 #ifdef THREAD_DUMMY_IMPL
+
 #include "notify.h"
+#include "numeric_types.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : AtomicAdjustDummyImpl
@@ -33,9 +35,9 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAEXPRESS AtomicAdjustDummyImpl {
 public:
-  INLINE static int inc(int &var);
-  INLINE static int dec(int &var);
-  INLINE static int set(int &var, int new_value);
+  INLINE static PN_int32 inc(PN_int32 &var);
+  INLINE static PN_int32 dec(PN_int32 &var);
+  INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
 };
 
 #include "atomicAdjustDummyImpl.I"

+ 5 - 0
panda/src/express/atomicAdjustImpl.h

@@ -32,6 +32,11 @@ typedef AtomicAdjustDummyImpl AtomicAdjustImpl;
 #include "atomicAdjustWin32Impl.h"
 typedef AtomicAdjustWin32Impl AtomicAdjustImpl;
 
+#elif defined(THREAD_POSIX_IMPL)
+
+#include "atomicAdjustPosixImpl.h"
+typedef AtomicAdjustPosixImpl AtomicAdjustImpl;
+
 #elif defined(THREAD_NSPR_IMPL)
 
 #include "atomicAdjustNsprImpl.h"

+ 6 - 6
panda/src/express/atomicAdjustNsprImpl.I

@@ -23,8 +23,8 @@
 //  Description: Atomically increments the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustNsprImpl::
-inc(int &var) {
+INLINE PN_int32 AtomicAdjustNsprImpl::
+inc(PN_int32 &var) {
   return PR_AtomicIncrement(&var);
 }
 
@@ -34,8 +34,8 @@ inc(int &var) {
 //  Description: Atomically decrements the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustNsprImpl::
-dec(int &var) {
+INLINE PN_int32 AtomicAdjustNsprImpl::
+dec(PN_int32 &var) {
   return PR_AtomicDecrement(&var);
 }
 
@@ -45,7 +45,7 @@ dec(int &var) {
 //  Description: Atomically changes the indicated variable and
 //               returns the original value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustNsprImpl::
-set(int &var, int new_value) {
+INLINE PN_int32 AtomicAdjustNsprImpl::
+set(PN_int32 &var, PN_int32 new_value) {
   return PR_AtomicSet(&var, new_value);
 }

+ 4 - 3
panda/src/express/atomicAdjustNsprImpl.h

@@ -25,6 +25,7 @@
 #ifdef THREAD_NSPR_IMPL
 
 #include "notify.h"
+#include "numeric_types.h"
 
 #include <pratom.h>
 
@@ -34,9 +35,9 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAEXPRESS AtomicAdjustNsprImpl {
 public:
-  INLINE static int inc(int &var);
-  INLINE static int dec(int &var);
-  INLINE static int set(int &var, int new_value);
+  INLINE static PN_int32 inc(PN_int32 &var);
+  INLINE static PN_int32 dec(PN_int32 &var);
+  INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
 };
 
 #include "atomicAdjustNsprImpl.I"

+ 61 - 0
panda/src/express/atomicAdjustPosixImpl.I

@@ -0,0 +1,61 @@
+// Filename: atomicAdjustPosixImpl.I
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustPosixImpl::inc
+//       Access: Public, Static
+//  Description: Atomically increments the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE PN_int32 AtomicAdjustPosixImpl::
+inc(PN_int32 &var) {
+  pthread_mutex_lock(&_mutex);
+  PN_int32 result = ++var;
+  pthread_mutex_unlock(&_mutex);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustPosixImpl::dec
+//       Access: Public, Static
+//  Description: Atomically decrements the indicated variable and
+//               returns the new value.
+////////////////////////////////////////////////////////////////////
+INLINE PN_int32 AtomicAdjustPosixImpl::
+dec(PN_int32 &var) {
+  pthread_mutex_lock(&_mutex);
+  PN_int32 result = --var;
+  pthread_mutex_unlock(&_mutex);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustPosixImpl::set
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE PN_int32 AtomicAdjustPosixImpl::
+set(PN_int32 &var, PN_int32 new_value) {
+  pthread_mutex_lock(&_mutex);
+  PN_int32 orig_value = var;
+  var = new_value;
+  pthread_mutex_unlock(&_mutex);
+  return orig_value;
+}

+ 27 - 0
panda/src/express/atomicAdjustPosixImpl.cxx

@@ -0,0 +1,27 @@
+// Filename: atomicAdjustPosixImpl.cxx
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "atomicAdjustPosixImpl.h"
+
+pthread_mutex_t AtomicAdjustPosixImpl::_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#endif  // THREAD_POSIX_IMPL

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

@@ -0,0 +1,50 @@
+// Filename: atomicAdjustPosixImpl.h
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ATOMICADJUSTPOSIXIMPL_H
+#define ATOMICADJUSTPOSIXIMPL_H
+
+#include "pandabase.h"
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "notify.h"
+#include "numeric_types.h"
+
+#include <pthread.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : AtomicAdjustPosixImpl
+// Description : Uses POSIX to implement atomic adjustments.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS AtomicAdjustPosixImpl {
+public:
+  INLINE static PN_int32 inc(PN_int32 &var);
+  INLINE static PN_int32 dec(PN_int32 &var);
+  INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
+
+private:
+  static pthread_mutex_t _mutex;
+};
+
+#include "atomicAdjustPosixImpl.I"
+
+#endif  // THREAD_POSIX_IMPL
+
+#endif

+ 6 - 15
panda/src/express/atomicAdjustWin32Impl.I

@@ -23,9 +23,8 @@
 //  Description: Atomically increments the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustWin32Impl::
-inc(int &var) {
-  nassertr(sizeof(int) == sizeof(LONG), ++var);
+INLINE PN_int32 AtomicAdjustWin32Impl::
+inc(PN_int32 &var) {
   return InterlockedIncrement((LONG *)&var);
 }
 
@@ -35,9 +34,8 @@ inc(int &var) {
 //  Description: Atomically decrements the indicated variable and
 //               returns the new value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustWin32Impl::
-dec(int &var) {
-  nassertr(sizeof(int) == sizeof(LONG), --var);
+INLINE PN_int32 AtomicAdjustWin32Impl::
+dec(PN_int32 &var) {
   return InterlockedDecrement((LONG *)&var);
 }
 
@@ -47,14 +45,7 @@ dec(int &var) {
 //  Description: Atomically changes the indicated variable and
 //               returns the original value.
 ////////////////////////////////////////////////////////////////////
-INLINE int AtomicAdjustWin32Impl::
-set(int &var, int new_value) {
-#ifndef NDEBUG
-  nassertd(sizeof(int) == sizeof(LONG)) {
-    int temp = var;
-    var = new_value;
-    return temp;
-  }
-#endif
+INLINE PN_int32 AtomicAdjustWin32Impl::
+set(PN_int32 &var, PN_int32 new_value) {
   return InterlockedExchange((LONG *)&var, new_value);
 }

+ 4 - 3
panda/src/express/atomicAdjustWin32Impl.h

@@ -25,6 +25,7 @@
 #ifdef THREAD_WIN32_IMPL
 
 #include "notify.h"
+#include "numeric_types.h"
 
 #include <windows.h>
 
@@ -35,9 +36,9 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAEXPRESS AtomicAdjustWin32Impl {
 public:
-  INLINE static int inc(int &var);
-  INLINE static int dec(int &var);
-  INLINE static int set(int &var, int new_value);
+  INLINE static PN_int32 inc(PN_int32 &var);
+  INLINE static PN_int32 dec(PN_int32 &var);
+  INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
 };
 
 #include "atomicAdjustWin32Impl.I"

+ 5 - 0
panda/src/express/conditionVarImpl.h

@@ -32,6 +32,11 @@ typedef ConditionVarDummyImpl ConditionVarImpl;
 #include "conditionVarWin32Impl.h"
 typedef ConditionVarWin32Impl ConditionVarImpl;
 
+#elif defined(THREAD_POSIX_IMPL)
+
+#include "conditionVarPosixImpl.h"
+typedef ConditionVarPosixImpl ConditionVarImpl;
+
 #elif defined(THREAD_NSPR_IMPL)
 
 #include "conditionVarNsprImpl.h"

+ 64 - 0
panda/src/express/conditionVarPosixImpl.I

@@ -0,0 +1,64 @@
+// Filename: conditionVarPosixImpl.I
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ConditionVarPosixImpl::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ConditionVarPosixImpl::
+ConditionVarPosixImpl(MutexPosixImpl &mutex) :
+  _mutex(mutex)
+{
+  int result = pthread_cond_init(&_cvar, NULL);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ConditionVarPosixImpl::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ConditionVarPosixImpl::
+~ConditionVarPosixImpl() {
+  int result = pthread_cond_destroy(&_cvar);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ConditionVarPosixImpl::wait
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ConditionVarPosixImpl::
+wait() {
+  int result = pthread_cond_wait(&_cvar, &_mutex._lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ConditionVarPosixImpl::signal
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ConditionVarPosixImpl::
+signal() {
+  int result = pthread_cond_signal(&_cvar);
+  nassertv(result == 0);
+}

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

@@ -0,0 +1,25 @@
+// Filename: conditionVarPosixImpl.cxx
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_NSPR_IMPL
+
+#include "conditionVarNsprImpl.h"
+
+#endif  // THREAD_NSPR_IMPL

+ 55 - 0
panda/src/express/conditionVarPosixImpl.h

@@ -0,0 +1,55 @@
+// Filename: conditionVarPosixImpl.h
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONDITIONVARPOSIXIMPL_H
+#define CONDITIONVARPOSIXIMPL_H
+
+#include "pandabase.h"
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "mutexPosixImpl.h"
+#include "notify.h"
+
+#include <pthread.h>
+
+class MutexPosixImpl;
+
+////////////////////////////////////////////////////////////////////
+//       Class : ConditionVarPosixImpl
+// Description : Uses Posix threads to implement a conditionVar.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS ConditionVarPosixImpl {
+public:
+  INLINE ConditionVarPosixImpl(MutexPosixImpl &mutex);
+  INLINE ~ConditionVarPosixImpl();
+
+  INLINE void wait();
+  INLINE void signal();
+
+private:
+  MutexPosixImpl &_mutex;
+  pthread_cond_t _cvar;
+};
+
+#include "conditionVarPosixImpl.I"
+
+#endif  // THREAD_POSIX_IMPL
+
+#endif

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

@@ -1,6 +1,7 @@
 #include "atomicAdjust.cxx"
 #include "atomicAdjustDummyImpl.cxx"
 #include "atomicAdjustNsprImpl.cxx"
+#include "atomicAdjustPosixImpl.cxx"
 #include "atomicAdjustWin32Impl.cxx"
 #include "buffer.cxx"
 #include "checksumHashGenerator.cxx"
@@ -8,6 +9,7 @@
 #include "conditionVar.cxx"
 #include "conditionVarDummyImpl.cxx"
 #include "conditionVarNsprImpl.cxx"
+#include "conditionVarPosixImpl.cxx"
 #include "conditionVarWin32Impl.cxx"
 #include "config_express.cxx"
 #include "datagram.cxx"
@@ -30,6 +32,7 @@
 #include "mutexHolder.cxx"
 #include "mutexDummyImpl.cxx"
 #include "mutexNsprImpl.cxx"
+#include "mutexPosixImpl.cxx"
 #include "mutexWin32Impl.cxx"
 #include "namable.cxx"
 #include "nativeNumericData.cxx"

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

@@ -21,6 +21,7 @@
 #include "thread.cxx"
 #include "threadDummyImpl.cxx"
 #include "threadNsprImpl.cxx"
+#include "threadPosixImpl.cxx"
 #include "threadWin32Impl.cxx"
 #include "trueClock.cxx"
 #include "typedReferenceCount.cxx"

+ 11 - 3
panda/src/express/mutexImpl.h

@@ -26,19 +26,27 @@
 
 #include "mutexDummyImpl.h"
 typedef MutexDummyImpl MutexImpl;
-#undef MUTEX_REENTRANT
+#undef HAVE_REMUTEXIMPL
 
 #elif defined(THREAD_WIN32_IMPL)
 
 #include "mutexWin32Impl.h"
 typedef MutexWin32Impl MutexImpl;
-#define MUTEX_REENTRANT 1  // Win32 Mutexes are already reentrant.
+typedef MutexWin32Impl ReMutexImpl;  // Win32 Mutexes are always reentrant.
+#define HAVE_REMUTEXIMPL 1
+
+#elif defined(THREAD_POSIX_IMPL)
+
+#include "mutexPosixImpl.h"
+typedef MutexPosixImpl MutexImpl;
+typedef ReMutexPosixImpl ReMutexImpl;
+#define HAVE_REMUTEXIMPL 1
 
 #elif defined(THREAD_NSPR_IMPL)
 
 #include "mutexNsprImpl.h"
 typedef MutexNsprImpl MutexImpl;
-#undef MUTEX_REENTRANT
+#undef HAVE_REMUTEXIMPL
 
 #endif
 

+ 114 - 0
panda/src/express/mutexPosixImpl.I

@@ -0,0 +1,114 @@
+// Filename: mutexPosixImpl.I
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexPosixImpl::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexPosixImpl::
+MutexPosixImpl() {
+  pthread_mutexattr_t attr;
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+  int result = pthread_mutex_init(&_lock, &attr);
+  pthread_mutexattr_destroy(&attr);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexPosixImpl::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MutexPosixImpl::
+~MutexPosixImpl() {
+  int result = pthread_mutex_destroy(&_lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexPosixImpl::lock
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexPosixImpl::
+lock() {
+  int result = pthread_mutex_lock(&_lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexPosixImpl::release
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void MutexPosixImpl::
+release() {
+  int result = pthread_mutex_unlock(&_lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexPosixImpl::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ReMutexPosixImpl::
+ReMutexPosixImpl() {
+  pthread_mutexattr_t attr;
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+  int result = pthread_mutex_init(&_lock, &attr);
+  pthread_mutexattr_destroy(&attr);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexPosixImpl::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ReMutexPosixImpl::
+~ReMutexPosixImpl() {
+  int result = pthread_mutex_destroy(&_lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexPosixImpl::lock
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ReMutexPosixImpl::
+lock() {
+  int result = pthread_mutex_lock(&_lock);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexPosixImpl::release
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ReMutexPosixImpl::
+release() {
+  int result = pthread_mutex_unlock(&_lock);
+  nassertv(result == 0);
+}

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

@@ -0,0 +1,25 @@
+// Filename: mutexPosixImpl.cxx
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "mutexPosixImpl.h"
+
+#endif  // THREAD_POSIX_IMPL

+ 68 - 0
panda/src/express/mutexPosixImpl.h

@@ -0,0 +1,68 @@
+// Filename: mutexPosixImpl.h
+// Created by:  drose (10Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MUTEXPOSIXIMPL_H
+#define MUTEXPOSIXIMPL_H
+
+#include "pandabase.h"
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "notify.h"
+
+#include <pthread.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : MutexPosixImpl
+// Description : Uses Posix threads to implement a mutex.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS MutexPosixImpl {
+public:
+  INLINE MutexPosixImpl();
+  INLINE ~MutexPosixImpl();
+
+  INLINE void lock();
+  INLINE void release();
+
+private:
+  pthread_mutex_t _lock;
+  friend class ConditionVarPosixImpl;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : ReMutexPosixImpl
+// Description : Uses Posix threads to implement a reentrant mutex.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS ReMutexPosixImpl {
+public:
+  INLINE ReMutexPosixImpl();
+  INLINE ~ReMutexPosixImpl();
+
+  INLINE void lock();
+  INLINE void release();
+
+private:
+  pthread_mutex_t _lock;
+};
+
+#include "mutexPosixImpl.I"
+
+#endif  // THREAD_POSIX_IMPL
+
+#endif

+ 2 - 3
panda/src/express/reMutex.I

@@ -17,10 +17,9 @@
 ////////////////////////////////////////////////////////////////////
 
 
-#ifdef MUTEX_REENTRANT
+#ifdef HAVE_REMUTEXIMPL
 // In this branch, the ReMutex class is implemented as a thin wrapper
-// around the native MutexImpl class (which is already reentrant
-// anyway).
+// around the native ReMutexImpl class.
 
 ////////////////////////////////////////////////////////////////////
 //     Function: ReMutex::Constructor

+ 3 - 2
panda/src/express/reMutex.cxx

@@ -18,7 +18,7 @@
 
 #include "reMutex.h"
 
-#ifndef MUTEX_REENTRANT
+#ifndef HAVE_REMUTEXIMPL
 
 // Most of the methods in this class are stubbed out in the
 // THREAD_DUMMY_IMPL case, especially when CHECK_REENTRANT_MUTEX is
@@ -81,4 +81,5 @@ do_release() {
 
 #endif  // !THREAD_DUMMY_IMPL || CHECK_REENTRANT_MUTEX
 
-#endif  // MUTEX_REENTRANT
+#endif  // !HAVE_REMUTEXIMPL
+

+ 4 - 4
panda/src/express/reMutex.h

@@ -47,10 +47,10 @@ public:
   INLINE bool debug_is_locked() const;
 
 private:
-#ifdef MUTEX_REENTRANT
-  // If the native Mutex implementation is already reentrant, just use
-  // that.
-  MutexImpl _impl;
+#ifdef HAVE_REMUTEXIMPL
+  // If the native Mutex implementation provides a reentrant flavor,
+  // just use that.
+  ReMutexImpl _impl;
 
 #elif !defined(THREAD_DUMMY_IMPL) || defined(CHECK_REENTRANT_MUTEX)
   void do_lock();

+ 2 - 1
panda/src/express/referenceCount.h

@@ -25,6 +25,7 @@
 #include "memoryUsage.h"
 #include "config_express.h"
 #include "atomicAdjust.h"
+#include "numeric_types.h"
 
 #include <stdlib.h>
 
@@ -81,7 +82,7 @@ private:
     deleted_ref_count = -100,
   };
 
-  int _ref_count;
+  PN_int32 _ref_count;
   WeakReferenceList *_weak_list;
 
 public:

+ 5 - 1
panda/src/express/selectThreadImpl.h

@@ -36,7 +36,11 @@
 
 // In Windows, use the native threading library.
 #define THREAD_WIN32_IMPL 1
-#define THREAD_NSPR_IMPL 1  // Temp while developing.
+
+#elif defined(HAVE_POSIX_THREADS)
+
+// Posix threads are nice.
+#define THREAD_POSIX_IMPL 1
 
 #elif defined(HAVE_NSPR)
 

+ 2 - 1
panda/src/express/thread.h

@@ -115,8 +115,9 @@ private:
   static TypeHandle _type_handle;
 
   friend class ThreadDummyImpl;
-  friend class ThreadNsprImpl;
   friend class ThreadWin32Impl;
+  friend class ThreadPosixImpl;
+  friend class ThreadNsprImpl;
 };
 
 INLINE ostream &operator << (ostream &out, const Thread &thread);

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

@@ -32,6 +32,11 @@ typedef ThreadDummyImpl ThreadImpl;
 #include "threadWin32Impl.h"
 typedef ThreadWin32Impl ThreadImpl;
 
+#elif defined(THREAD_POSIX_IMPL)
+
+#include "threadPosixImpl.h"
+typedef ThreadPosixImpl ThreadImpl;
+
 #elif defined(THREAD_NSPR_IMPL)
 
 #include "threadNsprImpl.h"

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

@@ -0,0 +1,93 @@
+// Filename: threadPosixImpl.I
+// Created by:  drose (09Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ThreadPosixImpl::
+ThreadPosixImpl(Thread *parent_obj) :
+  _parent_obj(parent_obj)
+{
+  _joinable = false;
+  _detached = false;
+  _status = S_new;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::prepare_for_exit
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadPosixImpl::
+prepare_for_exit() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::get_current_thread
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE Thread *ThreadPosixImpl::
+get_current_thread() {
+  if (!_got_pt_ptr_index) {
+    init_pt_ptr_index();
+  }
+  return (Thread *)pthread_getspecific(_pt_ptr_index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::bind_thread
+//       Access: Public, Static
+//  Description: Associates the indicated Thread object with the
+//               currently-executing thread.  You should not call this
+//               directly; use Thread::bind_thread() instead.
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadPosixImpl::
+bind_thread(Thread *thread) {
+  if (!_got_pt_ptr_index) {
+    init_pt_ptr_index();
+  }
+  int result = pthread_setspecific(_pt_ptr_index, thread);
+  nassertv(result == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::is_threading_supported
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool ThreadPosixImpl::
+is_threading_supported() {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::sleep
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ThreadPosixImpl::
+sleep(double seconds) {
+  struct timespec rqtp;
+  rqtp.tv_sec = time_t(seconds);
+  rqtp.tv_nsec = long((seconds - (double)rqtp.tv_sec) * 1000000000.0);
+  nanosleep(&rqtp, NULL);
+}

+ 231 - 0
panda/src/express/threadPosixImpl.cxx

@@ -0,0 +1,231 @@
+// Filename: threadPosixImpl.cxx
+// Created by:  drose (09Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "threadPosixImpl.h"
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "pointerTo.h"
+#include "config_express.h"
+#include "mutexHolder.h"
+
+#include <sched.h>
+
+pthread_key_t ThreadPosixImpl::_pt_ptr_index = 0;
+bool ThreadPosixImpl::_got_pt_ptr_index = false;
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+ThreadPosixImpl::
+~ThreadPosixImpl() {
+  if (thread_cat.is_debug()) {
+    thread_cat.debug() 
+      << "Deleting thread " << _parent_obj->get_name() << "\n";
+  }
+
+  MutexHolder holder(_mutex);
+
+  if (!_detached) {
+    pthread_detach(_thread);
+    _detached = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::start
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool ThreadPosixImpl::
+start(ThreadPriority priority, bool global, bool joinable) {
+  MutexHolder holder(_mutex);
+  if (thread_cat.is_debug()) {
+    thread_cat.debug() << "Starting thread " << _parent_obj->get_name() << "\n";
+  }
+
+  nassertr(_status == S_new, false);
+  _joinable = joinable;
+  _status = S_start_called;
+  _detached = false;
+
+  if (!_got_pt_ptr_index) {
+    init_pt_ptr_index();
+  }
+
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+
+  if (!_joinable) {
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    _detached = true;
+  }
+
+  struct sched_param param;
+  int current_policy;
+  int result = pthread_attr_getschedpolicy(&attr, &current_policy);
+  if (result != 0) {
+    thread_cat.warning()
+      << "Unable to query scheduling policy.\n";
+
+  } else {
+    int result = 0;
+    switch (priority) {
+    case TP_low:
+      param.sched_priority = sched_get_priority_min(current_policy);
+      result = pthread_attr_setschedparam(&attr, &param);
+      break;
+      
+    case TP_high:
+    case TP_urgent:
+      param.sched_priority = sched_get_priority_max(current_policy);
+      result = pthread_attr_setschedparam(&attr, &param);
+      break;
+      
+    case TP_normal:
+    default:
+      break;
+    }
+
+    if (result != 0) {
+      thread_cat.warning()
+        << "Unable to specify thread priority.\n";
+    }
+  }
+
+  // Increment the parent object's reference count first.  The thread
+  // will eventually decrement it when it terminates.
+  _parent_obj->ref();
+  result = pthread_create(&_thread,  &attr, &root_func, (void *)this);
+
+  pthread_attr_destroy(&attr);
+
+  if (result != 0) {
+    // 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: ThreadPosixImpl::interrupt
+//       Access: Public
+//  Description: Sends an interrupt message to the thread.  This will
+//               interrupt any blocking-type system calls the thread
+//               may be waiting on, such as I/O, so that the thread
+//               may continue some other processing.  The specific
+//               behavior is implementation dependent.
+////////////////////////////////////////////////////////////////////
+void ThreadPosixImpl::
+interrupt() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::join
+//       Access: Public
+//  Description: Blocks the calling process until the thread
+//               terminates.  If the thread has already terminated,
+//               this returns immediately.
+////////////////////////////////////////////////////////////////////
+void ThreadPosixImpl::
+join() {
+  _mutex.lock();
+  if (!_detached) {
+    _mutex.release();
+    void *return_val;
+    pthread_join(_thread, &return_val);
+    _detached = true;
+    return;
+  }
+  _mutex.release();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::root_func
+//       Access: Private, Static
+//  Description: The entry point of each thread.
+////////////////////////////////////////////////////////////////////
+void *ThreadPosixImpl::
+root_func(void *data) {
+  ThreadPosixImpl *self = (ThreadPosixImpl *)data;
+  int result = pthread_setspecific(_pt_ptr_index, self->_parent_obj);
+  nassertr(result == 0, NULL);
+
+  {
+    MutexHolder holder(self->_mutex);
+    nassertr(self->_status == S_start_called, NULL);
+    self->_status = S_running;
+  }
+
+  self->_parent_obj->thread_main();
+
+  if (thread_cat.is_debug()) {
+    thread_cat.debug()
+      << "Terminating thread " << self->_parent_obj->get_name() 
+      << ", count = " << self->_parent_obj->get_ref_count() << "\n";
+  }
+
+  {
+    MutexHolder holder(self->_mutex);
+    nassertr(self->_status == S_running, NULL);
+    self->_status = S_finished;
+  }
+
+  // Now drop the parent object reference that we grabbed in start().
+  // This might delete the parent object, and in turn, delete the
+  // ThreadPosixImpl object.
+  unref_delete(self->_parent_obj);
+
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ThreadPosixImpl::init_pt_ptr_index
+//       Access: Private, Static
+//  Description: Allocate a new index to store the Thread parent
+//               pointer as a piece of per-thread private data.
+////////////////////////////////////////////////////////////////////
+void ThreadPosixImpl::
+init_pt_ptr_index() {
+  nassertv(!_got_pt_ptr_index);
+
+  int result = pthread_key_create(&_pt_ptr_index, NULL);
+  if (result != 0) {
+    thread_cat.error()
+      << "Unable to associate Thread pointers with threads.\n";
+    return;
+  }
+
+  _got_pt_ptr_index = true;
+
+  // Assume that we must be in the main thread, since this method must
+  // be called before the first thread is spawned.
+  Thread *main_thread_obj = Thread::get_main_thread();
+  result = pthread_setspecific(_pt_ptr_index, main_thread_obj);
+  nassertv(result == 0);
+}
+
+#endif  // THREAD_POSIX_IMPL

+ 81 - 0
panda/src/express/threadPosixImpl.h

@@ -0,0 +1,81 @@
+// Filename: threadPosixImpl.h
+// Created by:  drose (09Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef THREADPOSIXIMPL_H
+#define THREADPOSIXIMPL_H
+
+#include "pandabase.h"
+#include "selectThreadImpl.h"
+
+#ifdef THREAD_POSIX_IMPL
+
+#include "notify.h"
+#include "threadPriority.h"
+#include "pmutex.h"
+
+#include <pthread.h>
+
+class Thread;
+
+////////////////////////////////////////////////////////////////////
+//       Class : ThreadPosixImpl
+// Description : Uses Posix threads to implement a thread.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS ThreadPosixImpl {
+public:
+  INLINE ThreadPosixImpl(Thread *parent_obj);
+  ~ThreadPosixImpl();
+
+  bool start(ThreadPriority priority, bool global, bool joinable);
+  void interrupt();
+  void join();
+
+  INLINE static void prepare_for_exit();
+
+  INLINE static Thread *get_current_thread();
+  INLINE static void bind_thread(Thread *thread);
+  INLINE static bool is_threading_supported();
+  INLINE static void sleep(double seconds);
+
+private:
+  static void *root_func(void *data);
+  static void init_pt_ptr_index();
+
+  enum Status {
+    S_new,
+    S_start_called,
+    S_running,
+    S_finished,
+  };
+
+  Mutex _mutex;
+  Thread *_parent_obj;
+  pthread_t _thread;
+  bool _joinable;
+  bool _detached;
+  Status _status;
+
+  static pthread_key_t _pt_ptr_index;
+  static bool _got_pt_ptr_index;
+};
+
+#include "threadPosixImpl.I"
+
+#endif  // THREAD_POSIX_IMPL
+
+#endif

+ 1 - 1
panda/src/putil/cachedTypedWritableReferenceCount.h

@@ -58,7 +58,7 @@ protected:
   bool do_test_ref_count_integrity() const;
 
 private:
-  int _cache_ref_count;
+  PN_int32 _cache_ref_count;
 
 public:
   static TypeHandle get_class_type() {

+ 1 - 1
panda/src/putil/nodeCachedReferenceCount.h

@@ -72,7 +72,7 @@ protected:
   bool do_test_ref_count_integrity() const;
   
 private:
-  int _node_ref_count;
+  PN_int32 _node_ref_count;
 
 public:
   static TypeHandle get_class_type() {