Browse Source

fix for exiting internal threads

Cary Sandvig 25 years ago
parent
commit
b2c8a4a204

+ 24 - 7
panda/src/audio/audio_linux_traits.cxx

@@ -29,6 +29,7 @@ static byte* scratch_buffer;
 static byte* fetch_buffer;
 static byte* fetch_buffer;
 static int want_buffers = 0, have_buffers = 0;
 static int want_buffers = 0, have_buffers = 0;
 static bool initializing = true;
 static bool initializing = true;
+static bool stop_mixing = false;
 static int output_fd;
 static int output_fd;
 static thread* update_thread;
 static thread* update_thread;
 static int sample_size = sizeof(short);
 static int sample_size = sizeof(short);
@@ -158,35 +159,35 @@ static void update_linux(void) {
   }
   }
 }
 }
 
 
-static void internal_update(void*) {
+static void* internal_update(void*) {
   if ((output_fd = open(audio_device->c_str(), O_WRONLY, 0)) == -1) {
   if ((output_fd = open(audio_device->c_str(), O_WRONLY, 0)) == -1) {
     audio_cat->error() << "could not open '" << audio_device << "'" << endl;
     audio_cat->error() << "could not open '" << audio_device << "'" << endl;
-    return;
+    return (void*)0L;
   }
   }
   // this one I don't know about
   // this one I don't know about
   int fragsize = 0x0004000c;
   int fragsize = 0x0004000c;
   if (ioctl(output_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize) == -1) {
   if (ioctl(output_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize) == -1) {
     audio_cat->error() << "faied to set fragment size" << endl;
     audio_cat->error() << "faied to set fragment size" << endl;
-    return;
+    return (void*)0L;
   }
   }
   // for now signed, 16-bit, little endian
   // for now signed, 16-bit, little endian
   int format = AFMT_S16_LE;
   int format = AFMT_S16_LE;
   if (ioctl(output_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
   if (ioctl(output_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
     audio_cat->error() << "failed to set format on the dsp" << endl;
     audio_cat->error() << "failed to set format on the dsp" << endl;
-    return;
+    return (void*)0L;
   }
   }
   // set stereo
   // set stereo
   int stereo = 1;
   int stereo = 1;
   if (ioctl(output_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
   if (ioctl(output_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
     audio_cat->error() << "failed to set stereo on the dsp" << endl;
     audio_cat->error() << "failed to set stereo on the dsp" << endl;
-    return;
+    return (void*)0L;
   }
   }
   // set the frequency
   // set the frequency
   if (ioctl(output_fd, SNDCTL_DSP_SPEED, &audio_mix_freq) == -1) {
   if (ioctl(output_fd, SNDCTL_DSP_SPEED, &audio_mix_freq) == -1) {
     audio_cat->error() << "failed to set frequency on the dsp" << endl;
     audio_cat->error() << "failed to set frequency on the dsp" << endl;
-    return;
+    return (void*)0L;
   }
   }
-  while (1) {
+  while (!stop_mixing) {
     if (have_buffers == 0) {
     if (have_buffers == 0) {
       ipc_traits::sleep(0, audio_auto_update_delay);
       ipc_traits::sleep(0, audio_auto_update_delay);
     } else {
     } else {
@@ -199,6 +200,20 @@ static void internal_update(void*) {
       }
       }
     }
     }
   }
   }
+  delete [] buffer1;
+  delete [] buffer2;
+  delete [] scratch_buffer;
+  delete [] fetch_buffer;
+  delete [] zero_buffer;
+  stop_mixing = false;
+  audio_cat->debug() << "exiting internal thread" << endl;
+  return (void*)0L;
+}
+
+static void shutdown_linux(void) {
+  stop_mixing = true;
+  while (stop_mixing);
+  audio_cat->debug() << "I believe the internal thread has exited" << endl;
 }
 }
 
 
 static void initialize(void) {
 static void initialize(void) {
@@ -220,12 +235,14 @@ static void initialize(void) {
   want_buffers = 2;
   want_buffers = 2;
   have_buffers = 0;
   have_buffers = 0;
   initializing = true;
   initializing = true;
+  stop_mixing = false;
 
 
   audio_cat->info() << "spawning internal update thread" << endl;
   audio_cat->info() << "spawning internal update thread" << endl;
   update_thread = thread::create(internal_update, (void*)0L,
   update_thread = thread::create(internal_update, (void*)0L,
 				 thread::PRIORITY_NORMAL);
 				 thread::PRIORITY_NORMAL);
 
 
   AudioManager::set_update_func(update_linux);
   AudioManager::set_update_func(update_linux);
+  AudioManager::set_shutdown_func(shutdown_linux);
   have_initialized = true;
   have_initialized = true;
 }
 }
 
 

+ 10 - 1
panda/src/audio/audio_manager.I

@@ -41,6 +41,15 @@ INLINE void AudioManager::spawn_update(void) {
   get_ptr()->ns_spawn_update();
   get_ptr()->ns_spawn_update();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AudioManager::shutdown
+//       Access: Public, Static
+//  Description: kill any internal threads, free any internal data
+////////////////////////////////////////////////////////////////////
+INLINE void AudioManager::shutdown(void) {
+  get_ptr()->ns_shutdown();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioManager::set_volume (sample)
 //     Function: AudioManager::set_volume (sample)
 //       Access: Public, Static
 //       Access: Public, Static
@@ -66,4 +75,4 @@ INLINE void AudioManager::set_volume(AudioMusic* music, int v) {
 //               directly; there's only supposed to be one AudioManager
 //               directly; there's only supposed to be one AudioManager
 //               in the universe and it constructs itself.
 //               in the universe and it constructs itself.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE AudioManager::AudioManager(void) : _spawned((thread*)0L) {}
+INLINE AudioManager::AudioManager(void) {}

+ 49 - 4
panda/src/audio/audio_manager.cxx

@@ -9,7 +9,11 @@
 AudioManager* AudioManager::_global_ptr = (AudioManager*)0L;
 AudioManager* AudioManager::_global_ptr = (AudioManager*)0L;
 AudioManager::UpdateFunc* AudioManager::_update_func =
 AudioManager::UpdateFunc* AudioManager::_update_func =
     (AudioManager::UpdateFunc*)0L;
     (AudioManager::UpdateFunc*)0L;
+AudioManager::ShutdownFunc* AudioManager::_shutdown_func =
+    (AudioManager::ShutdownFunc*)0L;
 mutex AudioManager::_manager_mutex;
 mutex AudioManager::_manager_mutex;
+bool* AudioManager::_quit = (bool*)0L;
+thread* AudioManager::_spawned = (thread*)0L;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioManager::set_update_func
 //     Function: AudioManager::set_update_func
@@ -24,6 +28,21 @@ void AudioManager::set_update_func(AudioManager::UpdateFunc* func) {
   _update_func = func;
   _update_func = func;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AudioManager::set_shutdown_func
+//       Access: Public, Static
+//  Description: register a function that will shutdown the internal
+//               audio state
+////////////////////////////////////////////////////////////////////
+void AudioManager::set_shutdown_func(AudioManager::ShutdownFunc* func) {
+  if (_shutdown_func != (AudioManager::ShutdownFunc*)0L)
+    audio_cat->error() << "There maybe be more then one audio driver installed"
+		       << endl;
+  _shutdown_func = func;
+  if (_quit == (bool*)0L)
+    _quit = new bool(false);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioManager::get_ptr
 //     Function: AudioManager::get_ptr
 //       Access: Private, Static
 //       Access: Private, Static
@@ -59,11 +78,15 @@ void AudioManager::ns_play(AudioMusic* music) {
 //       Access: static
 //       Access: static
 //  Description: the thread function to call update forever.
 //  Description: the thread function to call update forever.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void AudioManager::spawned_update(void*) {
-  while (1) {
+void* AudioManager::spawned_update(void* data) {
+  bool* flag = (bool*)data;
+  while (! (*flag)) {
     AudioManager::update();
     AudioManager::update();
     ipc_traits::sleep(0, audio_auto_update_delay);
     ipc_traits::sleep(0, audio_auto_update_delay);
   }
   }
+  *flag = false;
+  audio_cat->debug() << "exiting update thread" << endl;
+  return (void*)0L;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -90,6 +113,28 @@ void AudioManager::ns_set_volume(AudioMusic* music, int v) {
 //  Description: spawn a thread that calls update every so often
 //  Description: spawn a thread that calls update every so often
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AudioManager::ns_spawn_update(void) {
 void AudioManager::ns_spawn_update(void) {
-  _spawned = thread::create(spawned_update, (void*)0L,
-			    thread::PRIORITY_NORMAL);
+  if (_spawned == (thread*)0L) {
+    if (_quit == (bool*)0L)
+      _quit = new bool(false);
+    *_quit = false;
+    _spawned = thread::create(spawned_update, _quit, thread::PRIORITY_NORMAL);
+  } else {
+    audio_cat->error() << "tried to spawn 2 update threads" << endl;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioManager::ns_shutdown
+//       Access: Private
+//  Description: non-static implementation of shutdown stuff
+////////////////////////////////////////////////////////////////////
+void AudioManager::ns_shutdown(void) {
+  if (_quit != (bool*)0L)
+    *_quit = true;
+  if (_shutdown_func != (ShutdownFunc*)0L)
+    (*_shutdown_func)();
+  if (_spawned != (thread*)0L)
+    while (*_quit);
+  audio_cat->debug() << "update thread has shutdown" << endl;
+  delete _quit;
 }
 }

+ 8 - 2
panda/src/audio/audio_manager.h

@@ -20,24 +20,30 @@ private:
   void ns_play(AudioSample*);
   void ns_play(AudioSample*);
   void ns_play(AudioMusic*);
   void ns_play(AudioMusic*);
   void ns_spawn_update(void);
   void ns_spawn_update(void);
+  void ns_shutdown(void);
   void ns_set_volume(AudioSample*, int);
   void ns_set_volume(AudioSample*, int);
   void ns_set_volume(AudioMusic*, int);
   void ns_set_volume(AudioMusic*, int);
 
 
   static AudioManager* get_ptr(void);
   static AudioManager* get_ptr(void);
-  static void spawned_update(void*);
+  static void* spawned_update(void*);
 
 
   typedef void UpdateFunc(void);
   typedef void UpdateFunc(void);
+  typedef void ShutdownFunc(void);
   static AudioManager* _global_ptr;
   static AudioManager* _global_ptr;
   static UpdateFunc* _update_func;
   static UpdateFunc* _update_func;
+  static ShutdownFunc* _shutdown_func;
   static mutex _manager_mutex;
   static mutex _manager_mutex;
-  thread* _spawned;
+  static bool* _quit;
+  static thread* _spawned;
 public:
 public:
   static void set_update_func(UpdateFunc*);
   static void set_update_func(UpdateFunc*);
+  static void set_shutdown_func(ShutdownFunc*);
 
 
   INLINE static void play(AudioSample*);
   INLINE static void play(AudioSample*);
   INLINE static void play(AudioMusic*);
   INLINE static void play(AudioMusic*);
   INLINE static void update(void);
   INLINE static void update(void);
   INLINE static void spawn_update(void);
   INLINE static void spawn_update(void);
+  INLINE static void shutdown(void);
   INLINE static void set_volume(AudioSample*, int);
   INLINE static void set_volume(AudioSample*, int);
   INLINE static void set_volume(AudioMusic*, int);
   INLINE static void set_volume(AudioMusic*, int);
 };
 };

+ 4 - 0
panda/src/audio/audio_win_traits.cxx

@@ -657,6 +657,10 @@ void WinMusic::destroy(AudioTraits::MusicClass* music) {
 WinPlaying::~WinPlaying(void) {
 WinPlaying::~WinPlaying(void) {
 }
 }
 
 
+AudioTraits::PlayingClass::PlayingStatus WinPlaying::status(void) {
+  return AudioTraits::PlayingClass::BAD;
+}
+
 WinPlayer* WinPlayer::_global_instance = (WinPlayer*)0L;
 WinPlayer* WinPlayer::_global_instance = (WinPlayer*)0L;
 
 
 WinPlayer::~WinPlayer(void) {
 WinPlayer::~WinPlayer(void) {

+ 2 - 0
panda/src/audio/audio_win_traits.h

@@ -69,6 +69,8 @@ class EXPCL_PANDA WinPlaying : public AudioTraits::PlayingClass {
 public:
 public:
   INLINE WinPlaying(void);
   INLINE WinPlaying(void);
   ~WinPlaying(void);
   ~WinPlaying(void);
+
+  virtual AudioTraits::PlayingClass::PlayingStatus status(void);
 };
 };
 
 
 class EXPCL_PANDA WinPlayer : public AudioTraits::PlayerClass {
 class EXPCL_PANDA WinPlayer : public AudioTraits::PlayerClass {