#include "gold.h"
#ifdef ENABLE_THREADS
#include <cstring>
#include <pthread.h>
#include "debug.h"
#include "gold-threads.h"
#include "workqueue.h"
#include "workqueue-internal.h"
namespace gold
{
class Workqueue_thread
{
public:
Workqueue_thread(Workqueue_threader_threadpool*, int thread_number);
~Workqueue_thread();
private:
Workqueue_thread(const Workqueue_thread&);
Workqueue_thread& operator=(const Workqueue_thread&);
void
check(const char* function, int err) const;
static void*
thread_body(void*);
Workqueue_threader_threadpool* threadpool_;
int thread_number_;
pthread_t tid_;
};
Workqueue_thread::Workqueue_thread(Workqueue_threader_threadpool* threadpool,
int thread_number)
: threadpool_(threadpool), thread_number_(thread_number)
{
pthread_attr_t attr;
int err = pthread_attr_init(&attr);
this->check("pthread_attr_init", err);
err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
this->check("pthread_attr_setdetachstate", err);
err = pthread_create(&this->tid_, &attr, &Workqueue_thread::thread_body,
reinterpret_cast<void*>(this));
this->check("pthread_create", err);
err = pthread_attr_destroy(&attr);
this->check("pthread_attr_destroy", err);
}
Workqueue_thread::~Workqueue_thread()
{
}
void
Workqueue_thread::check(const char* function, int err) const
{
if (err != 0)
gold_fatal(_("%s failed: %s"), function, strerror(err));
}
extern "C"
void*
Workqueue_thread::thread_body(void* arg)
{
Workqueue_thread* pwt = reinterpret_cast<Workqueue_thread*>(arg);
pwt->threadpool_->process(pwt->thread_number_);
delete pwt;
return NULL;
}
Workqueue_threader_threadpool::Workqueue_threader_threadpool(
Workqueue* workqueue)
: Workqueue_threader(workqueue),
check_thread_count_(0),
lock_(),
desired_thread_count_(1),
threads_(1)
{
}
Workqueue_threader_threadpool::~Workqueue_threader_threadpool()
{
this->get_workqueue()->set_thread_count(0);
}
void
Workqueue_threader_threadpool::set_thread_count(int thread_count)
{
int create;
{
Hold_lock hl(this->lock_);
this->desired_thread_count_ = thread_count;
create = this->desired_thread_count_ - this->threads_;
if (create < 0)
this->check_thread_count_ = 1;
}
if (create > 0)
{
for (int i = 0; i < create; ++i)
{
new Workqueue_thread(this, this->threads_);
++this->threads_;
}
}
}
bool
Workqueue_threader_threadpool::should_cancel_thread()
{
if (!this->check_thread_count_)
return false;
{
Hold_lock hl(this->lock_);
if (this->threads_ > this->desired_thread_count_)
{
--this->threads_;
return true;
}
this->check_thread_count_ = 0;
}
return false;
}
}
#endif