00001 // Filename: asyncUtility.cxx 00002 // Created by: mike (09Jan97) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "config_downloader.h" 00020 #include "asyncUtility.h" 00021 00022 #if defined(WIN32) 00023 #define WINDOWS_LEAN_AND_MEAN 00024 #include <wtypes.h> 00025 #undef WINDOWS_LEAN_AND_MEAN 00026 #else 00027 #include <sys/time.h> 00028 #endif 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Defines 00032 //////////////////////////////////////////////////////////////////// 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: AsyncUtility::Constructor 00036 // Access: Public 00037 // Description: 00038 //////////////////////////////////////////////////////////////////// 00039 AsyncUtility:: 00040 AsyncUtility(float frequency) : _frequency(frequency) { 00041 _next_token = 1; 00042 _shutdown = false; 00043 _threaded = false; 00044 _threads_enabled = true; 00045 00046 #ifdef OLD_HAVE_IPC 00047 _request_cond = new condition_variable(_lock); 00048 #endif 00049 } 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: AsyncUtility::Destructor 00053 // Access: Public 00054 // Description: 00055 //////////////////////////////////////////////////////////////////// 00056 AsyncUtility:: 00057 ~AsyncUtility() { 00058 #ifdef OLD_HAVE_IPC 00059 delete _request_cond; 00060 #endif 00061 } 00062 00063 //////////////////////////////////////////////////////////////////// 00064 // Function: AsyncUtility::create_thread 00065 // Access: Public 00066 // Description: 00067 //////////////////////////////////////////////////////////////////// 00068 void AsyncUtility:: 00069 create_thread(void) { 00070 #ifdef OLD_HAVE_IPC 00071 if (_threaded == false && _threads_enabled == true) { 00072 downloader_cat.debug() 00073 << "AsyncUtility::create_thread()" << endl; 00074 _thread = thread::create(&st_callback, this, thread::PRIORITY_NORMAL); 00075 _threaded = true; 00076 } 00077 #endif 00078 } 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Function: AsyncUtility::destroy_thread 00082 // Access: Protected 00083 // Description: 00084 //////////////////////////////////////////////////////////////////// 00085 void AsyncUtility:: 00086 destroy_thread(void) { 00087 #ifdef OLD_HAVE_IPC 00088 if (_threaded == false) 00089 return; 00090 00091 // Tell the thread to shut itself down. 00092 // We need to grab the lock in order to signal the condition variable 00093 _lock.lock(); 00094 _shutdown = true; 00095 _request_cond->signal(); 00096 _lock.unlock(); 00097 00098 // Join the loader thread - calling process blocks until the loader 00099 // thread returns. 00100 void *ret; 00101 _thread->join(&ret); 00102 #endif 00103 } 00104 00105 //////////////////////////////////////////////////////////////////// 00106 // Function: AsyncUtility::st_callback 00107 // Access: Protected, Static 00108 // Description: This is a static wrapper around the callback() 00109 // method, below. It's static just so we can pass it to 00110 // the thread-creation function. In addition, the 00111 // function has a void* return type even though we 00112 // don't actually return anything. This is necessary 00113 // because ipc assumes a function that does not return 00114 // anything indicates that the associated thread should 00115 // be created as unjoinable (detached). 00116 //////////////////////////////////////////////////////////////////// 00117 void* AsyncUtility:: 00118 st_callback(void *arg) { 00119 #ifdef OLD_HAVE_IPC 00120 nassertr(arg != NULL, NULL); 00121 ((AsyncUtility *)arg)->callback(); 00122 #endif 00123 return NULL; 00124 } 00125 00126 //////////////////////////////////////////////////////////////////// 00127 // Function: AsyncUtility::callback 00128 // Access: Protected 00129 // Description: This is the main body of the sub-thread. It waits 00130 // forever for a request to show up, and then serves it. 00131 //////////////////////////////////////////////////////////////////// 00132 void AsyncUtility:: 00133 callback(void) { 00134 #ifdef OLD_HAVE_IPC 00135 while (process_request()) { 00136 // Sleep until a signal arrives 00137 _lock.lock(); 00138 _request_cond->wait(); 00139 _lock.unlock(); 00140 } 00141 #endif 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: AsyncUtility::nap 00146 // Access: Protected 00147 // Description: 00148 //////////////////////////////////////////////////////////////////// 00149 void AsyncUtility:: 00150 nap(void) const { 00151 #ifdef OLD_HAVE_IPC 00152 #ifdef WIN32 00153 _sleep((DWORD)(1000 * _frequency)); 00154 #else 00155 struct timeval tv; 00156 tv.tv_sec = 0; 00157 tv.tv_usec = (long)(1000000 * _frequency); 00158 select(0, NULL, NULL, NULL, &tv); 00159 #endif 00160 #endif // OLD_HAVE_IPC 00161 }