c++/lib c++/tests DEVELOPMENT
Christian Mollekopf
mollekopf at kolabsys.com
Fri Feb 24 01:34:25 CET 2012
DEVELOPMENT | 16 ++++++++++
c++/lib/CMakeLists.txt | 2 -
c++/lib/utils.cpp | 66 +++++++++++++++++++++++++++++--------------
c++/tests/conversiontest.cpp | 33 +++++++++++++++++++++
c++/tests/conversiontest.h | 2 +
5 files changed, 97 insertions(+), 22 deletions(-)
New commits:
commit 177938de4a173c5a087d55de23320d28ec6102b9
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Fri Feb 24 01:31:50 2012 +0100
ThreadLocal storage of globals for thread safety. Doesn't work when called from python...
diff --git a/DEVELOPMENT b/DEVELOPMENT
index 3a60e90..db795c3 100644
--- a/DEVELOPMENT
+++ b/DEVELOPMENT
@@ -1,3 +1,19 @@
+Building:
+
+To build everything including the pykolab stuff:
+# autoreconf -v
+# ./configure
+# make
+
+If you get "error: possibly undefined macro: AC_PROG_INTLTOOL" on autoreconf you might need to install intltool.
+
+For the python tests:
+# make quicktest
+
+Make sure you have "nosetests" for python2 is installed (python2-nose on arch). Otherwise you will get an error that "PyInit__kolabformat" could not be found.
+
+For the library only, switch to the c++ directory and read the instructinos in there
+
Branch layout:
master
diff --git a/c++/lib/CMakeLists.txt b/c++/lib/CMakeLists.txt
index 9cc48f1..dfd4921 100644
--- a/c++/lib/CMakeLists.txt
+++ b/c++/lib/CMakeLists.txt
@@ -10,7 +10,7 @@ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC " ) #always generate shared libra
#Library with serialization/deserialization code and kolab-containers
add_library(kolabxml SHARED kolabformat.cpp kolabcontainers.cpp kolabevent.cpp kolabtodo.cpp kolabjournal.cpp kolabcontact.cpp utils.cpp base64.cpp ../compiled/XMLParserWrapper.cpp ../compiled/grammar-input-stream.cxx ${SCHEMA_SOURCEFILES})
-target_link_libraries(kolabxml ${XERCES_C})
+target_link_libraries(kolabxml ${XERCES_C} boost_thread)
#For the core library we can be stricter when compiling. This doesn't work with the auto generated code though.
set_target_properties(kolabxml PROPERTIES COMPILE_FLAGS "-Wl,--no-undefined -Werror ")
diff --git a/c++/lib/utils.cpp b/c++/lib/utils.cpp
index b3862d3..c9ed61c 100644
--- a/c++/lib/utils.cpp
+++ b/c++/lib/utils.cpp
@@ -20,46 +20,72 @@
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/thread.hpp>
#include <time.h>
#include "base64.h"
namespace Kolab {
namespace Utils {
+
+/**
+ * We have to store our global variables thread-local to ensure thread-safety.
+ */
+struct Global {
+ std::string createdUID;
+ std::string productId;
+ std::string xKolabVersion;
-std::string global_createdUID;
-std::string global_productId;
-std::string global_xKolabVersion;
+ ErrorSeverity errorBit;
+ std::string errorMessage;
+};
+
+boost::thread_specific_ptr<Global> ptr;
+class ThreadLocal
+{
+public:
+ static Global &inst()
+ {
+ Global *t = ptr.get();
+ std::cout << "inst " << boost::this_thread::get_id() << std::endl;
+ if (!t) {
+ std::cout << "initialize Global" << std::endl;
+ t = new Global();
+ ptr.reset(t);
+ }
+ return *t;
+ }
+};
void setKolabVersion(const std::string &s)
{
- global_xKolabVersion = s;
+ ThreadLocal::inst().xKolabVersion = s;
}
std::string kolabVersion()
{
- return global_xKolabVersion;
+ return ThreadLocal::inst().xKolabVersion;
}
void setProductId(const std::string &s)
{
- global_productId = s;
+ ThreadLocal::inst().productId = s;
}
std::string productId()
{
- return global_productId;
+ return ThreadLocal::inst().productId;
}
void setCreatedUid(const std::string &s)
{
- global_createdUID = s;
+ ThreadLocal::inst().createdUID = s;
}
std::string createdUid()
{
- return global_createdUID;
+ return ThreadLocal::inst().createdUID;
}
@@ -81,8 +107,6 @@ DateTime getCurrentTime()
return DateTime(ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, true);
}
-ErrorSeverity global_errorBit;
-std::string global_errorMessage;
void logMessage(const std::string &m, ErrorSeverity s)
{
@@ -95,17 +119,17 @@ void logMessage(const std::string &m, ErrorSeverity s)
break;
case Error:
std::cerr << "Error: " << m << std::endl;
- if (global_errorBit < Error) {
- global_errorBit = Error;
- global_errorMessage = m;
+ if (ThreadLocal::inst().errorBit < Error) {
+ ThreadLocal::inst().errorBit = Error;
+ ThreadLocal::inst().errorMessage = m;
}
break;
case Critical:
default:
std::cerr << "Critical: " << m << std::endl;
- if (global_errorBit < Critical) {
- global_errorBit = Critical;
- global_errorMessage = m;
+ if (ThreadLocal::inst().errorBit < Critical) {
+ ThreadLocal::inst().errorBit = Critical;
+ ThreadLocal::inst().errorMessage = m;
}
}
}
@@ -117,18 +141,18 @@ void logMessage(const std::string &message, const std::string &file, int line, E
void clearErrors()
{
- global_errorBit = NoError;
- global_errorMessage.clear();
+ ThreadLocal::inst().errorBit = NoError;
+ ThreadLocal::inst().errorMessage.clear();
}
ErrorSeverity getError()
{
- return global_errorBit;
+ return ThreadLocal::inst().errorBit;
}
std::string getErrorMessage()
{
- return global_errorMessage;
+ return ThreadLocal::inst().errorMessage;
}
diff --git a/c++/tests/conversiontest.cpp b/c++/tests/conversiontest.cpp
index 369e380..95c4bf1 100644
--- a/c++/tests/conversiontest.cpp
+++ b/c++/tests/conversiontest.cpp
@@ -6,6 +6,7 @@
#include <lib/utils.h>
#include "serializers.h"
+#include <boost/thread.hpp>
Q_DECLARE_METATYPE(Kolab::Duration);
Q_DECLARE_METATYPE(Kolab::DayPos);
@@ -141,6 +142,38 @@ void ConversionTest::uriInlineEncodingTest()
QCOMPARE(d, std::string("data"));
}
+void wait(int seconds)
+{
+ boost::this_thread::sleep(boost::posix_time::seconds(seconds));
+}
+
+void threadF()
+{
+ for (int i = 0; i < 5; ++i)
+ {
+ std::stringstream s;
+ s << boost::this_thread::get_id();
+ std::string uid = s.str();//std::string(boost::this_thread::get_id());
+ std::cout << uid << std::endl;
+ Kolab::Utils::setCreatedUid(uid);
+ wait(1);
+ if (Kolab::Utils::createdUid() != uid) {
+ std::cout << "Error " << uid << std::endl;
+ } else {
+ std::cout << "ok" << std::endl;
+ }
+ }
+}
+
+void ConversionTest::threadLocalTest()
+{
+ boost::thread t(threadF);
+ boost::thread t2(threadF);
+ t.join();
+ t2.join();
+}
+
+
QTEST_MAIN( ConversionTest )
diff --git a/c++/tests/conversiontest.h b/c++/tests/conversiontest.h
index 3b4739e..41eda33 100644
--- a/c++/tests/conversiontest.h
+++ b/c++/tests/conversiontest.h
@@ -28,6 +28,8 @@ class ConversionTest : public QObject
void xCardSerializerTest();
void uriInlineEncodingTest();
+
+ void threadLocalTest();
};
#endif // CONVERSIONTEST_H
More information about the commits
mailing list