Reference documentation for deal.II version 8.5.1
thread_management.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2015 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/thread_management.h>
17 
18 #include <cerrno>
19 #include <cstdlib>
20 #include <iostream>
21 #include <list>
22 
23 #ifdef DEAL_II_HAVE_UNISTD_H
24 # include <unistd.h>
25 #endif
26 
27 
28 DEAL_II_NAMESPACE_OPEN
29 
30 
31 namespace Threads
32 {
33  namespace internal
34  {
35  // counter and access mutex for the
36  // number of threads
37  volatile unsigned int n_existing_threads_counter = 1;
38  Mutex n_existing_threads_mutex;
39 
40 
41  void register_thread ()
42  {
43  Mutex::ScopedLock lock (n_existing_threads_mutex);
44  ++n_existing_threads_counter;
45  }
46 
47 
48 
49  void deregister_thread ()
50  {
51  Mutex::ScopedLock lock (n_existing_threads_mutex);
52  --n_existing_threads_counter;
53  Assert (n_existing_threads_counter >= 1,
55  }
56 
57 
58 
59  void handle_std_exception (const std::exception &exc)
60  {
61  // lock the following context
62  // to ensure that we don't
63  // print things over each other
64  // if we have trouble from
65  // multiple threads. release
66  // the lock before calling
67  // std::abort, though
68  static Mutex mutex;
69  {
70  Mutex::ScopedLock lock(mutex);
71 
72  std::cerr << std::endl << std::endl
73  << "---------------------------------------------------------"
74  << std::endl
75  << "In one of the sub-threads of this program, an exception\n"
76  << "was thrown and not caught. Since exceptions do not\n"
77  << "propagate to the main thread, the library has caught it.\n"
78  << "The information carried by this exception is given below.\n"
79  << std::endl
80  << "---------------------------------------------------------"
81  << std::endl;
82  std::cerr << "Exception message: " << std::endl
83  << " " << exc.what() << std::endl
84  << "Exception type: " << std::endl
85  << " " << typeid(exc).name() << std::endl;
86  std::cerr << "Aborting!" << std::endl
87  << "---------------------------------------------------------"
88  << std::endl;
89  }
90 
91  std::abort ();
92  }
93 
94 
95 
96  void handle_unknown_exception ()
97  {
98  // lock the following context
99  // to ensure that we don't
100  // print things over each other
101  // if we have trouble from
102  // multiple threads. release
103  // the lock before calling
104  // std::abort, though
105  static Mutex mutex;
106  {
107  Mutex::ScopedLock lock(mutex);
108 
109  std::cerr << std::endl << std::endl
110  << "---------------------------------------------------------"
111  << std::endl
112  << "In one of the sub-threads of this program, an exception\n"
113  << "was thrown and not caught. Since exceptions do not\n"
114  << "propagate to the main thread, the library has caught it.\n"
115  << std::endl
116  << "---------------------------------------------------------"
117  << std::endl;
118  std::cerr << "Type of exception is unknown, but not std::exception.\n"
119  << "No additional information is available.\n"
120  << "---------------------------------------------------------"
121  << std::endl;
122  }
123  std::abort ();
124  }
125  }
126 
127 
128 
129  unsigned int n_existing_threads ()
130  {
131  Mutex::ScopedLock lock (internal::n_existing_threads_mutex);
132  return internal::n_existing_threads_counter;
133  }
134 
135 
136  unsigned int this_thread_id ()
137  {
138 #ifdef SYS_gettid
139  const pid_t this_id = syscall(SYS_gettid);
140 #elif defined(DEAL_II_HAVE_UNISTD_H) && defined(DEAL_II_HAVE_GETPID)
141  const pid_t this_id = getpid();
142 #else
143  const unsigned int this_id = 0;
144 #endif
145 
146  return static_cast<unsigned int>(this_id);
147  }
148 
149 
150 
151 #ifndef DEAL_II_WITH_THREADS
152  DummyBarrier::DummyBarrier (const unsigned int count,
153  const char *,
154  void *)
155  {
156  (void)count;
157  Assert (count == 1, ExcBarrierSizeNotUseful(count));
158  }
159 
160 
161 #else
162 # ifdef DEAL_II_USE_MT_POSIX
163 
164 
165 #ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
166  PosixThreadBarrier::PosixThreadBarrier (const unsigned int count,
167  const char *,
168  void *)
169  {
170  pthread_barrier_init (&barrier, 0, count);
171  }
172 
173 #else
174 
175  PosixThreadBarrier::PosixThreadBarrier (const unsigned int count,
176  const char *,
177  void *)
178  : count (count)
179  {
180  // throw an exception unless we
181  // have the special case that a
182  // count of 1 is given, since
183  // then waiting for a barrier is
184  // a no-op, and we don't need the
185  // POSIX functionality
186  AssertThrow (count == 1,
187  ExcMessage ("Your local POSIX installation does not support\n"
188  "POSIX barriers. You will not be able to use\n"
189  "this class, but the rest of the threading\n"
190  "functionality is available."));
191  }
192 #endif
193 
194 
195 
197  {
198 #ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
199  pthread_barrier_destroy (&barrier);
200 #else
201  // unless the barrier is a no-op,
202  // complain again (how did we get
203  // here then?)
204  if (count != 1)
205  std::abort ();
206 #endif
207  }
208 
209 
210 
211  int
213  {
214 #ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
215  return pthread_barrier_wait (&barrier);
216 #else
217  // in the special case, this
218  // function is a no-op. otherwise
219  // complain about the missing
220  // POSIX functions
221  if (count == 1)
222  return 0;
223  else
224  {
225  std::abort ();
226  return 1;
227  };
228 #endif
229  }
230 
231 
232 
233 
234 # endif
235 #endif
236 
237 
238 
239  std::vector<std::pair<unsigned int,unsigned int> >
240  split_interval (const unsigned int begin,
241  const unsigned int end,
242  const unsigned int n_intervals)
243  {
244  Assert (end >= begin, ExcInternalError());
245 
246  const unsigned int n_elements = end-begin;
247  const unsigned int n_elements_per_interval = n_elements / n_intervals;
248  const unsigned int residual = n_elements % n_intervals;
249 
250  std::vector<std::pair<unsigned int,unsigned int> > return_values (n_intervals);
251 
252  return_values[0].first = begin;
253  for (unsigned int i=0; i<n_intervals; ++i)
254  {
255  if (i != n_intervals-1)
256  {
257  return_values[i].second = (return_values[i].first
258  + n_elements_per_interval);
259  // distribute residual in
260  // division equally among
261  // the first few
262  // subintervals
263  if (i < residual)
264  ++return_values[i].second;
265  return_values[i+1].first = return_values[i].second;
266  }
267  else
268  return_values[i].second = end;
269  };
270  return return_values;
271  }
272 } // end namespace Thread
273 
274 
275 DEAL_II_NAMESPACE_CLOSE
unsigned int this_thread_id()
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
PosixThreadBarrier(const unsigned int count, const char *name=0, void *arg=0)
std::vector< std::pair< unsigned int, unsigned int > > split_interval(const unsigned int begin, const unsigned int end, const unsigned int n_intervals)
DummyBarrier(const unsigned int count, const char *name=0, void *arg=0)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:313
unsigned int n_existing_threads()
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcBarrierSizeNotUseful(int arg1)