File: team_sthread.cpp

package info (click to toggle)
cppad 2025.00.00.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 11,552 kB
  • sloc: cpp: 112,594; sh: 5,972; ansic: 179; python: 71; sed: 12; makefile: 10
file content (150 lines) | stat: -rw-r--r-- 3,861 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-24 Bradley M. Bell
// ----------------------------------------------------------------------------
/*
{xrst_begin team_sthread.cpp}

Standard Thread Implementation of a Team of AD Threads
######################################################
See :ref:`team_thread.hpp-name` for this routines specifications.

{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end team_sthread.cpp}
*/
// BEGIN C++
# include <thread>
# include <mutex>
# include <map>
# include <cppad/cppad.hpp>
# include "../team_thread.hpp"

namespace {
   using CppAD::thread_alloc;
   //
   // begin_work_mutex_;
   std::mutex begin_work_mutex_;
   //
   // thread_id2num_
   std::map< std::thread::id, size_t > thread_id2num_;
   //
   // num_threads_
   // number of threads in this team
   size_t num_threads_;
   //
   // sequential_execution_
   bool sequential_execution_ = true;
   //
   // in_parallel
   // used to inform CppAD when we are in parallel execution mode
   bool in_parallel(void)
   {  return ! sequential_execution_; }
   //
   // thread_number
   // used to inform CppAD of the current thread number
   size_t thread_number(void)
   {  return thread_id2num_.at( std::this_thread::get_id() ); }
}
// team_create
bool team_create(size_t num_threads)
{
   bool ok = ! in_parallel();
   ok     &= num_threads > 0;
   //
   // thread_id2num_
   // must setup for this thread before calling parallel_setup
   thread_id2num_.clear();
   std::thread::id thread_id  = std::this_thread::get_id();
   size_t                       thread_num = 0;
   thread_id2num_[thread_id]  = thread_num;
   //
   // setup for using CppAD::AD<double> in parallel
   thread_alloc::parallel_setup(num_threads, in_parallel, thread_number);
   thread_alloc::hold_memory(true);
   CppAD::parallel_ad<double>();
   //
   // num_thread_
   num_threads_ = num_threads;
   //
   return ok;
}
// work_wrapper
void work_wrapper(void worker(void))
{  // begin_work_mutex_
   // wait here while thread_id2num_ is changing
   begin_work_mutex_.lock();
   begin_work_mutex_.unlock();
   //
   // now go to work
   worker();
}
// team_work
bool team_work( void worker(void) )
{  bool ok = sequential_execution_;
   ok     &= num_threads_ > 0;
   //
   // begin_work_mutex_
   // stop all threads at the beginning of the work routine
   begin_work_mutex_.lock();
   //
   // sequential_execution
   sequential_execution_ = false;
   //
   // thread_ptr
   CppAD::vector<std::thread*> thread_ptr(num_threads_ - 1);
   //
   // thread_num
   for(size_t thread_num = 1; thread_num < num_threads_; ++thread_num)
   {  //
      // thread_ptr
      thread_ptr[thread_num - 1] = new std::thread(work_wrapper, worker);
      //
      // thread_id
      std::thread::id thread_id = thread_ptr[thread_num-1]->get_id();
      //
      // thread_id2num_
      thread_id2num_[thread_id] = thread_num;
   }
   //
   // begin_work_mutex_
   // Let the threads go
   begin_work_mutex_.unlock();
   //
   // put this thread to work
   worker();
   //
   // join
   for(size_t thread_num = 1; thread_num < num_threads_; ++thread_num)
   {  thread_ptr[thread_num-1]->join();
      delete thread_ptr[thread_num-1];
   }
   //
   // sequential execution
   sequential_execution_ = true;
   //
   return ok;
}

bool team_destroy(void)
{  bool ok = ! in_parallel();
   ok     &= thread_number() == 0;;
   ok     &= num_threads_ > 0;

   // inform team_work of number of threads
   num_threads_ = 1;
   //
   // inform CppAD no longer in multi-threading mode
   thread_alloc::parallel_setup(num_threads_, nullptr, nullptr);
   thread_alloc::hold_memory(false);
   CppAD::parallel_ad<double>();
   //
   return ok;
}

const char* team_name(void)
{  return "sthread"; }
// END C++