gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Thread safe map construction and destruction (#223) It currently support pthread and windows threads.
0 7 1
default
8 files changed with 124 insertions and 1 deletions:
↑ Collapse diff ↑
Show white space 48 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2012
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_BITS_LOCK_H
20
#define LEMON_BITS_LOCK_H
21

	
22
#include <lemon/config.h>
23
#if defined(LEMON_USE_PTHREAD)
24
#include <pthread.h>
25
#elif defined(LEMON_USE_WIN32_THREADS)
26
#include <lemon/bits/windows.h>
27
#endif
28

	
29
namespace lemon {
30
  namespace bits {
31

	
32
#if defined(LEMON_USE_PTHREAD)
33
    class Lock {
34
    public:
35
      Lock() {
36
	pthread_mutex_init(&_lock, 0);
37
      }
38
      ~Lock() {
39
	pthread_mutex_destroy(&_lock);
40
      }
41
      void lock() {
42
	pthread_mutex_lock(&_lock);
43
      }
44
      void unlock() {
45
	pthread_mutex_unlock(&_lock);
46
      }
47

	
48
    private:
49
      pthread_mutex_t _lock;
50
    };
51
#elif defined(LEMON_USE_WIN32_THREADS)
52
    class Lock : public WinLock {};
53
#else
54
    class Lock {
55
    public:
56
      Lock() {}
57
      ~Lock() {}
58
      void lock() {}
59
      void unlock() {}
60
    };    
61
#endif
62
  }
63
}
64

	
65
#endif
Show white space 48 line context
... ...
@@ -93,48 +93,52 @@
93 93
    CMAKE_EXE_LINKER_FLAGS_MAINTAINER
94 94
    CMAKE_SHARED_LINKER_FLAGS_MAINTAINER )
95 95

	
96 96
IF(CMAKE_CONFIGURATION_TYPES)
97 97
  LIST(APPEND CMAKE_CONFIGURATION_TYPES Maintainer)
98 98
  LIST(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
99 99
  SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
100 100
      "Add the configurations that we need"
101 101
      FORCE)
102 102
 endif()
103 103

	
104 104
IF(NOT CMAKE_BUILD_TYPE)
105 105
  SET(CMAKE_BUILD_TYPE "Release")
106 106
ENDIF()
107 107

	
108 108
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
109 109
    "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel Maintainer."
110 110
    FORCE )
111 111

	
112 112

	
113 113
INCLUDE(CheckTypeSize)
114 114
CHECK_TYPE_SIZE("long long" LONG_LONG)
115 115
SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
116 116

	
117
INCLUDE(FindThreads)
118
SET(LEMON_USE_PTHREAD ${CMAKE_USE_PTHREADS_INIT})
119
SET(LEMON_USE_WIN32_THREADS ${CMAKE_USE_WIN32_THREADS_INIT})
120

	
117 121
ENABLE_TESTING()
118 122

	
119 123
IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
120 124
  ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
121 125
ELSE()
122 126
  ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
123 127
ENDIF()
124 128

	
125 129
ADD_SUBDIRECTORY(lemon)
126 130
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
127 131
  ADD_SUBDIRECTORY(contrib)
128 132
  ADD_SUBDIRECTORY(demo)
129 133
  ADD_SUBDIRECTORY(tools)
130 134
  ADD_SUBDIRECTORY(doc)
131 135
  ADD_SUBDIRECTORY(test)
132 136
ENDIF()
133 137

	
134 138
CONFIGURE_FILE(
135 139
  ${PROJECT_SOURCE_DIR}/cmake/LEMONConfig.cmake.in
136 140
  ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
137 141
  @ONLY
138 142
)
139 143
IF(UNIX)
140 144
  INSTALL(
Show white space 48 line context
... ...
@@ -117,38 +117,39 @@
117 117
	lemon/planarity.h \
118 118
	lemon/preflow.h \
119 119
	lemon/quad_heap.h \
120 120
	lemon/radix_heap.h \
121 121
	lemon/radix_sort.h \
122 122
	lemon/random.h \
123 123
	lemon/smart_graph.h \
124 124
	lemon/soplex.h \
125 125
	lemon/static_graph.h \
126 126
	lemon/suurballe.h \
127 127
	lemon/time_measure.h \
128 128
	lemon/tolerance.h \
129 129
	lemon/unionfind.h \
130 130
	lemon/bits/windows.h
131 131

	
132 132
bits_HEADERS += \
133 133
	lemon/bits/alteration_notifier.h \
134 134
	lemon/bits/array_map.h \
135 135
	lemon/bits/bezier.h \
136 136
	lemon/bits/default_map.h \
137 137
	lemon/bits/edge_set_extender.h \
138 138
	lemon/bits/enable_if.h \
139 139
	lemon/bits/graph_adaptor_extender.h \
140 140
	lemon/bits/graph_extender.h \
141
	lemon/bits/lock.h \
141 142
	lemon/bits/map_extender.h \
142 143
	lemon/bits/path_dump.h \
143 144
	lemon/bits/solver_bits.h \
144 145
	lemon/bits/traits.h \
145 146
	lemon/bits/variant.h \
146 147
	lemon/bits/vector_map.h
147 148

	
148 149
concept_HEADERS += \
149 150
	lemon/concepts/digraph.h \
150 151
	lemon/concepts/graph.h \
151 152
	lemon/concepts/graph_components.h \
152 153
	lemon/concepts/heap.h \
153 154
	lemon/concepts/maps.h \
154 155
	lemon/concepts/path.h
Show white space 48 line context
... ...
@@ -2,48 +2,49 @@
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
20 20
#define LEMON_BITS_ALTERATION_NOTIFIER_H
21 21

	
22 22
#include <vector>
23 23
#include <list>
24 24

	
25 25
#include <lemon/core.h>
26
#include <lemon/bits/lock.h>
26 27

	
27 28
//\ingroup graphbits
28 29
//\file
29 30
//\brief Observer notifier for graph alteration observers.
30 31

	
31 32
namespace lemon {
32 33

	
33 34
  // \ingroup graphbits
34 35
  //
35 36
  // \brief Notifier class to notify observes about alterations in
36 37
  // a container.
37 38
  //
38 39
  // The simple graphs can be refered as two containers: a node container
39 40
  // and an edge container. But they do not store values directly, they
40 41
  // are just key continars for more value containers, which are the
41 42
  // node and edge maps.
42 43
  //
43 44
  // The node and edge sets of the graphs can be changed as we add or erase
44 45
  // nodes and edges in the graph. LEMON would like to handle easily
45 46
  // that the node and edge maps should contain values for all nodes or
46 47
  // edges. If we want to check on every indicing if the map contains
47 48
  // the current indicing key that cause a drawback in the performance
48 49
  // in the library. We use another solution: we notify all maps about
49 50
  // an alteration in the graph, which cause only drawback on the
... ...
@@ -230,49 +231,49 @@
230 231
      // \brief The member function to notificate the observer about the
231 232
      // container is built.
232 233
      //
233 234
      // The build() member function notificates the observer about the
234 235
      // container is built from an empty container. It have to be
235 236
      // overrided in the subclasses.
236 237
      virtual void build() = 0;
237 238

	
238 239
      // \brief The member function to notificate the observer about all
239 240
      // items are erased from the container.
240 241
      //
241 242
      // The clear() member function notificates the observer about all
242 243
      // items are erased from the container. It have to be overrided in
243 244
      // the subclasses.
244 245
      virtual void clear() = 0;
245 246

	
246 247
    };
247 248

	
248 249
  protected:
249 250

	
250 251
    const Container* container;
251 252

	
252 253
    typedef std::list<ObserverBase*> Observers;
253 254
    Observers _observers;
254

	
255
    lemon::bits::Lock _lock;
255 256

	
256 257
  public:
257 258

	
258 259
    // \brief Default constructor.
259 260
    //
260 261
    // The default constructor of the AlterationNotifier.
261 262
    // It creates an empty notifier.
262 263
    AlterationNotifier()
263 264
      : container(0) {}
264 265

	
265 266
    // \brief Constructor.
266 267
    //
267 268
    // Constructor with the observed container parameter.
268 269
    AlterationNotifier(const Container& _container)
269 270
      : container(&_container) {}
270 271

	
271 272
    // \brief Copy Constructor of the AlterationNotifier.
272 273
    //
273 274
    // Copy constructor of the AlterationNotifier.
274 275
    // It creates only an empty notifier because the copiable
275 276
    // notifier's observers have to be registered still into that notifier.
276 277
    AlterationNotifier(const AlterationNotifier& _notifier)
277 278
      : container(_notifier.container) {}
278 279

	
... ...
@@ -311,56 +312,60 @@
311 312
    //
312 313
    // Returns the next item in the container. It is
313 314
    // for iterate on the container.
314 315
    void next(Item& item) const {
315 316
      container->next(item);
316 317
    }
317 318

	
318 319
    // \brief Returns the id of the item.
319 320
    //
320 321
    // Returns the id of the item provided by the container.
321 322
    int id(const Item& item) const {
322 323
      return container->id(item);
323 324
    }
324 325

	
325 326
    // \brief Returns the maximum id of the container.
326 327
    //
327 328
    // Returns the maximum id of the container.
328 329
    int maxId() const {
329 330
      return container->maxId(Item());
330 331
    }
331 332

	
332 333
  protected:
333 334

	
334 335
    void attach(ObserverBase& observer) {
336
      _lock.lock();
335 337
      observer._index = _observers.insert(_observers.begin(), &observer);
336 338
      observer._notifier = this;
339
      _lock.unlock();
337 340
    }
338 341

	
339 342
    void detach(ObserverBase& observer) {
343
      _lock.lock();
340 344
      _observers.erase(observer._index);
341 345
      observer._index = _observers.end();
342 346
      observer._notifier = 0;
347
      _lock.unlock();
343 348
    }
344 349

	
345 350
  public:
346 351

	
347 352
    // \brief Notifies all the registed observers about an item added to
348 353
    // the container.
349 354
    //
350 355
    // It notifies all the registed observers about an item added to
351 356
    // the container.
352 357
    void add(const Item& item) {
353 358
      typename Observers::reverse_iterator it;
354 359
      try {
355 360
        for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
356 361
          (*it)->add(item);
357 362
        }
358 363
      } catch (...) {
359 364
        typename Observers::iterator jt;
360 365
        for (jt = it.base(); jt != _observers.end(); ++jt) {
361 366
          (*jt)->erase(item);
362 367
        }
363 368
        throw;
364 369
      }
365 370
    }
366 371

	
Show white space 48 line context
... ...
@@ -109,26 +109,56 @@
109 109
      else os << "unknown";
110 110
#else
111 111
      timeval tv;
112 112
      gettimeofday(&tv, 0);
113 113

	
114 114
      char cbuf[26];
115 115
      ctime_r(&tv.tv_sec,cbuf);
116 116
      os << cbuf;
117 117
#endif
118 118
      return os.str();
119 119
    }
120 120

	
121 121
    int getWinRndSeed()
122 122
    {
123 123
#ifdef WIN32
124 124
      FILETIME time;
125 125
      GetSystemTimeAsFileTime(&time);
126 126
      return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
127 127
#else
128 128
      timeval tv;
129 129
      gettimeofday(&tv, 0);
130 130
      return getpid() + tv.tv_sec + tv.tv_usec;
131 131
#endif
132 132
    }
133

	
134
    WinLock::WinLock() {
135
#ifdef WIN32
136
      CRITICAL_SECTION *lock = new CRITICAL_SECTION;
137
      InitializeCriticalSection(lock);
138
      _repr = lock;
139
#endif
133 140
  }
141
    
142
    WinLock::~WinLock() {
143
#ifdef WIN32
144
      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
145
      DeleteCriticalSection(lock);
146
      delete lock;
147
#endif
134 148
}
149

	
150
    void WinLock::lock() {
151
#ifdef WIN32
152
      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
153
      EnterCriticalSection(lock);
154
#endif
155
    }
156

	
157
    void WinLock::unlock() {
158
#ifdef WIN32
159
      CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
160
      LeaveCriticalSection(lock);
161
#endif
162
    }
163
  }
164
}
Show white space 48 line context
... ...
@@ -7,28 +7,38 @@
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_BITS_WINDOWS_H
20 20
#define LEMON_BITS_WINDOWS_H
21 21

	
22 22
#include <string>
23 23

	
24 24
namespace lemon {
25 25
  namespace bits {
26 26
    void getWinProcTimes(double &rtime,
27 27
                         double &utime, double &stime,
28 28
                         double &cutime, double &cstime);
29 29
    std::string getWinFormattedDate();
30 30
    int getWinRndSeed();
31

	
32
    class WinLock {
33
    public:
34
      WinLock();
35
      ~WinLock();
36
      void lock();
37
      void unlock();
38
    private:
39
      void *_repr;
40
    };
31 41
  }
32 42
}
33 43

	
34 44
#endif
Show white space 48 line context
1 1
#define LEMON_VERSION "@PROJECT_VERSION@"
2 2
#cmakedefine LEMON_HAVE_LONG_LONG 1
3 3
#cmakedefine LEMON_HAVE_LP 1
4 4
#cmakedefine LEMON_HAVE_MIP 1
5 5
#cmakedefine LEMON_HAVE_GLPK 1
6 6
#cmakedefine LEMON_HAVE_CPLEX 1
7 7
#cmakedefine LEMON_HAVE_CLP 1
8 8
#cmakedefine LEMON_HAVE_CBC 1
9
#cmakedefine LEMON_USE_PTHREAD 1
10
#cmakedefine LEMON_USE_WIN32_THREADS 1
Show white space 48 line context
... ...
@@ -3,24 +3,30 @@
3 3

	
4 4
/* Define to 1 if you have long long */
5 5
#undef LEMON_HAVE_LONG_LONG
6 6

	
7 7
/* Define to 1 if you have any LP solver. */
8 8
#undef LEMON_HAVE_LP
9 9

	
10 10
/* Define to 1 if you have any MIP solver. */
11 11
#undef LEMON_HAVE_MIP
12 12

	
13 13
/* Define to 1 if you have CPLEX. */
14 14
#undef LEMON_HAVE_CPLEX
15 15

	
16 16
/* Define to 1 if you have GLPK. */
17 17
#undef LEMON_HAVE_GLPK
18 18

	
19 19
/* Define to 1 if you have SOPLEX */
20 20
#undef LEMON_HAVE_SOPLEX
21 21

	
22 22
/* Define to 1 if you have CLP */
23 23
#undef LEMON_HAVE_CLP
24 24

	
25 25
/* Define to 1 if you have CBC */
26 26
#undef LEMON_HAVE_CBC
27

	
28
/* Define to 1 if you have pthread */
29
#undef LEMON_USE_PTHREAD
30

	
31
/* Define to 1 if you have win32 threads */
32
#undef LEMON_USE_WIN32_THREADS
0 comments (0 inline)