diff --git a/panda/metalibs/panda/Sources.pp b/panda/metalibs/panda/Sources.pp index a1d6f589f2..338a068c40 100644 --- a/panda/metalibs/panda/Sources.pp +++ b/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] diff --git a/panda/src/device/Sources.pp b/panda/src/device/Sources.pp index 2cfdf9ff05..463ac818a6 100644 --- a/panda/src/device/Sources.pp +++ b/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 diff --git a/panda/src/device/clientBase.cxx b/panda/src/device/clientBase.cxx index fea404e8d8..d30a4c271c 100644 --- a/panda/src/device/clientBase.cxx +++ b/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 diff --git a/panda/src/device/clientBase.h b/panda/src/device/clientBase.h index faf61d3b48..6111c43404 100644 --- a/panda/src/device/clientBase.h +++ b/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; diff --git a/panda/src/device/clientDevice.I b/panda/src/device/clientDevice.I index 63051ed7c3..7045101089 100644 --- a/panda/src/device/clientDevice.I +++ b/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 } diff --git a/panda/src/device/clientDevice.h b/panda/src/device/clientDevice.h index 84208c5f2f..f612d568ae 100644 --- a/panda/src/device/clientDevice.h +++ b/panda/src/device/clientDevice.h @@ -23,7 +23,7 @@ #include -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC #include #endif @@ -64,7 +64,7 @@ private: string _device_name; bool _is_connected; -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC mutex _lock; #endif diff --git a/panda/src/downloader/Sources.pp b/panda/src/downloader/Sources.pp index e8228c7690..d410d68507 100644 --- a/panda/src/downloader/Sources.pp +++ b/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 diff --git a/panda/src/downloader/asyncUtility.cxx b/panda/src/downloader/asyncUtility.cxx index 080571d22e..8f70b547a5 100644 --- a/panda/src/downloader/asyncUtility.cxx +++ b/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 } diff --git a/panda/src/downloader/asyncUtility.h b/panda/src/downloader/asyncUtility.h index 2c34f62309..79ebea021a 100644 --- a/panda/src/downloader/asyncUtility.h +++ b/panda/src/downloader/asyncUtility.h @@ -25,7 +25,7 @@ #include #include -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC #include #include #include @@ -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; diff --git a/panda/src/downloader/multiplexStreamBuf.cxx b/panda/src/downloader/multiplexStreamBuf.cxx index 690ec8029e..005598d0c6 100644 --- a/panda/src/downloader/multiplexStreamBuf.cxx +++ b/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 diff --git a/panda/src/downloader/multiplexStreamBuf.h b/panda/src/downloader/multiplexStreamBuf.h index c0e32f72dd..c16524a9e4 100644 --- a/panda/src/downloader/multiplexStreamBuf.h +++ b/panda/src/downloader/multiplexStreamBuf.h @@ -21,7 +21,7 @@ #include -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC #include #endif @@ -82,7 +82,7 @@ private: string _line_buffer; -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC mutex _lock; #endif }; diff --git a/panda/src/downloadertools/Sources.pp b/panda/src/downloadertools/Sources.pp index 1519d09170..b82a5d336c 100644 --- a/panda/src/downloadertools/Sources.pp +++ b/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 diff --git a/panda/src/event/Sources.pp b/panda/src/event/Sources.pp index 899963c597..054964c178 100644 --- a/panda/src/event/Sources.pp +++ b/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 diff --git a/panda/src/event/eventQueue.cxx b/panda/src/event/eventQueue.cxx index 5f7894297b..6a09390509 100644 --- a/panda/src/event/eventQueue.cxx +++ b/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()) { diff --git a/panda/src/event/eventQueue.h b/panda/src/event/eventQueue.h index 800c13beda..5d1a0634aa 100644 --- a/panda/src/event/eventQueue.h +++ b/panda/src/event/eventQueue.h @@ -26,7 +26,7 @@ #include -#ifdef HAVE_IPC +#ifdef OLD_HAVE_IPC #include #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 }; diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index 037dab316f..201673e1d5 100644 --- a/panda/src/express/Sources.pp +++ b/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 + diff --git a/panda/src/express/atomicAdjust.I b/panda/src/express/atomicAdjust.I new file mode 100644 index 0000000000..949e93f112 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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); +} diff --git a/panda/src/express/atomicAdjust.cxx b/panda/src/express/atomicAdjust.cxx new file mode 100644 index 0000000000..488d0d8648 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "atomicAdjust.h" diff --git a/panda/src/express/atomicAdjust.h b/panda/src/express/atomicAdjust.h new file mode 100644 index 0000000000..329ef6b06e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/express/atomicAdjustDummyImpl.I b/panda/src/express/atomicAdjustDummyImpl.I new file mode 100644 index 0000000000..27c6757686 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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; +} diff --git a/panda/src/express/atomicAdjustDummyImpl.cxx b/panda/src/express/atomicAdjustDummyImpl.cxx new file mode 100644 index 0000000000..55852fa284 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "selectIpcImpl.h" + +#ifdef IPC_DUMMY_IMPL + +#include "atomicAdjustDummyImpl.h" + +#endif // IPC_DUMMY_IMPL diff --git a/panda/src/express/atomicAdjustDummyImpl.h b/panda/src/express/atomicAdjustDummyImpl.h new file mode 100644 index 0000000000..c6756aa57f --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/ipc/ipc_atomics.h b/panda/src/express/atomicAdjustImpl.h similarity index 58% rename from panda/src/ipc/ipc_atomics.h rename to panda/src/express/atomicAdjustImpl.h index 81731fc49b..0390f997fa 100644 --- a/panda/src/ipc/ipc_atomics.h +++ b/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 +#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 diff --git a/panda/src/express/atomicAdjustNsprImpl.I b/panda/src/express/atomicAdjustNsprImpl.I new file mode 100644 index 0000000000..fb2037a81e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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); +} diff --git a/panda/src/express/atomicAdjustNsprImpl.cxx b/panda/src/express/atomicAdjustNsprImpl.cxx new file mode 100644 index 0000000000..6e735908c2 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "selectIpcImpl.h" + +#ifdef IPC_NSPR_IMPL + +#include "atomicAdjustNsprImpl.h" + +#endif // IPC_NSPR_IMPL diff --git a/panda/src/express/atomicAdjustNsprImpl.h b/panda/src/express/atomicAdjustNsprImpl.h new file mode 100644 index 0000000000..67c9e457ef --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef ATOMICADJUSTNSPRIMPL_H +#define ATOMICADJUSTNSPRIMPL_H + +#include "pandabase.h" +#include "selectIpcImpl.h" + +#ifdef IPC_NSPR_IMPL + +#include "notify.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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 diff --git a/panda/src/express/config_express.cxx b/panda/src/express/config_express.cxx index 8a54ed728b..b9568cf739 100644 --- a/panda/src/express/config_express.cxx +++ b/panda/src/express/config_express.cxx @@ -33,6 +33,7 @@ ConfigureDef(config_express); NotifyCategoryDef(express, ""); +NotifyCategoryDef(ipc, ""); extern void init_system_type_handles(); diff --git a/panda/src/express/config_express.h b/panda/src/express/config_express.h index 9e8fa487d1..2e10aeea4a 100644 --- a/panda/src/express/config_express.h +++ b/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 diff --git a/panda/src/express/express_composite1.cxx b/panda/src/express/express_composite1.cxx index b5571cb7a2..fbe1277066 100644 --- a/panda/src/express/express_composite1.cxx +++ b/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" diff --git a/panda/src/express/express_composite2.cxx b/panda/src/express/express_composite2.cxx index 5fdf01c8ff..1eab3c6c32 100644 --- a/panda/src/express/express_composite2.cxx +++ b/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" diff --git a/panda/src/express/mutex.I b/panda/src/express/mutex.I new file mode 100644 index 0000000000..363651a195 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 ©) { + nassertv(false); +} + +//////////////////////////////////////////////////////////////////// +// Function: Mutex::Copy Assignment Operator +// Access: Private +// Description: Do not attempt to copy mutexes. +//////////////////////////////////////////////////////////////////// +INLINE void Mutex:: +operator = (const Mutex ©) { + 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(); +} diff --git a/panda/src/ipc/ipc_file.I b/panda/src/express/mutex.cxx similarity index 88% rename from panda/src/ipc/ipc_file.I rename to panda/src/express/mutex.cxx index 659b6ecad1..31fd0a6e6c 100644 --- a/panda/src/ipc/ipc_file.I +++ b/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 @@ // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// + +#include "mutex.h" diff --git a/panda/src/express/mutex.h b/panda/src/express/mutex.h new file mode 100644 index 0000000000..ed1fc3467e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 ©); + INLINE void operator = (const Mutex ©); + +public: + INLINE void lock(); + INLINE void release(); + +private: + MutexImpl _impl; +}; + +#include "mutex.I" + +#endif diff --git a/panda/src/express/mutexDummyImpl.I b/panda/src/express/mutexDummyImpl.I new file mode 100644 index 0000000000..6a91a7f976 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 +} diff --git a/panda/src/express/mutexDummyImpl.cxx b/panda/src/express/mutexDummyImpl.cxx new file mode 100644 index 0000000000..58947d5581 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "selectIpcImpl.h" + +#ifdef IPC_DUMMY_IMPL + +#include "mutexDummyImpl.h" + +#endif // IPC_DUMMY_IMPL diff --git a/panda/src/express/mutexDummyImpl.h b/panda/src/express/mutexDummyImpl.h new file mode 100644 index 0000000000..dd728bbf58 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/express/mutexHolder.I b/panda/src/express/mutexHolder.I new file mode 100644 index 0000000000..89d923765a --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 ©) { + nassertv(false); +} + +//////////////////////////////////////////////////////////////////// +// Function: MutexHolder::Copy Assignment Operator +// Access: Private +// Description: Do not attempt to copy MutexHolders. +//////////////////////////////////////////////////////////////////// +INLINE void MutexHolder:: +operator = (const MutexHolder ©) { + nassertv(false); +} diff --git a/panda/src/express/mutexHolder.cxx b/panda/src/express/mutexHolder.cxx new file mode 100644 index 0000000000..89627eeb90 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "mutexHolder.h" diff --git a/panda/src/express/mutexHolder.h b/panda/src/express/mutexHolder.h new file mode 100644 index 0000000000..ad7b7baebe --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 ©); + INLINE void operator = (const MutexHolder ©); + +private: +#ifdef HAVE_IPC + Mutex *_mutex; +#endif +}; + +#include "mutexHolder.I" + +#endif diff --git a/panda/src/ipc/ipc_nt_traits.cxx b/panda/src/express/mutexImpl.h similarity index 53% rename from panda/src/ipc/ipc_nt_traits.cxx rename to panda/src/express/mutexImpl.h index b3e8298584..05dbc9ff00 100644 --- a/panda/src/ipc/ipc_nt_traits.cxx +++ b/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 + + + diff --git a/panda/src/express/mutexNsprImpl.I b/panda/src/express/mutexNsprImpl.I new file mode 100644 index 0000000000..6e344e8531 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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); +} diff --git a/panda/src/express/mutexNsprImpl.cxx b/panda/src/express/mutexNsprImpl.cxx new file mode 100644 index 0000000000..ad3d045c2e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "selectIpcImpl.h" + +#ifdef IPC_NSPR_IMPL + +#include "mutexNsprImpl.h" + +#endif // IPC_NSPR_IMPL diff --git a/panda/src/express/mutexNsprImpl.h b/panda/src/express/mutexNsprImpl.h new file mode 100644 index 0000000000..845ebe0c04 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef MUTEXNSPRIMPL_H +#define MUTEXNSPRIMPL_H + +#include "pandabase.h" +#include "selectIpcImpl.h" + +#ifdef IPC_NSPR_IMPL + +#include "notify.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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 diff --git a/panda/src/express/referenceCount.I b/panda/src/express/referenceCount.I index cc37c55336..0510a07d21 100644 --- a/panda/src/express/referenceCount.I +++ b/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); + nassertr(_ref_count >= 0, 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 - - ((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 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; diff --git a/panda/src/express/referenceCount.h b/panda/src/express/referenceCount.h index 595f530d43..ef78a00326 100644 --- a/panda/src/express/referenceCount.h +++ b/panda/src/express/referenceCount.h @@ -24,6 +24,7 @@ #include "typedObject.h" #include "memoryUsage.h" #include "config_express.h" +#include "atomicAdjust.h" #include @@ -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; diff --git a/panda/src/express/selectIpcImpl.h b/panda/src/express/selectIpcImpl.h new file mode 100644 index 0000000000..6da997e05e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/express/test_threaddata.cxx b/panda/src/express/test_threaddata.cxx new file mode 100644 index 0000000000..6fcd697b69 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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; +} diff --git a/panda/src/express/thread.I b/panda/src/express/thread.I new file mode 100644 index 0000000000..ac077e2fa4 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 ©) : _impl(this) { + nassertv(false); +} + +//////////////////////////////////////////////////////////////////// +// Function: Thread::Copy Assignment Operator +// Access: Private +// Description: Do not attempt to copy threads. +//////////////////////////////////////////////////////////////////// +INLINE void Thread:: +operator = (const Thread ©) { + 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); +} diff --git a/panda/src/express/thread.cxx b/panda/src/express/thread.cxx new file mode 100644 index 0000000000..5375bac786 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "thread.h" + + +//////////////////////////////////////////////////////////////////// +// Function: Thread::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +Thread:: +~Thread() { +} diff --git a/panda/src/express/thread.h b/panda/src/express/thread.h new file mode 100644 index 0000000000..6715e49b6b --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 ©); + INLINE void operator = (const Thread ©); + +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 diff --git a/panda/src/express/threadDummyImpl.I b/panda/src/express/threadDummyImpl.I new file mode 100644 index 0000000000..08eefa67ff --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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) { +} diff --git a/panda/src/express/threadDummyImpl.cxx b/panda/src/express/threadDummyImpl.cxx new file mode 100644 index 0000000000..e5d79f16a7 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "selectIpcImpl.h" + +#ifdef IPC_DUMMY_IMPL + +#include "threadDummyImpl.h" + +#endif // IPC_DUMMY_IMPL diff --git a/panda/src/express/threadDummyImpl.h b/panda/src/express/threadDummyImpl.h new file mode 100644 index 0000000000..87fd5e66d7 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 + +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 diff --git a/panda/src/express/threadImpl.h b/panda/src/express/threadImpl.h new file mode 100644 index 0000000000..fe330a15b1 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/express/threadNsprImpl.I b/panda/src/express/threadNsprImpl.I new file mode 100644 index 0000000000..43d82c1e2d --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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)); +} diff --git a/panda/src/express/threadNsprImpl.cxx b/panda/src/express/threadNsprImpl.cxx new file mode 100644 index 0000000000..384a0f1a04 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 diff --git a/panda/src/express/threadNsprImpl.h b/panda/src/express/threadNsprImpl.h new file mode 100644 index 0000000000..fc9902a5d4 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 +#include + +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 diff --git a/panda/src/ipc/ipc_library.h b/panda/src/express/threadPriority.h similarity index 50% rename from panda/src/ipc/ipc_library.h rename to panda/src/express/threadPriority.h index b097d25415..68831ffe7d 100644 --- a/panda/src/ipc/ipc_library.h +++ b/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 +#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 diff --git a/panda/src/ipc/Sources.pp b/panda/src/ipc/Sources.pp deleted file mode 100644 index 290f39edcb..0000000000 --- a/panda/src/ipc/Sources.pp +++ /dev/null @@ -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 diff --git a/panda/src/ipc/ipc.cxx b/panda/src/ipc/ipc.cxx deleted file mode 100644 index ec9d121d9f..0000000000 --- a/panda/src/ipc/ipc.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#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; -} - - diff --git a/panda/src/ipc/ipc_composite1.cxx b/panda/src/ipc/ipc_composite1.cxx deleted file mode 100644 index 59bb41627c..0000000000 --- a/panda/src/ipc/ipc_composite1.cxx +++ /dev/null @@ -1,4 +0,0 @@ - -#include "ipc.cxx" -#include "ipc_traits.cxx" - diff --git a/panda/src/ipc/ipc_condition.h b/panda/src/ipc/ipc_condition.h deleted file mode 100644 index df5fa1accc..0000000000 --- a/panda/src/ipc/ipc_condition.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_CONDITION_H__ -#define __IPC_CONDITION_H__ - -#include - -#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__ */ diff --git a/panda/src/ipc/ipc_file.h b/panda/src/ipc/ipc_file.h deleted file mode 100644 index 29373e17d9..0000000000 --- a/panda/src/ipc/ipc_file.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_FILE_H__ -#define __IPC_FILE_H__ - -#include -#include -#include -#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__ */ - diff --git a/panda/src/ipc/ipc_mach_traits.h b/panda/src/ipc/ipc_mach_traits.h deleted file mode 100644 index 192a8d5ffe..0000000000 --- a/panda/src/ipc/ipc_mach_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_MACH_TRAITS_H__ -#define __IPC_MACH_TRAITS_H__ - -#include - -#include -#include -#include -#include - -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 - -#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__ */ diff --git a/panda/src/ipc/ipc_nspr_traits.h b/panda/src/ipc/ipc_nspr_traits.h deleted file mode 100644 index 2f6b8a3f0f..0000000000 --- a/panda/src/ipc/ipc_nspr_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_NSPR_TRAITS_H__ -#define __IPC_NSPR_TRAITS_H__ - -#include -#include - -#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__ */ diff --git a/panda/src/ipc/ipc_nt_traits.h b/panda/src/ipc/ipc_nt_traits.h deleted file mode 100644 index 6a30e05077..0000000000 --- a/panda/src/ipc/ipc_nt_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_NT_TRAITS_H__ -#define __IPC_NT_TRAITS_H__ - -#include - -#include -#include -#define WINDOWS_LEAN_AND_MEAN -#include -#undef WINDOWS_LEAN_AND_MEAN -#include - -#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 - -#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 -/* -extern "C" { -void usleep(unsigned long); -} -*/ -#endif /* __GNUC__ */ - -#include -#include -#include -#include - -#if (defined(__GLIBC__) && __GLIBC__ >= 2) -// typedef of struct timeval and gettimeofday(); -#include -#include -#endif /* __GLIBC__ */ - -// #if defined(__linux__) && defined(_MIT_POSIX_THREADS) -// #include -// #endif /* __linux__ & _MIT_POSIX_THREADS */ - -#if defined(__sgi) -#define PthreadSupportThreadPriority -// this next is just a guess -#define PthreadDraftVersion 10 -#include -#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, - ¶m)); -#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__ */ diff --git a/panda/src/ipc/ipc_ps2_traits.h b/panda/src/ipc/ipc_ps2_traits.h deleted file mode 100644 index c1c355ef85..0000000000 --- a/panda/src/ipc/ipc_ps2_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __ipc_ps2_traits_h__ -#define __ipc_ps2_traits_h__ - -#include -#include -#include -#include -#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 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::iterator begin = waiting_thread_list.begin(); - plist::iterator end = waiting_thread_list.end(); - plist::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 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::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::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__ diff --git a/panda/src/ipc/ipc_semaphore.h b/panda/src/ipc/ipc_semaphore.h deleted file mode 100644 index 6418a6bcd8..0000000000 --- a/panda/src/ipc/ipc_semaphore.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_SEMAPHORE_H__ -#define __IPC_SEMAPHORE_H__ - -#include - -#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__ */ diff --git a/panda/src/ipc/ipc_solaris_traits.h b/panda/src/ipc/ipc_solaris_traits.h deleted file mode 100644 index f9432ecde9..0000000000 --- a/panda/src/ipc/ipc_solaris_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_SOLARIS_TRAITS_H__ -#define __IPC_SOLARIS_TRAITS_H__ - -#include - -#include -#include -#include - -#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__ */ diff --git a/panda/src/ipc/ipc_thread.h b/panda/src/ipc/ipc_thread.h deleted file mode 100644 index 796f9af1fd..0000000000 --- a/panda/src/ipc/ipc_thread.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_THREAD_H__ -#define __IPC_THREAD_H__ - -#include -#include - -#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__ */ diff --git a/panda/src/ipc/ipc_traits.cxx b/panda/src/ipc/ipc_traits.cxx deleted file mode 100644 index 759ff679d4..0000000000 --- a/panda/src/ipc/ipc_traits.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#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 -#include "pmap.h" - -ConfigureFn(ipc_trait) { - ipc_traits::thread_class::BuildRootThread(); -} - -pvector 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 */ - - diff --git a/panda/src/ipc/ipc_traits.h b/panda/src/ipc/ipc_traits.h deleted file mode 100644 index 6488b2f5c1..0000000000 --- a/panda/src/ipc/ipc_traits.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __IPC_TRAITS_H__ -#define __IPC_TRAITS_H__ - -#include -#include - -// 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 - -#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__ */ diff --git a/panda/src/ipc/loom.cxx b/panda/src/ipc/loom.cxx deleted file mode 100644 index 1985b0c315..0000000000 --- a/panda/src/ipc/loom.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "loom_internal.h" -#include - -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(); - } -} diff --git a/panda/src/ipc/loom.h b/panda/src/ipc/loom.h deleted file mode 100644 index 43b321bf8b..0000000000 --- a/panda/src/ipc/loom.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __LOOM_H__ -#define __LOOM_H__ - -#include - -#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 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__ */ diff --git a/panda/src/ipc/loom_internal.h b/panda/src/ipc/loom_internal.h deleted file mode 100644 index a7f1347761..0000000000 --- a/panda/src/ipc/loom_internal.h +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef __LOOM_INTERNAL_H__ -#define __LOOM_INTERNAL_H__ - -#include - -#include "loom.h" -#include "ipc_mutex.h" -#include "ipc_condition.h" -#include "ipc_thread.h" -#include "plist.h" - -class app_service; - -typedef std::plist 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__ */ diff --git a/panda/src/ipc/loom_main.cxx b/panda/src/ipc/loom_main.cxx deleted file mode 100644 index 9a14a4566d..0000000000 --- a/panda/src/ipc/loom_main.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "loom_internal.h" -#include -#include -#include - -#include - -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; ilock(); - 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); -} diff --git a/panda/src/ipc/loom_test1.cxx b/panda/src/ipc/loom_test1.cxx deleted file mode 100644 index 7701eb8804..0000000000 --- a/panda/src/ipc/loom_test1.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "loom.h" -#include - -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); -} diff --git a/panda/src/ipc/loom_test2.cxx b/panda/src/ipc/loom_test2.cxx deleted file mode 100644 index 3ba7b333e7..0000000000 --- a/panda/src/ipc/loom_test2.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "loom.h" -#include - -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); -} diff --git a/panda/src/ipc/test_diners.cxx b/panda/src/ipc/test_diners.cxx deleted file mode 100644 index fb8fc34bc0..0000000000 --- a/panda/src/ipc/test_diners.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -// A solution to the infamous dining philosophers, implemented using the -// threading abstraction. This program exercises thread creation and -// destruction, mutexes, and condition variables. - -#include -#include -#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 -#include "ipc_file.h" -#include -#include -#include - -#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; -} - - - - diff --git a/panda/src/ipc/test_priority.cxx b/panda/src/ipc/test_priority.cxx deleted file mode 100644 index 317bd92858..0000000000 --- a/panda/src/ipc/test_priority.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include -#include -#include -#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 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 -#include -#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); - } -} diff --git a/panda/src/ipc/test_thread.cxx b/panda/src/ipc/test_thread.cxx deleted file mode 100644 index 54c831981e..0000000000 --- a/panda/src/ipc/test_thread.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include -#include -#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; -} diff --git a/panda/src/ipc/test_threaddata.cxx b/panda/src/ipc/test_threaddata.cxx deleted file mode 100644 index 2bde7bb905..0000000000 --- a/panda/src/ipc/test_threaddata.cxx +++ /dev/null @@ -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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include -#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; -} diff --git a/panda/src/pgraph/loader.cxx b/panda/src/pgraph/loader.cxx index be2ff2887a..50a3351596 100644 --- a/panda/src/pgraph/loader.cxx +++ b/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