# HG changeset patch
# User Balazs Dezso <deba@inf.elte.hu>
# Date 1327832921 -3600
# Node ID 43a91b33f3747428f70be1da8dbdf9da4edb3d2a
# Parent  eb252f805431c5ec10c258ef603cf1c8460ba977
Thread safe map construction and destruction (#223)

It currently support pthread and windows threads.

diff -r eb252f805431 -r 43a91b33f374 CMakeLists.txt
--- a/CMakeLists.txt	Fri Jan 20 19:08:00 2012 +0100
+++ b/CMakeLists.txt	Sun Jan 29 11:28:41 2012 +0100
@@ -114,6 +114,10 @@
 CHECK_TYPE_SIZE("long long" LONG_LONG)
 SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
 
+INCLUDE(FindThreads)
+SET(LEMON_USE_PTHREAD ${CMAKE_USE_PTHREADS_INIT})
+SET(LEMON_USE_WIN32_THREADS ${CMAKE_USE_WIN32_THREADS_INIT})
+
 ENABLE_TESTING()
 
 IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
diff -r eb252f805431 -r 43a91b33f374 lemon/Makefile.am
--- a/lemon/Makefile.am	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/Makefile.am	Sun Jan 29 11:28:41 2012 +0100
@@ -138,6 +138,7 @@
 	lemon/bits/enable_if.h \
 	lemon/bits/graph_adaptor_extender.h \
 	lemon/bits/graph_extender.h \
+	lemon/bits/lock.h \
 	lemon/bits/map_extender.h \
 	lemon/bits/path_dump.h \
 	lemon/bits/solver_bits.h \
diff -r eb252f805431 -r 43a91b33f374 lemon/bits/alteration_notifier.h
--- a/lemon/bits/alteration_notifier.h	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/bits/alteration_notifier.h	Sun Jan 29 11:28:41 2012 +0100
@@ -23,6 +23,7 @@
 #include <list>
 
 #include <lemon/core.h>
+#include <lemon/bits/lock.h>
 
 //\ingroup graphbits
 //\file
@@ -251,7 +252,7 @@
 
     typedef std::list<ObserverBase*> Observers;
     Observers _observers;
-
+    lemon::bits::Lock _lock;
 
   public:
 
@@ -332,14 +333,18 @@
   protected:
 
     void attach(ObserverBase& observer) {
+      _lock.lock();
       observer._index = _observers.insert(_observers.begin(), &observer);
       observer._notifier = this;
+      _lock.unlock();
     }
 
     void detach(ObserverBase& observer) {
+      _lock.lock();
       _observers.erase(observer._index);
       observer._index = _observers.end();
       observer._notifier = 0;
+      _lock.unlock();
     }
 
   public:
diff -r eb252f805431 -r 43a91b33f374 lemon/bits/lock.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/bits/lock.h	Sun Jan 29 11:28:41 2012 +0100
@@ -0,0 +1,65 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2012
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_LOCK_H
+#define LEMON_BITS_LOCK_H
+
+#include <lemon/config.h>
+#if defined(LEMON_USE_PTHREAD)
+#include <pthread.h>
+#elif defined(LEMON_USE_WIN32_THREADS)
+#include <lemon/bits/windows.h>
+#endif
+
+namespace lemon {
+  namespace bits {
+
+#if defined(LEMON_USE_PTHREAD)
+    class Lock {
+    public:
+      Lock() {
+	pthread_mutex_init(&_lock, 0);
+      }
+      ~Lock() {
+	pthread_mutex_destroy(&_lock);
+      }
+      void lock() {
+	pthread_mutex_lock(&_lock);
+      }
+      void unlock() {
+	pthread_mutex_unlock(&_lock);
+      }
+
+    private:
+      pthread_mutex_t _lock;
+    };
+#elif defined(LEMON_USE_WIN32_THREADS)
+    class Lock : public WinLock {};
+#else
+    class Lock {
+    public:
+      Lock() {}
+      ~Lock() {}
+      void lock() {}
+      void unlock() {}
+    };    
+#endif
+  }
+}
+
+#endif
diff -r eb252f805431 -r 43a91b33f374 lemon/bits/windows.cc
--- a/lemon/bits/windows.cc	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/bits/windows.cc	Sun Jan 29 11:28:41 2012 +0100
@@ -130,5 +130,35 @@
       return getpid() + tv.tv_sec + tv.tv_usec;
 #endif
     }
+
+    WinLock::WinLock() {
+#ifdef WIN32
+      CRITICAL_SECTION *lock = new CRITICAL_SECTION;
+      InitializeCriticalSection(lock);
+      _repr = lock;
+#endif
+    }
+    
+    WinLock::~WinLock() {
+#ifdef WIN32
+      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+      DeleteCriticalSection(lock);
+      delete lock;
+#endif
+    }
+
+    void WinLock::lock() {
+#ifdef WIN32
+      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+      EnterCriticalSection(lock);
+#endif
+    }
+
+    void WinLock::unlock() {
+#ifdef WIN32
+      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+      LeaveCriticalSection(lock);
+#endif
+    }
   }
 }
diff -r eb252f805431 -r 43a91b33f374 lemon/bits/windows.h
--- a/lemon/bits/windows.h	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/bits/windows.h	Sun Jan 29 11:28:41 2012 +0100
@@ -28,6 +28,16 @@
                          double &cutime, double &cstime);
     std::string getWinFormattedDate();
     int getWinRndSeed();
+
+    class WinLock {
+    public:
+      WinLock();
+      ~WinLock();
+      void lock();
+      void unlock();
+    private:
+      void *_repr;
+    };
   }
 }
 
diff -r eb252f805431 -r 43a91b33f374 lemon/config.h.cmake
--- a/lemon/config.h.cmake	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/config.h.cmake	Sun Jan 29 11:28:41 2012 +0100
@@ -6,3 +6,5 @@
 #cmakedefine LEMON_HAVE_CPLEX 1
 #cmakedefine LEMON_HAVE_CLP 1
 #cmakedefine LEMON_HAVE_CBC 1
+#cmakedefine LEMON_USE_PTHREAD 1
+#cmakedefine LEMON_USE_WIN32_THREADS 1
diff -r eb252f805431 -r 43a91b33f374 lemon/config.h.in
--- a/lemon/config.h.in	Fri Jan 20 19:08:00 2012 +0100
+++ b/lemon/config.h.in	Sun Jan 29 11:28:41 2012 +0100
@@ -24,3 +24,9 @@
 
 /* Define to 1 if you have CBC */
 #undef LEMON_HAVE_CBC
+
+/* Define to 1 if you have pthread */
+#undef LEMON_USE_PTHREAD
+
+/* Define to 1 if you have win32 threads */
+#undef LEMON_USE_WIN32_THREADS