The attached patch adds a global mutex to protect all access to the
proj4 library and ensure that only one thread can be inside a call to
the library at a time.
Jon Burgess has confirmed that this fixes the the rendering problems
he was seeing when trying to do multithreaded rendering.
The problem (as discovered with valgrind's helgrind tool) is that the
library has a global error variable called pj_errno and if one thread
writes to that and then another one reads it then the wrong thread can
think it has seen an error and things go pear shaped.
Tom
--
Tom Hughes ([EMAIL PROTECTED])
http://www.compton.nu/
Index: include/mapnik/projection.hpp
===================================================================
--- include/mapnik/projection.hpp (revision 625)
+++ include/mapnik/projection.hpp (working copy)
@@ -28,6 +28,7 @@
// mapnik
#include <mapnik/envelope.hpp>
// boost
+#include <boost/thread/mutex.hpp>
#include <boost/utility.hpp>
// stl
#include <string>
@@ -66,6 +67,7 @@
private:
std::string params_;
void * proj_;
+ static boost::mutex mutex_;
};
}
Index: src/projection.cpp
===================================================================
--- src/projection.cpp (revision 625)
+++ src/projection.cpp (working copy)
@@ -24,10 +24,13 @@
// mapnik
#include <mapnik/projection.hpp>
+#include <mapnik/utils.hpp>
// proj4
#include <proj_api.h>
namespace mapnik {
+ boost::mutex projection::mutex_;
+
projection::projection(std::string params)
: params_(params)
{
@@ -54,6 +57,7 @@
bool projection::is_geographic() const
{
+ mutex::scoped_lock lock(mutex_);
return pj_is_latlong(proj_);
}
@@ -64,6 +68,7 @@
void projection::forward(double & x, double &y ) const
{
+ mutex::scoped_lock lock(mutex_);
projUV p;
p.u = x * DEG_TO_RAD;
p.v = y * DEG_TO_RAD;
@@ -74,6 +79,7 @@
void projection::inverse(double & x,double & y) const
{
+ mutex::scoped_lock lock(mutex_);
projUV p;
p.u = x;
p.v = y;
@@ -84,11 +90,13 @@
projection::~projection()
{
+ mutex::scoped_lock lock(mutex_);
if (proj_) pj_free(proj_);
}
void projection::init()
{
+ mutex::scoped_lock lock(mutex_);
proj_=pj_init_plus(params_.c_str());
if (!proj_) throw proj_init_error(params_);
}
Index: src/proj_transform.cpp
===================================================================
--- src/proj_transform.cpp (revision 625)
+++ src/proj_transform.cpp (working copy)
@@ -22,8 +22,10 @@
//$Id$
+// mapnik
#include <mapnik/proj_transform.hpp>
-
+#include <mapnik/utils.hpp>
+// proj4
#include <proj_api.h>
namespace mapnik {
@@ -33,12 +35,16 @@
: source_(source),
dest_(dest)
{
+ mutex::scoped_lock lock(projection::mutex_);
+
is_source_latlong_ = pj_is_latlong(source_.proj_);
is_dest_latlong_ = pj_is_latlong(dest_.proj_);
}
bool proj_transform::forward (double & x, double & y , double & z) const
{
+ mutex::scoped_lock lock(projection::mutex_);
+
if (is_source_latlong_)
{
x *= DEG_TO_RAD;
@@ -62,6 +68,8 @@
bool proj_transform::backward (double & x, double & y , double & z) const
{
+ mutex::scoped_lock lock(projection::mutex_);
+
if (is_dest_latlong_)
{
x *= DEG_TO_RAD;
_______________________________________________
Mapnik-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/mapnik-devel