From 06f26e85df99b56fee97282b9f9ac7d51fb976cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=BCmmel?= Date: Sat, 15 Jan 2011 21:06:28 +0000 Subject: [PATCH] Fix crash on Windows: 1. open LYX 2. CRTL-N 3. CRTL-D hold D --> crash Graph must be thread save to fix this. And for sure, we need a mutex also later. Mutex is a simple wrapper around QMutex, with pseudo-value semantic. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37222 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Graph.cpp | 12 ++++++++ src/Graph.h | 5 +++ src/support/mutex.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++ src/support/mutex.h | 63 +++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 src/support/mutex.cpp create mode 100644 src/support/mutex.h diff --git a/src/Graph.cpp b/src/Graph.cpp index bfb61dc3f3..0320b9bc34 100644 --- a/src/Graph.cpp +++ b/src/Graph.cpp @@ -57,6 +57,8 @@ void Graph::clearPaths() vector const Graph::getReachableTo(int target, bool clear_visited) { + Mutex::Locker lock(&mutex_); + vector result; if (!bfs_init(target, clear_visited)) return result; @@ -92,6 +94,8 @@ vector const Graph::getReachable(int from, bool only_viewable, bool clear_visited) { + Mutex::Locker lock(&mutex_); + vector result; if (!bfs_init(from, clear_visited)) return result; @@ -128,6 +132,8 @@ vector const bool Graph::isReachable(int from, int to) { + Mutex::Locker lock(&mutex_); + if (from == to) return true; @@ -159,6 +165,8 @@ bool Graph::isReachable(int from, int to) Graph::EdgePath const Graph::getPath(int from, int to) { + Mutex::Locker lock(&mutex_); + static const EdgePath path; if (from == to) return path; @@ -199,6 +207,8 @@ Graph::EdgePath const Graph::getPath(int from, int to) void Graph::init(int size) { + Mutex::Locker lock(&mutex_); + vertices_ = vector(size); arrows_.clear(); numedges_ = 0; @@ -207,6 +217,8 @@ void Graph::init(int size) void Graph::addEdge(int from, int to) { + Mutex::Locker lock(&mutex_); + arrows_.push_back(Arrow(from, to, numedges_)); numedges_++; Arrow * ar = &(arrows_.back()); diff --git a/src/Graph.h b/src/Graph.h index fad35ac37d..de1a555117 100644 --- a/src/Graph.h +++ b/src/Graph.h @@ -13,6 +13,8 @@ #ifndef GRAPH_H #define GRAPH_H +#include "support/mutex.h" + #include #include #include @@ -100,6 +102,9 @@ private: /// seems kind of fragile. Perhaps a better solution would be /// to pass the ids as we create the arrows. int numedges_; + + /// make public functions thread save + Mutex mutex_; }; diff --git a/src/support/mutex.cpp b/src/support/mutex.cpp new file mode 100644 index 0000000000..042c9b88cd --- /dev/null +++ b/src/support/mutex.cpp @@ -0,0 +1,72 @@ +/** + * \file mutex.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Peter Kümmel + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "mutex.h" + +#include + + +namespace lyx { + + +struct Mutex::Private +{ + // QMutex::Recursive: less risks for dead-locks + Private() : qmutex_(QMutex::Recursive) + { + } + + QMutex qmutex_; +}; + + +Mutex::Mutex() : d(new Private) +{ +} + + +Mutex::~Mutex() +{ + delete d; +} + + +// It makes no sense to copy the mutex, +// each instance has its own QMutex, +// therefore nothing to copy! +// TODO review +Mutex::Mutex(const Mutex&) : d(new Private) +{ +} + + +Mutex& Mutex::operator=(const Mutex&) +{ + return *this; +} + + + +Mutex::Locker::Locker(Mutex* mtx) : mutex_(mtx) +{ + mutex_->d->qmutex_.lock(); +} + + +Mutex::Locker::~Locker() +{ + mutex_->d->qmutex_.unlock(); +} + + + +} // namespace lyx diff --git a/src/support/mutex.h b/src/support/mutex.h new file mode 100644 index 0000000000..ed3954f03f --- /dev/null +++ b/src/support/mutex.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +/** + * \file mutex.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Peter Kümmel + * + * Full author contact details are available in file CREDITS. + * + * A collection of string helper functions that works with string. + * Some of these would certainly benefit from a rewrite/optimization. + */ + +#ifndef MUTEX_H +#define MUTEX_H + + +namespace lyx { + + +class Mutex +{ +public: + Mutex(); + ~Mutex(); + + /// Scope based locking: + /// Usage: + /// >>> unlocked + /// { + /// Mutex::Locker locker(a_Mutex_ptr); + /// >>> locked + /// } + /// >>> unlocked + class Locker + { + public: + Locker(Mutex*); + ~Locker(); + + private: + Locker(); + Locker(const Locker& rhs); + Locker& operator=(const Locker& rhs); + Mutex* mutex_; + }; + + + // pseude-value semantic + // needed by GuiPrefs which makes a copy + Mutex(const Mutex&); + Mutex& operator=(const Mutex&); + +private: + struct Private; + Private* d; +}; + + +} // namespace lyx + +#endif