Replaced pthread with std:: thread and mutex

This commit is contained in:
Jean-Francois Dockes
2016-07-12 18:08:21 +02:00
parent d8f215b6ed
commit c1fad4afc7
33 changed files with 367 additions and 633 deletions
+4 -3
View File
@@ -16,16 +16,17 @@
*/
#include "autoconfig.h"
#include <mutex>
#include "rcldoc.h"
#include "fetcher.h"
#include "bglfetcher.h"
#include "log.h"
#include "ptmutex.h"
#include "beaglequeuecache.h"
// We use a single beagle cache object to access beagle data. We protect it
// against multiple thread access.
static PTMutexInit o_beagler_mutex;
static std::mutex o_beagler_mutex;
bool BGLDocFetcher::fetch(RclConfig* cnf, const Rcl::Doc& idoc, RawDoc& out)
{
@@ -36,7 +37,7 @@ bool BGLDocFetcher::fetch(RclConfig* cnf, const Rcl::Doc& idoc, RawDoc& out)
}
Rcl::Doc dotdoc;
{
PTMutexLocker locker(o_beagler_mutex);
std::unique_lock<std::mutex> locker(o_beagler_mutex);
// Retrieve from our webcache (beagle data). The beagler
// object is created at the first call of this routine and
// deleted when the program exits.
+6 -6
View File
@@ -85,13 +85,13 @@ extern void *FsIndexerInternfileWorker(void*);
// main thread either before or after the exciting part
class FSIFIMissingStore : public FIMissingStore {
#ifdef IDX_THREADS
PTMutexInit m_mutex;
std::mutex m_mutex;
#endif
public:
virtual void addMissing(const string& prog, const string& mt)
{
#ifdef IDX_THREADS
PTMutexLocker locker(m_mutex);
std::unique_lock<std::mutex> locker(m_mutex);
#endif
FIMissingStore::addMissing(prog, mt);
}
@@ -178,7 +178,7 @@ bool FsIndexer::index(int flags)
if (m_updater) {
#ifdef IDX_THREADS
PTMutexLocker locker(m_updater->m_mutex);
std::unique_lock<std::mutex> locker(m_updater->m_mutex);
#endif
m_updater->status.dbtotdocs = m_db->docCnt();
}
@@ -554,7 +554,7 @@ FsIndexer::processone(const std::string &fn, const struct stat *stp,
{
if (m_updater) {
#ifdef IDX_THREADS
PTMutexLocker locker(m_updater->m_mutex);
std::unique_lock<std::mutex> locker(m_updater->m_mutex);
#endif
if (!m_updater->update()) {
return FsTreeWalker::FtwStop;
@@ -668,7 +668,7 @@ FsIndexer::processonefile(RclConfig *config,
LOGDEB0("processone: up to date: " << (fn) << "\n" );
if (m_updater) {
#ifdef IDX_THREADS
PTMutexLocker locker(m_updater->m_mutex);
std::unique_lock<std::mutex> locker(m_updater->m_mutex);
#endif
// Status bar update, abort request etc.
m_updater->status.fn = fn;
@@ -799,7 +799,7 @@ FsIndexer::processonefile(RclConfig *config,
// Tell what we are doing and check for interrupt request
if (m_updater) {
#ifdef IDX_THREADS
PTMutexLocker locker(m_updater->m_mutex);
std::unique_lock<std::mutex> locker(m_updater->m_mutex);
#endif
++(m_updater->status.docsdone);
if (m_updater->status.dbtotdocs < m_updater->status.docsdone)
+3 -3
View File
@@ -18,11 +18,11 @@
#define _fsindexer_h_included_
#include <list>
#include <mutex>
#include "indexer.h"
#include "fstreewalk.h"
#ifdef IDX_THREADS
#include "ptmutex.h"
#include "workqueue.h"
#endif // IDX_THREADS
@@ -93,7 +93,7 @@ class FsIndexer : public FsTreeWalkerCB {
if (!dorecord)
return;
#ifdef IDX_THREADS
PTMutexLocker locker(mutex);
std::unique_lock<std::mutex> locker(mutex);
#endif
udis.push_back(udi);
}
@@ -103,7 +103,7 @@ class FsIndexer : public FsTreeWalkerCB {
}
private:
#ifdef IDX_THREADS
PTMutexInit mutex;
std::mutex mutex;
#endif
bool dorecord;
std::vector<std::string> udis;
+3 -5
View File
@@ -22,6 +22,7 @@
#include <list>
#include <map>
#include <vector>
#include <mutex>
using std::string;
using std::list;
@@ -30,9 +31,6 @@ using std::vector;
#include "rcldb.h"
#include "rcldoc.h"
#ifdef IDX_THREADS
#include "ptmutex.h"
#endif
class FsIndexer;
class BeagleQueueIndexer;
@@ -66,7 +64,7 @@ class DbIxStatus {
class DbIxStatusUpdater {
public:
#ifdef IDX_THREADS
PTMutexInit m_mutex;
std::mutex m_mutex;
#endif
DbIxStatus status;
virtual ~DbIxStatusUpdater(){}
@@ -75,7 +73,7 @@ class DbIxStatusUpdater {
virtual bool update(DbIxStatus::Phase phase, const string& fn)
{
#ifdef IDX_THREADS
PTMutexLocker lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
#endif
status.phase = phase;
status.fn = fn;
+6 -9
View File
@@ -32,6 +32,7 @@
#include <time.h>
#include <string>
#include <map>
#include <mutex>
#include "rclconfig.h"
@@ -78,16 +79,12 @@ class RclMonEventQueue {
public:
RclMonEventQueue();
~RclMonEventQueue();
/** Unlock queue and wait until there are new events.
* Returns with the queue locked */
bool wait(int secs = -1, bool *timedout = 0);
/** Unlock queue */
bool unlock();
/** Lock queue. */
bool lock();
/** Lock queue and add event. */
/** Wait for event or timeout. Returns with the queue locked */
std::unique_lock<std::mutex> wait(int secs = -1, bool *timedout = 0);
/** Add event. */
bool pushEvent(const RclMonEvent &ev);
void setTerminate(); /* To all threads: end processing */
/** To all threads: end processing */
void setTerminate();
bool ok();
bool empty();
RclMonEvent pop();
+96 -134
View File
@@ -24,7 +24,6 @@
* initialization function.
*/
#include <pthread.h>
#include <errno.h>
#include <fnmatch.h>
#include "safeunistd.h"
@@ -34,6 +33,11 @@
#include <cstdlib>
#include <list>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using std::list;
using std::vector;
@@ -51,8 +55,6 @@ using std::vector;
typedef unsigned long mttcast;
static pthread_t rcv_thrid;
// Seconds between auxiliary db (stem, spell) updates:
static const int dfltauxinterval = 60 *60;
static int auxinterval = dfltauxinterval;
@@ -135,13 +137,13 @@ public:
vector<DelayPat> m_delaypats;
RclConfig *m_config;
bool m_ok;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
std::mutex m_mutex;
std::condition_variable m_cond;
RclEQData()
: m_config(0), m_ok(false)
: m_config(0), m_ok(true)
{
if (!pthread_mutex_init(&m_mutex, 0) && !pthread_cond_init(&m_cond, 0))
m_ok = true;
}
void readDelayPats(int dfltsecs);
DelayPat searchDelayPats(const string& path)
@@ -192,8 +194,8 @@ void RclEQData::readDelayPats(int dfltsecs)
// when necessary.
void RclEQData::delayInsert(const queue_type::iterator &qit)
{
MONDEB(("RclEQData::delayInsert: minclock %lu\n",
(mttcast)qit->second.m_minclock));
MONDEB("RclEQData::delayInsert: minclock " << qit->second.m_minclock <<
std::endl);
for (delays_type::iterator dit = m_delays.begin();
dit != m_delays.end(); dit++) {
queue_type::iterator qit1 = *dit;
@@ -222,62 +224,33 @@ void RclMonEventQueue::setopts(int opts)
}
/** Wait until there is something to process on the queue, or timeout.
* Must be called with the queue locked
* returns a queue lock
*/
bool RclMonEventQueue::wait(int seconds, bool *top)
std::unique_lock<std::mutex> RclMonEventQueue::wait(int seconds, bool *top)
{
MONDEB(("RclMonEventQueue::wait\n"));
std::unique_lock<std::mutex> lock(m_data->m_mutex);
MONDEB("RclMonEventQueue::wait, seconds: " << seconds << std::endl);
if (!empty()) {
MONDEB(("RclMonEventQueue:: imm return\n"));
return true;
MONDEB("RclMonEventQueue:: immediate return\n");
return lock;
}
int err;
if (seconds > 0) {
struct timespec to;
to.tv_sec = time(0L) + seconds;
to.tv_nsec = 0;
if (top)
*top = false;
if ((err =
pthread_cond_timedwait(&m_data->m_cond, &m_data->m_mutex, &to))) {
if (err == ETIMEDOUT) {
*top = true;
MONDEB(("RclMonEventQueue:: timeout\n"));
return true;
}
LOGERR("RclMonEventQueue::wait:pthread_cond_timedwait failedwith err " << (err) << "\n" );
return false;
}
if (m_data->m_cond.wait_for(lock, std::chrono::seconds(seconds)) ==
std::cv_status::timeout) {
*top = true;
MONDEB("RclMonEventQueue:: timeout\n");
return lock;
}
} else {
if ((err = pthread_cond_wait(&m_data->m_cond, &m_data->m_mutex))) {
LOGERR("RclMonEventQueue::wait: pthread_cond_wait failedwith err " << (err) << "\n" );
return false;
}
m_data->m_cond.wait(lock);
}
MONDEB(("RclMonEventQueue:: normal return\n"));
return true;
}
bool RclMonEventQueue::lock()
{
MONDEB(("RclMonEventQueue:: lock\n"));
if (pthread_mutex_lock(&m_data->m_mutex)) {
LOGERR("RclMonEventQueue::lock: pthread_mutex_lock failed\n" );
return false;
}
MONDEB(("RclMonEventQueue:: lock return\n"));
return true;
}
bool RclMonEventQueue::unlock()
{
MONDEB(("RclMonEventQueue:: unlock\n"));
if (pthread_mutex_unlock(&m_data->m_mutex)) {
LOGERR("RclMonEventQueue::lock: pthread_mutex_unlock failed\n" );
return false;
}
return true;
MONDEB("RclMonEventQueue:: non-timeout return\n");
return lock;
}
void RclMonEventQueue::setConfig(RclConfig *cnf)
@@ -312,37 +285,36 @@ bool RclMonEventQueue::ok()
void RclMonEventQueue::setTerminate()
{
MONDEB(("RclMonEventQueue:: setTerminate\n"));
lock();
MONDEB("RclMonEventQueue:: setTerminate\n");
std::unique_lock<std::mutex> lock(m_data->m_mutex);
m_data->m_ok = false;
pthread_cond_broadcast(&m_data->m_cond);
unlock();
m_data->m_cond.notify_all();
}
// Must be called with the queue locked
bool RclMonEventQueue::empty()
{
if (m_data == 0) {
MONDEB(("RclMonEventQueue::empty(): true (m_data==0)\n"));
MONDEB("RclMonEventQueue::empty(): true (m_data==0)\n");
return true;
}
if (!m_data->m_iqueue.empty()) {
MONDEB(("RclMonEventQueue::empty(): false (m_iqueue not empty)\n"));
MONDEB("RclMonEventQueue::empty(): false (m_iqueue not empty)\n");
return true;
}
if (m_data->m_dqueue.empty()) {
MONDEB(("RclMonEventQueue::empty(): true (m_Xqueue both empty)\n"));
MONDEB("RclMonEventQueue::empty(): true (m_Xqueue both empty)\n");
return true;
}
// Only dqueue has events. Have to check the delays (only the
// first, earliest one):
queue_type::iterator qit = *(m_data->m_delays.begin());
if (qit->second.m_minclock > time(0)) {
MONDEB(("RclMonEventQueue::empty(): true (no delay ready %lu)\n",
(mttcast)qit->second.m_minclock));
MONDEB("RclMonEventQueue::empty(): true (no delay ready " <<
qit->second.m_minclock << ")\n");
return true;
}
MONDEB(("RclMonEventQueue::empty(): returning false (delay expired)\n"));
MONDEB("RclMonEventQueue::empty(): returning false (delay expired)\n");
return false;
}
@@ -352,15 +324,15 @@ bool RclMonEventQueue::empty()
RclMonEvent RclMonEventQueue::pop()
{
time_t now = time(0);
MONDEB(("RclMonEventQueue::pop(), now %lu\n", (mttcast)now));
MONDEB("RclMonEventQueue::pop(), now " << now << std::endl);
// Look at the delayed events, get rid of the expired/unactive
// ones, possibly return an expired/needidx one.
while (!m_data->m_delays.empty()) {
delays_type::iterator dit = m_data->m_delays.begin();
queue_type::iterator qit = *dit;
MONDEB(("RclMonEventQueue::pop(): in delays: evt minclock %lu\n",
(mttcast)qit->second.m_minclock));
MONDEB("RclMonEventQueue::pop(): in delays: evt minclock " <<
qit->second.m_minclock << std::endl);
if (qit->second.m_minclock <= now) {
if (qit->second.m_needidx) {
RclMonEvent ev = qit->second;
@@ -399,8 +371,8 @@ RclMonEvent RclMonEventQueue::pop()
// special processing to limit their reindexing rate.
bool RclMonEventQueue::pushEvent(const RclMonEvent &ev)
{
MONDEB(("RclMonEventQueue::pushEvent for %s\n", ev.m_path.c_str()));
lock();
MONDEB("RclMonEventQueue::pushEvent for " << ev.m_path << std::endl);
std::unique_lock<std::mutex> lock(m_data->m_mutex);
DelayPat pat = m_data->searchDelayPats(ev.m_path);
if (pat.seconds != 0) {
@@ -432,8 +404,7 @@ bool RclMonEventQueue::pushEvent(const RclMonEvent &ev)
m_data->m_iqueue[ev.m_path] = ev;
}
pthread_cond_broadcast(&m_data->m_cond);
unlock();
m_data->m_cond.notify_all();
return true;
}
@@ -482,19 +453,12 @@ bool startMonitor(RclConfig *conf, int opts)
if (!conf->getConfParam("monixinterval", &ixinterval))
ixinterval = dfltixinterval;
rclEQ.setConfig(conf);
rclEQ.setopts(opts);
if (pthread_create(&rcv_thrid, 0, &rclMonRcvRun, &rclEQ) != 0) {
LOGERR("startMonitor: cant create event-receiving thread\n" );
return false;
}
if (!rclEQ.lock()) {
LOGERR("startMonitor: cant lock queue ???\n" );
return false;
}
std::thread treceive(rclMonRcvRun, &rclEQ);
treceive.detach();
LOGDEB("start_monitoring: entering main loop\n" );
bool timedout;
@@ -504,61 +468,62 @@ bool startMonitor(RclConfig *conf, int opts)
list<string> modified;
list<string> deleted;
;
// Set a relatively short timeout for better monitoring of exit requests
while (rclEQ.wait(2, &timedout)) {
// Queue is locked.
while (true) {
{
std::unique_lock<std::mutex> lock = rclEQ.wait(2, &timedout);
// x11IsAlive() can't be called from ok() because both threads call it
// and Xlib is not multithreaded.
// x11IsAlive() can't be called from ok() because both
// threads call it and Xlib is not multithreaded.
#ifndef _WIN32
bool x11dead = !(opts & RCLMON_NOX11) && !x11IsAlive();
if (x11dead)
LOGDEB("RclMonprc: x11 is dead\n" );
bool x11dead = !(opts & RCLMON_NOX11) && !x11IsAlive();
if (x11dead)
LOGDEB("RclMonprc: x11 is dead\n" );
#else
bool x11dead = false;
bool x11dead = false;
#endif
if (!rclEQ.ok() || x11dead) {
rclEQ.unlock();
break;
}
if (!rclEQ.ok() || x11dead) {
break;
}
// Process event queue
for (;;) {
// Retrieve event
RclMonEvent ev = rclEQ.pop();
if (ev.m_path.empty())
break;
switch (ev.evtype()) {
case RclMonEvent::RCLEVT_MODIFY:
case RclMonEvent::RCLEVT_DIRCREATE:
LOGDEB0("Monitor: Modify/Check on " << (ev.m_path) << "\n" );
modified.push_back(ev.m_path);
break;
case RclMonEvent::RCLEVT_DELETE:
LOGDEB0("Monitor: Delete on " << (ev.m_path) << "\n" );
// If this is for a directory (which the caller should
// tell us because he knows), we should purge the db
// of all the subtree, because on a directory rename,
// inotify will only generate one event for the
// renamed top, not the subentries. This is relatively
// complicated to do though, and we currently do not
// do it, and just wait for a restart to do a full run and
// purge.
deleted.push_back(ev.m_path);
if (ev.evflags() & RclMonEvent::RCLEVT_ISDIR) {
vector<string> paths;
if (subtreelist(conf, ev.m_path, paths)) {
deleted.insert(deleted.end(),
paths.begin(), paths.end());
}
}
break;
default:
LOGDEB("Monitor: got Other on [" << (ev.m_path) << "]\n" );
}
}
// Unlock queue before processing lists
rclEQ.unlock();
// Process event queue
for (;;) {
// Retrieve event
RclMonEvent ev = rclEQ.pop();
if (ev.m_path.empty())
break;
switch (ev.evtype()) {
case RclMonEvent::RCLEVT_MODIFY:
case RclMonEvent::RCLEVT_DIRCREATE:
LOGDEB0("Monitor: Modify/Check on " << ev.m_path << "\n");
modified.push_back(ev.m_path);
break;
case RclMonEvent::RCLEVT_DELETE:
LOGDEB0("Monitor: Delete on " << (ev.m_path) << "\n" );
// If this is for a directory (which the caller should
// tell us because he knows), we should purge the db
// of all the subtree, because on a directory rename,
// inotify will only generate one event for the
// renamed top, not the subentries. This is relatively
// complicated to do though, and we currently do not
// do it, and just wait for a restart to do a full run and
// purge.
deleted.push_back(ev.m_path);
if (ev.evflags() & RclMonEvent::RCLEVT_ISDIR) {
vector<string> paths;
if (subtreelist(conf, ev.m_path, paths)) {
deleted.insert(deleted.end(),
paths.begin(), paths.end());
}
}
break;
default:
LOGDEB("Monitor: got Other on [" << (ev.m_path) << "]\n" );
}
}
}
// Process. We don't do this every time but let the lists accumulate
// a little, this saves processing. Start at once if list is big.
@@ -608,8 +573,6 @@ bool startMonitor(RclConfig *conf, int opts)
o_reexec->removeArg("-n");
o_reexec->reexec();
}
// Lock queue before waiting again
rclEQ.lock();
}
LOGDEB("Rclmonprc: calling queue setTerminate\n" );
rclEQ.setTerminate();
@@ -619,7 +582,6 @@ bool startMonitor(RclConfig *conf, int opts)
// during our limited time window for exiting. To be reviewed if
// we ever need several monitor invocations in the same process
// (can't foresee any reason why we'd want to do this).
// pthread_join(rcv_thrid, 0);
LOGDEB("Monitor: returning\n" );
return true;
}