Main Page · Modules · All Classes · Class Hierarchy
MARandomness.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MARandomness.hpp"
23 
24 #include <MCLog.hpp>
25 #include <MCThreadLocalData.hpp>
26 #include <MCTimer.hpp>
27 
28 #include <boost/algorithm/string/replace.hpp>
29 #include <boost/tuple/tuple.hpp>
30 
31 #include <vector>
32 
33 namespace
34 {
35 typedef boost::tuple<int64_t, std::string, MC::IntList> RandomPointType;
36 typedef std::vector<RandomPointType> RandomPointList;
37 
38 // Registered random point list
39 MCThreadLocalData<RandomPointList> RandomPoints(true);
40 
41 void CheckStaticRandomnessVariables()
42 {
43  if (unlikely(!RandomPoints.get()))
44  {
45  RandomPoints.reset(new RandomPointList);
46  }
47 }
48 }
49 
50 MC::IntList MARandomness::GenerateRandomPoint(const std::string& id, unsigned int count,
51  int min, int max)
52 {
53  MC::IntList RandomNumbers;
54  unsigned int Count = count == 0 ? 1 : count;
55 
56  for (unsigned int i = 0; i < Count; ++i)
57  {
58  RandomNumbers.push_back(MCRandComplex<int>(min, max));
59  }
60  LogRandomPoint(id, RandomNumbers);
61  return RandomNumbers;
62 }
63 
64 
65 void MARandomness::RegisterRandomPoint(int64_t timestamp, const std::string& id,
66  const int number)
67 {
68  MC::IntList Numbers;
69 
70  CheckStaticRandomnessVariables();
71  Numbers.push_back(number);
72 #if defined(__clang__)
73  // The clang gives old ABI version (std::string) for __PRETTY_FUNCTION__ thus it needs workaround
74  std::string ID(id);
75 
76  boost::replace_all(ID, "std::string", "std::__cxx11::string");
77  RandomPoints->push_back(RandomPointType(timestamp, ID, Numbers));
78 #else
79  RandomPoints->push_back(RandomPointType(timestamp, id, Numbers));
80 #endif
81 }
82 
83 
84 void MARandomness::RegisterRandomPoint(int64_t timestamp, const std::string& id,
85  const MC::IntList& numbers)
86 {
87  CheckStaticRandomnessVariables();
88 #if defined(__clang__)
89  // The clang gives old ABI version (std::string) for __PRETTY_FUNCTION__ thus it needs workaround
90  std::string ID(id);
91 
92  boost::replace_all(ID, "std::string", "std::__cxx11::string");
93  RandomPoints->push_back(RandomPointType(timestamp, ID, numbers));
94 #else
95  RandomPoints->push_back(RandomPointType(timestamp, id, numbers));
96 #endif
97 }
98 
99 
100 MC::IntList MARandomness::QueryRandomPoint(const std::string& id, unsigned int count, int min)
101 {
102  int64_t CurrentTime = MCTimer::GetElapsedSystemTime() / 1000;
103  unsigned int Count = count == 0 ? 1 : count;
104  std::string ID(id);
105  ::RandomPointList& RandomPointList = *RandomPoints.get();
106 
107 #if defined(__clang__)
108  // The clang gives old ABI version (std::string) for __PRETTY_FUNCTION__ thus it needs workaround
109  boost::replace_all(ID, "std::string", "std::__cxx11::string");
110 #endif
111  CheckStaticRandomnessVariables();
112 // printf("Query random point: %s\n", ID.c_str());
113  // Remove obsolete random points
114  while (!RandomPointList.empty() && RandomPointList.begin()->get<0>() < CurrentTime-5*1000)
115  {
116  RandomPointList.erase(RandomPointList.begin());
117  }
118  // Search for the random point
119  for (auto iter = RandomPointList.begin(); iter != RandomPointList.end(); ++iter)
120  {
121  // Unable to find the random point
122  if (iter->get<0>() < CurrentTime-5*1000)
123  {
124 // printf("Query random point: %d < %d\n", (int)iter->get<0>(), (int)CurrentTime);
125  MC_WARNING("Unable to find the random point (%s)", ID.c_str());
126  return MC::IntList(Count, min);
127  }
128  if (iter->get<1>() == ID)
129  {
130  MC::IntList Numbers = iter->get<2>();
131 
132  RandomPointList.erase(iter);
133  LogRandomPoint(ID, Numbers);
134  return Numbers;
135  }
136  }
137  MC_WARNING("Unable to find the random point (%s)", ID.c_str());
138  return MC::IntList(Count, min);
139 }
140 
141 
143 {
144  CheckStaticRandomnessVariables();
145  return !RandomPoints->empty();
146 }
147 
148 
149 void MARandomness::LogRandomPoint(const std::string& id, const MC::IntList& numbers)
150 {
151  std::string LogMessage = "Random point: ["+id+'|';
152 
153  for (unsigned int i = 0; i < numbers.size(); ++i)
154  {
155  LogMessage += MCToStr(numbers[i]);
156  if (i < numbers.size()-1)
157  LogMessage += ',';
158  }
159  LogMessage += ']';
160  MC_LOG("%s", LogMessage.c_str());
161 }
static void LogRandomPoint(const std::string &id, const MC::IntList &numbers)
Log a random point.
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
std::string MCToStr(const T value, bool hex_manipulator=false)
Convert an other type to string with std::stringstream.
Definition: MCDefs.hpp:360
static void RegisterRandomPoint(int64_t timestamp, const std::string &id, const int number)
Register a random point with a single number.
static MC::IntList GenerateRandomPoint(const std::string &id, unsigned int count, int min, int max)
Generate a random point.
static bool IsAnyRegisteredPoint()
Check if there is any registered random point.
static int64_t GetElapsedSystemTime(bool relative_time=true)
Get the system time.
Definition: MCTimer.cpp:92
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
static MC::IntList QueryRandomPoint(const std::string &id, unsigned int count, int min)
Query a random point.