SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
FullParallelExplanation.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <thread>
4 #include <unistd.h>
5 
6 #include "../utils/Bookkeeping.h"
7 
9 
10 namespace smtrat {
11 namespace mcsat {
12 
13 /**
14  * This explanation executes all given explanation parallel in multiple threads and waits until every single one has finished,
15  * returning the result of the first listed explanation
16  */
17  // TODO currently trying to be FastParallelExplanation, change behavior to description
18 template<typename... Backends>
20 private:
21  using B = std::tuple<Backends...>;
23 
24  template<std::size_t N = 0, carl::EnableIfBool<N == std::tuple_size<B>::value> = carl::dummy>
25  std::optional<Explanation> explain(const mcsat::Bookkeeping&, carl::Variable, const FormulasT&,
26  const std::size_t NUM_THREADS, std::mutex& mtx,
27  std::vector<std::thread>& threads, std::vector<pthread_t>& nativeHandles,
28  size_t& counter, std::vector<std::optional<Explanation>>& explanations) const {
29 
30  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "All explanations started.");
31  mtx.unlock();
32  void *res;
33  int s;
34  std::optional<Explanation> explanation;
35  while(true) {
36  if(counter == NUM_THREADS){ SMTRAT_LOG_ERROR("smtrat.mcsat.explanation", "No explanation left."); }
37  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Look for resulting explanation");
38  for (size_t i = 0; i < NUM_THREADS; i++) {
39  explanation = explanations[i];
40  if (explanation != std::nullopt) {
41  mtx.lock();
42  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Found explanation: " << *explanation);
43  for(size_t j = 0; j < NUM_THREADS; j++){
44  pthread_cancel(nativeHandles[j]);
45 
46  s = pthread_join(nativeHandles[j], &res);
47  if(s != 0){ SMTRAT_LOG_ERROR("smtrat.mcsat.explanation", "Join failed"); }
48  if (res != PTHREAD_CANCELED){
49  SMTRAT_LOG_ERROR("smtrat.mcsat.explanation", "Thread not cancelled");
50  } else {
51  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Thread cancelled successfully");
52  }
53  }
54  nativeHandles.clear();
55  mtx.unlock();
56  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Return reachable");
57  return explanation;
58  }
59  }
60  }
61 
62  }
63 
64  template<std::size_t N = 0, carl::EnableIfBool<N < std::tuple_size<B>::value> = carl::dummy>
65  std::optional<Explanation> explain(const mcsat::Bookkeeping& data, carl::Variable var, const FormulasT& reason,
66  const std::size_t NUM_THREADS, std::mutex& mtx,
67  std::vector<std::thread>& threads, std::vector<pthread_t>& nativeHandles,
68  size_t& counter, std::vector<std::optional<Explanation>>& explanations) const {
69 
70  auto F = [&](){
71  if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)){
72  SMTRAT_LOG_ERROR("smtrat.mcsat.explanation", "Pthread set cancel type error");
73  assert(false);
74  }
75 
76  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Concurrent strategy " << N+1 << " started");
77  explanations[N] = std::get<N>(mBackends)(data, var, reason);
78  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Concurrent strategy " << N+1 << " done");
79 
80  mtx.lock();
81  counter++;
82  mtx.unlock();
83 
84  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Concurrent strategy " << N+1 << " waiting");
85  //TODO make this a wait()
86  while(true){
87  //no-op
88  (void)0;
89  };
90  };
91  SMTRAT_LOG_TRACE("smtrat.mcsat.explanation", "Create Thread");
92  threads.push_back(std::thread(F));
93  SMTRAT_LOG_TRACE("smtrat.mcsat.explanation", "Created Thread");
94  nativeHandles.push_back(threads[N].native_handle());
95  SMTRAT_LOG_TRACE("smtrat.mcsat.explanation", "Store Thread");
96 
97  explain<N+1>(data, var, reason, NUM_THREADS, mtx, threads, nativeHandles, counter, explanations);
98  }
99 
100 public:
101  std::optional<Explanation> operator()(const mcsat::Bookkeeping& data, carl::Variable var, const FormulasT& reason) const {
102  const std::size_t NUM_THREADS = std::tuple_size<B>::value;
103  if(NUM_THREADS <= 0){
104  SMTRAT_LOG_ERROR("smtrat.mcsat.explanation", "No explanation given.");
105  return std::nullopt;
106  }
107 
108  std::mutex mtx;
109  std::vector<std::thread> threads;
110  std::vector<pthread_t> nativeHandles;
111  size_t counter = 0;
112  std::vector<std::optional<Explanation>> explanations(NUM_THREADS, std::nullopt);
113 
114  mtx.lock();
115  // same workarround as in sequential explanation
116  std::optional<Explanation> explanation = explain<0>(data, var, reason, NUM_THREADS, mtx, threads, nativeHandles, counter, explanations);
117  SMTRAT_LOG_DEBUG("smtrat.mcsat.explanation", "Explanation returned");
118  return explanation;
119  }
120 
121 };
122 
123 } // namespace mcsat
124 } // namespace smtrat
Represent the trail, i.e.
Definition: Bookkeeping.h:19
int var(Lit p)
Definition: SolverTypes.h:64
Class to create the formulas for axioms.
carl::Formulas< Poly > FormulasT
Definition: types.h:39
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_ERROR(channel, msg)
Definition: logging.h:32
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
This explanation executes all given explanation parallel in multiple threads and waits until every si...
std::optional< Explanation > explain(const mcsat::Bookkeeping &, carl::Variable, const FormulasT &, const std::size_t NUM_THREADS, std::mutex &mtx, std::vector< std::thread > &threads, std::vector< pthread_t > &nativeHandles, size_t &counter, std::vector< std::optional< Explanation >> &explanations) const