Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

o Give Thread a lifecycle we can wait on.

o Move pthread_join() out of WaitFinished()
  • Loading branch information...
commit 6fd405f6002cac0f8ba928a347d378531f5c468b 1 parent 7fa80f5
@hzeller authored
Showing with 77 additions and 19 deletions.
  1. +10 −5 folve-filesystem.cc
  2. +50 −10 util.cc
  3. +17 −4 util.h
View
15 folve-filesystem.cc
@@ -388,9 +388,9 @@ class SndFileHandler :
}
virtual void NotifyPassedProcessorUnreferenced() {
- if (buffer_thread_ && !buffer_thread_->started()) {
- buffer_thread_->Start();
- }
+ if (!buffer_thread_) return;
+ assert(!buffer_thread_->StartCalled());
+ buffer_thread_->Start();
}
static bool ExtractDirAndSuffix(const std::string &filename,
@@ -448,6 +448,7 @@ class SndFileHandler :
base_stats_.out_gapless = true;
SaveOutputValues();
processor_ = NULL; // we handed over ownership.
+ Close(); // make sure that our thread is done.
next_file->NotifyPassedProcessorUnreferenced();
}
if (next_file) fs_->Close(found->c_str(), next_file);
@@ -457,7 +458,8 @@ class SndFileHandler :
if (input_frames_left_ == 0) {
Close();
}
- if (buffer_thread_ && !buffer_thread_->started()) {
+ if (buffer_thread_ && !buffer_thread_->StartCalled()) {
+ // First time we're called; fire up our thread.
buffer_thread_->Start();
}
return input_frames_left_;
@@ -542,6 +544,10 @@ class SndFileHandler :
void Close() {
if (snd_out_ == NULL) return; // done.
+ if (buffer_thread_) {
+ buffer_thread_->StopRunning();
+ buffer_thread_->WaitFinished();
+ }
SaveOutputValues();
if (base_stats_.max_output_value > 1.0) {
syslog(LOG_ERR, "Observed output clipping in '%s': "
@@ -557,7 +563,6 @@ class SndFileHandler :
if (snd_in_) sf_close(snd_in_);
if (snd_out_) sf_close(snd_out_);
snd_out_ = NULL;
- if (buffer_thread_) buffer_thread_->StopRunning();
close(filedes_);
}
View
60 util.cc
@@ -23,6 +23,7 @@
#include <syslog.h>
#include <cstdarg>
+#include <string.h>
double folve::CurrentTime() {
struct timeval tv;
@@ -80,22 +81,61 @@ bool folve::HasSuffix(const std::string &str, const std::string &suffix) {
suffix.length(), suffix) == 0;
}
-static void *CallRun(void *tobject) {
- reinterpret_cast<folve::Thread*>(tobject)->Run();
+void *folve::Thread::PthreadCallRun(void *tobject) {
+ reinterpret_cast<folve::Thread*>(tobject)->DoRun();
return NULL;
}
-folve::Thread::Thread() : started_(false) {}
-folve::Thread::~Thread() { WaitFinished(); }
+folve::Thread::Thread() : lifecycle_(INIT) {
+ pthread_cond_init(&lifecycle_condition_, NULL);
+}
+folve::Thread::~Thread() {
+ WaitFinished();
+ MutexLock l(&lifecycle_mutex_);
+ if (lifecycle_ == STOPPED) {
+ int result = pthread_join(thread_, NULL);
+ if (result != 0) {
+ fprintf(stderr, "err code: %d %s\n", result, strerror(result));
+ assert(result == 0);
+ }
+ lifecycle_ = JOINED; // just for good measure.
+ }
+}
+
+void folve::Thread::DoRun() {
+ Run();
+ SetLifecycle(STOPPED);
+}
+
+bool folve::Thread::StartCalled() { // more like: beyond init.
+ MutexLock l(&lifecycle_mutex_);
+ return lifecycle_ >= START_CALLED;
+}
+
+void folve::Thread::SetLifecycle(Lifecycle lifecycle) {
+ MutexLock l(&lifecycle_mutex_);
+ lifecycle_ = lifecycle;
+ pthread_cond_signal(&lifecycle_condition_);
+}
void folve::Thread::Start() {
- assert(!started_);
- pthread_create(&thread_, NULL, &CallRun, this);
- started_ = true;
+ MutexLock l(&lifecycle_mutex_);
+ assert(lifecycle_ == INIT);
+ pthread_create(&thread_, NULL, &PthreadCallRun, this);
+ lifecycle_ = START_CALLED;
}
void folve::Thread::WaitFinished() {
- if (!started_) return;
- pthread_join(thread_, NULL);
- started_ = false;
+ MutexLock l(&lifecycle_mutex_);
+ if (lifecycle_ == INIT) {
+ lifecycle_ = JOINED; // Never started ? Consider ourself joined.
+ return;
+ }
+ if (lifecycle_ == STOPPED || lifecycle_ == JOINED) {
+ return;
+ }
+ assert(lifecycle_ == START_CALLED); // that is what we're in now.
+ while (lifecycle_ != STOPPED) {
+ lifecycle_mutex_.WaitOn(&lifecycle_condition_);
+ }
}
View
21 util.h
@@ -58,6 +58,7 @@ namespace folve {
~Mutex() { pthread_mutex_destroy(&mutex_); }
void Lock() { pthread_mutex_lock(&mutex_); }
void Unlock() { pthread_mutex_unlock(&mutex_); }
+ void WaitOn(pthread_cond_t *cond) { pthread_cond_wait(cond, &mutex_); }
private:
pthread_mutex_t mutex_;
@@ -68,7 +69,6 @@ namespace folve {
public:
MutexLock(Mutex *m) : mutex_(m) { mutex_->Lock(); }
~MutexLock() { mutex_->Unlock(); }
-
private:
Mutex *const mutex_;
};
@@ -80,15 +80,28 @@ namespace folve {
virtual ~Thread();
void Start();
- bool started() const { return started_; }
-
+ bool StartCalled();
void WaitFinished();
// Override this.
virtual void Run() = 0;
private:
- bool started_;
+ enum Lifecycle {
+ INIT,
+ START_CALLED,
+ STOPPED,
+ JOINED,
+ };
+
+ void DoRun();
+ static void *PthreadCallRun(void *object);
+ void SetLifecycle(Lifecycle l);
+
+ pthread_cond_t lifecycle_condition_;
+ Mutex lifecycle_mutex_;
+ Lifecycle lifecycle_;
+
pthread_t thread_;
};
} // namespece folve
Please sign in to comment.
Something went wrong with that request. Please try again.