Go to the documentation of this file.00001
00002
00003 #ifndef OSL_SEARCHTIMER_H
00004 #define OSL_SEARCHTIMER_H
00005 #include "osl/misc/milliSeconds.h"
00006 #include "osl/misc/lightMutex.h"
00007 #include "osl/stl/vector.h"
00008 #include "osl/oslConfig.h"
00009 #include <boost/shared_ptr.hpp>
00010 #include <boost/cstdint.hpp>
00011 #include <limits>
00012
00013 namespace osl
00014 {
00015 namespace search
00016 {
00017 struct TimeAssigned
00018 {
00019 MilliSeconds::Interval standard, max;
00020 TimeAssigned()
00021 : standard(MilliSeconds::Interval::infinity()),
00022 max(MilliSeconds::Interval::infinity())
00023 {
00024 }
00025 explicit TimeAssigned(MilliSeconds::Interval assign)
00026 : standard(assign), max(assign)
00027 {
00028 }
00029 TimeAssigned(MilliSeconds::Interval s, MilliSeconds::Interval m)
00030 : standard(s), max(m)
00031 {
00032 }
00033 };
00034 class SearchMonitor;
00035 struct SearchTimerCommon
00036 {
00037 enum StopReason { NotStopped, NoMoreTime, NoMoreMemory, StopByOutside };
00039 MilliSeconds start_time;
00041 TimeAssigned assigned;
00043 volatile double next_iteration_coefficient;
00044 volatile bool stop_all;
00045 volatile StopReason stop_reason;
00046 uint64_t node_count_hard_limit;
00047 volatile int last_memory_use1000;
00048
00049
00050 MilliSeconds last_tested;
00051 uint64_t next_node_count;
00052 double nps;
00053 volatile bool stable;
00054 vector<boost::shared_ptr<SearchMonitor> > monitors;
00055 typedef LightMutex Mutex;
00056 mutable Mutex mutex;
00057
00058 SearchTimerCommon()
00059 : start_time(MilliSeconds::now()),
00060 next_iteration_coefficient(4.0), stop_all(0), stop_reason(NotStopped),
00061 node_count_hard_limit(std::numeric_limits<uint64_t>::max()),
00062 last_memory_use1000(0), stable(true)
00063 {
00064 }
00065 };
00066 class SearchTimer
00067 {
00068 boost::shared_ptr<SearchTimerCommon> shared_timer;
00069 typedef SearchTimerCommon::Mutex Mutex;
00070 public:
00071 SearchTimer() : shared_timer(new SearchTimerCommon) {}
00072 SearchTimer(const SearchTimer& src) : shared_timer(src.shared_timer) {}
00073 virtual ~SearchTimer();
00074 void setTimeAssign(const TimeAssigned& a) {
00075 SCOPED_LOCK(lk,shared_timer->mutex);
00076 shared_timer->assigned = a;
00077 }
00078 void setStartTime(MilliSeconds start) {
00079 SCOPED_LOCK(lk,shared_timer->mutex);
00080 shared_timer->start_time = start;
00081 shared_timer->next_node_count = 0;
00082 shared_timer->nps = 0.0;
00083 shared_timer->last_tested = start;
00084 shared_timer->stop_all = false;
00085 }
00086 void setStable(bool new_stable) { shared_timer->stable = new_stable; }
00087 bool isStableNow() const { return shared_timer->stable; }
00088 bool hasSchedule() const {
00089 SCOPED_LOCK(lk,shared_timer->mutex);
00090 return ! shared_timer->assigned.standard.isInfinity();
00091 }
00092 const TimeAssigned& timeAssigned() const
00093 {
00094 SCOPED_LOCK(lk,shared_timer->mutex);
00095 return shared_timer->assigned;
00096 }
00097 const MilliSeconds startTime() const {
00098 SCOPED_LOCK(lk,shared_timer->mutex);
00099 return shared_timer->start_time;
00100 }
00101 double elapsed(MilliSeconds now) const
00102 {
00103 return (now - shared_timer->start_time).toSeconds();
00104 }
00105 double elapsed() const { return elapsed(MilliSeconds::now()); }
00106
00107 void setNextIterationCoefficient(double new_value) {
00108 SCOPED_LOCK(lk,shared_timer->mutex);
00109 shared_timer->next_iteration_coefficient = new_value;
00110 }
00111 void setNodeCountHardLimit(uint64_t new_value) {
00112 SCOPED_LOCK(lk,shared_timer->mutex);
00113 shared_timer->node_count_hard_limit = new_value;
00114 }
00115 double nextIterationCoefficient() const {
00116 SCOPED_LOCK(lk,shared_timer->mutex);
00117 return shared_timer->next_iteration_coefficient;
00118 }
00119
00120 bool stopping() const { return shared_timer->stop_all; }
00121 void stopNow()
00122 {
00123 shared_timer->stop_reason = SearchTimerCommon::StopByOutside;
00124 shared_timer->stop_all = true;
00125 }
00126 SearchTimerCommon::StopReason stopReason() { return shared_timer->stop_reason; }
00127 void throwIfNoMoreTime(uint64_t node_count)
00128 {
00129 SearchTimerCommon& shared = *shared_timer;
00130 if (! shared.stop_all) {
00131 uint64_t next_node_count;
00132 {
00133 #ifdef OSL_USE_RACE_DETECTOR
00134 SCOPED_LOCK(lk,shared_timer->mutex);
00135 #endif
00136 next_node_count = shared.next_node_count;
00137 }
00138 if (next_node_count > node_count || ! hasSchedule())
00139 return;
00140 }
00141 testAndUpdateNextTimeTest(node_count);
00142 }
00143 int nodeAffordable() const
00144 {
00145 const MilliSeconds now = MilliSeconds::now();
00146 #ifdef OSL_USE_RACE_DETECTOR
00147 SCOPED_LOCK(lk,shared_timer->mutex);
00148 #endif
00149 const double nps = shared_timer->nps;
00150 const double left
00151 = (shared_timer->start_time + shared_timer->assigned.max - now).toSeconds();
00152 return std::max(0, static_cast<int>(nps * left));
00153 }
00155 static void adjustMemoryUseLimit(double scale=0.9);
00156 void addMonitor(const boost::shared_ptr<SearchMonitor>&);
00157 bool hasMonitor() const
00158 {
00159 return ! shared_timer->monitors.empty();
00160 }
00161 const vector<boost::shared_ptr<SearchMonitor> >& monitors() const
00162 {
00163 return shared_timer->monitors;
00164 }
00165 int lastMemoryUseRatio1000() const
00166 {
00167 return shared_timer->last_memory_use1000;
00168 }
00169 private:
00170 void testAndUpdateNextTimeTest(uint64_t node_count);
00171 void throwStop();
00172 };
00173 }
00174 }
00175
00176
00177 #endif
00178
00179
00180
00181