libfoedus-core
FOEDUS Core Library
stoppable_thread_impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
19 
20 #include <glog/logging.h>
21 
22 #include <ostream>
23 #include <sstream>
24 #include <string>
25 #include <thread>
26 
27 namespace foedus {
28 namespace thread {
29 void StoppableThread::initialize(const std::string &name,
30  std::thread &&the_thread, const std::chrono::microseconds &sleep_interval) {
31  name_ = name;
32  thread_ = std::move(the_thread);
33  sleep_interval_ = sleep_interval;
34  started_ = true;
35  stop_requested_ = false;
36  stopped_ = false;
37  LOG(INFO) << name_ << " initialized. sleep_interval=" << sleep_interval_.count() << " microsec";
38 }
39 
40 void StoppableThread::initialize(const std::string& name_prefix, int32_t name_ordinal,
41  std::thread &&the_thread, const std::chrono::microseconds &sleep_interval) {
42  std::stringstream str;
43  str << name_prefix << name_ordinal;
44  initialize(str.str(), std::move(the_thread), sleep_interval);
45 }
46 
48  VLOG(1) << name_ << " sleeping for " << sleep_interval_.count() << " microsec";
49  condition_.wait_for(sleep_interval_);
50  VLOG(1) << name_ << " woke up";
51  if (is_stop_requested()) {
52  LOG(INFO) << name_ << " stop requested";
53  return true;
54  } else {
55  return false;
56  }
57 }
58 
60  VLOG(1) << "Waking up " << name_ << "...";
61  condition_.notify_one();
62 }
63 
65  request_stop();
66  wait_for_stop();
67 }
69  if (started_ && !is_stopped() && !is_stop_requested()) {
70  LOG(INFO) << "Requesting to stop " << name_ << "...";
71  condition_.notify_one([this]{ stop_requested_ = true; });
72  LOG(INFO) << "Requested to stop " << name_;
73  } else {
74  LOG(INFO) << "Already requested to stop: " << name_;
75  }
76 }
77 
79  if (started_ && !is_stopped()) {
80  LOG(INFO) << "Stopping " << name_ << "...";
81  thread_.join();
82  LOG(INFO) << "Successfully Stopped " << name_;
83  stopped_ = true;
84  }
85 }
86 
87 std::string StoppableThread::to_string() const {
88  std::stringstream stream;
89  stream << *this;
90  return stream.str();
91 }
92 
93 std::ostream& operator<<(std::ostream& o, const StoppableThread& v) {
94  o << "<StoppableThread>"
95  << "<name_>" << v.name_ << "</name_>"
96  << "<native_thread_id>" << v.thread_.get_id() << "</native_thread_id>"
97  << "<sleep_interval_>" << v.sleep_interval_.count() << "</sleep_interval_>"
98  << "<started_>" << v.started_.load() << "</started_>"
99  << "<stop_requested_>" << v.stop_requested_.load() << "</stop_requested_>"
100  << "<stopped_>" << v.stopped_.load() << "</stopped_>"
101  << "</StoppableThread>";
102  return o;
103 }
104 
105 } // namespace thread
106 } // namespace foedus
bool is_stopped() const
returns whether this thread has stopped (if the thread hasn't started, false too).
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
void initialize(const std::string &name, std::thread &&the_thread, const std::chrono::microseconds &sleep_interval)
Initializes this object for the given thread.
void request_stop()
If the thread is still running, requests the thread to stop and waits until it exists.
bool wait_for(const std::chrono::duration< REP, PERIOD > &timeout, PREDICATE predicate)
Block until the event happens or the given period elapses.
void stop()
request_stop() plus wait_for_stop().
void wait_for_stop()
Blocks until the thread stops.
bool is_stop_requested() const
returns whether someone has requested to stop this.
void notify_one(SIGNAL_ACTION signal_action)
Notify one waiter that the event has happened.
std::ostream & operator<<(std::ostream &o, const ImpersonateSession &v)
void wakeup()
If the thread is still running and also sleeping, requests the thread to immediately wakeup and do it...
The frequently appearing quartet of std::thread, condition_varible, stop-request flag, and mutex.
bool sleep()
Sleep until the interval elapses or someone requests to stop this thread.