# HG changeset patch
# User Balazs Dezso <deba@inf.elte.hu>
# Date 1254386644 -7200
# Node ID 4e4e2b7e8ab5538cfe4cfb4a7912ebd7a3001e83
# Parent  8e68671af7898439dc9790c9d546b76ae0e8e6f6
Proof-of-concept for lock based concurrent map access (#223)

diff -r 8e68671af789 -r 4e4e2b7e8ab5 lemon/CMakeLists.txt
--- a/lemon/CMakeLists.txt	Wed Sep 30 08:41:06 2009 +0200
+++ b/lemon/CMakeLists.txt	Thu Oct 01 10:44:04 2009 +0200
@@ -12,6 +12,7 @@
   arg_parser.cc
   base.cc
   color.cc
+  lock.cc
   lp_base.cc
   lp_skeleton.cc
   random.cc
diff -r 8e68671af789 -r 4e4e2b7e8ab5 lemon/Makefile.am
--- a/lemon/Makefile.am	Wed Sep 30 08:41:06 2009 +0200
+++ b/lemon/Makefile.am	Thu Oct 01 10:44:04 2009 +0200
@@ -11,6 +11,7 @@
 	lemon/arg_parser.cc \
 	lemon/base.cc \
 	lemon/color.cc \
+	lemon/lock.cc \
 	lemon/lp_base.cc \
 	lemon/lp_skeleton.cc \
 	lemon/random.cc \
@@ -93,6 +94,7 @@
 	lemon/lgf_reader.h \
 	lemon/lgf_writer.h \
 	lemon/list_graph.h \
+	lemon/lock.h \
 	lemon/lp.h \
 	lemon/lp_base.h \
 	lemon/lp_skeleton.h \
diff -r 8e68671af789 -r 4e4e2b7e8ab5 lemon/bits/alteration_notifier.h
--- a/lemon/bits/alteration_notifier.h	Wed Sep 30 08:41:06 2009 +0200
+++ b/lemon/bits/alteration_notifier.h	Thu Oct 01 10:44:04 2009 +0200
@@ -23,6 +23,7 @@
 #include <list>
 
 #include <lemon/core.h>
+#include <lemon/lock.h>
 
 //\ingroup graphbits
 //\file
@@ -251,6 +252,7 @@
 
     typedef std::list<ObserverBase*> Observers;
     Observers _observers;
+    Lock *_lock;
 
 
   public:
@@ -260,13 +262,17 @@
     // The default constructor of the AlterationNotifier.
     // It creates an empty notifier.
     AlterationNotifier()
-      : container(0) {}
+      : container(0) {
+      _lock = LockFactory::createDefaultLock();
+    }
 
     // \brief Constructor.
     //
     // Constructor with the observed container parameter.
     AlterationNotifier(const Container& _container)
-      : container(&_container) {}
+      : container(&_container) {
+      _lock = LockFactory::createDefaultLock();
+    }
 
     // \brief Copy Constructor of the AlterationNotifier.
     //
@@ -274,7 +280,9 @@
     // It creates only an empty notifier because the copiable
     // notifier's observers have to be registered still into that notifier.
     AlterationNotifier(const AlterationNotifier& _notifier)
-      : container(_notifier.container) {}
+      : container(_notifier.container) {
+      _lock = LockFactory::createDefaultLock();
+    }
 
     // \brief Destructor.
     //
@@ -284,6 +292,7 @@
       for (it = _observers.begin(); it != _observers.end(); ++it) {
         (*it)->_notifier = 0;
       }
+      delete _lock;
     }
 
     // \brief Sets the container.
@@ -332,14 +341,18 @@
   protected:
 
     void attach(ObserverBase& observer) {
+      if (_lock) _lock->lock();
       observer._index = _observers.insert(_observers.begin(), &observer);
       observer._notifier = this;
+      if (_lock) _lock->unlock();
     }
 
     void detach(ObserverBase& observer) {
+      if (_lock) _lock->lock();
       _observers.erase(observer._index);
       observer._index = _observers.end();
       observer._notifier = 0;
+      if (_lock) _lock->unlock();
     }
 
   public:
diff -r 8e68671af789 -r 4e4e2b7e8ab5 lemon/lock.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/lock.cc	Thu Oct 01 10:44:04 2009 +0200
@@ -0,0 +1,5 @@
+#include <lemon/lock.h>
+
+namespace lemon {
+  const LockFactory* LockFactory::_factory = 0;
+}
diff -r 8e68671af789 -r 4e4e2b7e8ab5 lemon/lock.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/lock.h	Thu Oct 01 10:44:04 2009 +0200
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+
+#ifndef LEMON_LOCK_H
+#define LEMON_LOCK_H
+
+#include <pthread.h>
+
+namespace lemon {
+  
+  class Lock {
+  public:
+    virtual void lock() = 0;
+    virtual void unlock() = 0;
+    virtual ~Lock() {}
+  };
+  
+  class LockFactory {    
+  private:
+    static const LockFactory* _factory;
+  public:
+    
+    static void setDefaultFactory(const LockFactory *factory) {
+      if (_factory) delete _factory;
+      _factory = factory;
+    }
+    
+    static const LockFactory* defaultFactory() {
+      return _factory;
+    }
+
+    static Lock* createDefaultLock() {
+      if (_factory == 0) return 0;
+      else return _factory->createLock();
+    }
+    
+    virtual Lock* createLock() const = 0;
+    virtual ~LockFactory() {}
+  };
+
+  class PThreadLock : public Lock {
+  private:
+    pthread_mutex_t _mutex;
+  public:
+    PThreadLock() {
+      pthread_mutex_init(&_mutex, 0);
+    }
+    virtual void lock() {
+      pthread_mutex_lock(&_mutex);      
+    }
+    virtual void unlock() {
+      pthread_mutex_unlock(&_mutex);      
+    }
+  };
+
+  class PThreadLockFactory : public LockFactory {
+  public:
+    virtual PThreadLock* createLock() const {
+      return new PThreadLock();
+    }
+  };
+}
+
+#endif
