summaryrefslogtreecommitdiffstats
path: root/include/lldb/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Utility')
-rw-r--r--include/lldb/Utility/AnsiTerminal.h9
-rw-r--r--include/lldb/Utility/Either.h154
-rw-r--r--include/lldb/Utility/Iterable.h25
-rw-r--r--include/lldb/Utility/JSON.h127
-rw-r--r--include/lldb/Utility/ProcessStructReader.h8
-rw-r--r--include/lldb/Utility/PseudoTerminal.h2
-rw-r--r--include/lldb/Utility/PythonPointer.h73
-rw-r--r--include/lldb/Utility/SharedCluster.h6
-rw-r--r--include/lldb/Utility/SharingPtr.h79
-rw-r--r--include/lldb/Utility/StringExtractor.h3
-rw-r--r--include/lldb/Utility/TaskPool.h221
11 files changed, 528 insertions, 179 deletions
diff --git a/include/lldb/Utility/AnsiTerminal.h b/include/lldb/Utility/AnsiTerminal.h
index 9a5117a..a43dd1b 100644
--- a/include/lldb/Utility/AnsiTerminal.h
+++ b/include/lldb/Utility/AnsiTerminal.h
@@ -41,8 +41,13 @@
#define ANSI_CTRL_CONCEAL 8
#define ANSI_CTRL_CROSSED_OUT 9
-#define ANSI_ESC_START "\033["
-#define ANSI_ESC_END "m"
+#define ANSI_ESC_START "\033["
+#define ANSI_ESC_END "m"
+
+#define ANSI_STR(s) #s
+#define ANSI_DEF_STR(s) ANSI_STR(s)
+
+#define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END
#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END
#define ANSI_2_CTRL(ctrl1,ctrl2) "\033["##ctrl1";"##ctrl2 ANSI_ESC_END
diff --git a/include/lldb/Utility/Either.h b/include/lldb/Utility/Either.h
new file mode 100644
index 0000000..ae64736
--- /dev/null
+++ b/include/lldb/Utility/Either.h
@@ -0,0 +1,154 @@
+//===-- Either.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Either_h_
+#define liblldb_Either_h_
+
+#include "llvm/ADT/Optional.h"
+
+#include <functional>
+
+namespace lldb_utility {
+ template <typename T1, typename T2>
+ class Either
+ {
+ private:
+ enum class Selected
+ {
+ One, Two
+ };
+
+ Selected m_selected;
+ union
+ {
+ T1 m_t1;
+ T2 m_t2;
+ };
+
+ public:
+ Either (const T1& t1)
+ {
+ m_t1 = t1;
+ m_selected = Selected::One;
+ }
+
+ Either (const T2& t2)
+ {
+ m_t2 = t2;
+ m_selected = Selected::Two;
+ }
+
+ Either (const Either<T1,T2>& rhs)
+ {
+ switch (rhs.m_selected)
+ {
+ case Selected::One:
+ m_t1 = rhs.GetAs<T1>().getValue();
+ m_selected = Selected::One;
+ break;
+ case Selected::Two:
+ m_t2 = rhs.GetAs<T2>().getValue();
+ m_selected = Selected::Two;
+ break;
+ }
+ }
+
+ template <class X, typename std::enable_if<std::is_same<T1,X>::value>::type * = nullptr>
+ llvm::Optional<T1>
+ GetAs() const
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return m_t1;
+ default:
+ return llvm::Optional<T1>();
+ }
+ }
+
+ template <class X, typename std::enable_if<std::is_same<T2,X>::value>::type * = nullptr>
+ llvm::Optional<T2>
+ GetAs() const
+ {
+ switch (m_selected)
+ {
+ case Selected::Two:
+ return m_t2;
+ default:
+ return llvm::Optional<T2>();
+ }
+ }
+
+ template <class ResultType>
+ ResultType
+ Apply (std::function<ResultType(T1)> if_T1,
+ std::function<ResultType(T2)> if_T2) const
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return if_T1(m_t1);
+ case Selected::Two:
+ return if_T2(m_t2);
+ }
+ }
+
+ bool
+ operator == (const Either<T1,T2>& rhs)
+ {
+ return (GetAs<T1>() == rhs.GetAs<T1>()) && (GetAs<T2>() == rhs.GetAs<T2>());
+ }
+
+ explicit
+ operator bool ()
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return (bool)m_t1;
+ case Selected::Two:
+ return (bool)m_t2;
+ }
+ }
+
+ Either<T1,T2>&
+ operator = (const Either<T1,T2>& rhs)
+ {
+ switch (rhs.m_selected)
+ {
+ case Selected::One:
+ m_t1 = rhs.GetAs<T1>().getValue();
+ m_selected = Selected::One;
+ break;
+ case Selected::Two:
+ m_t2 = rhs.GetAs<T2>().getValue();
+ m_selected = Selected::Two;
+ break;
+ }
+ return *this;
+ }
+
+ ~Either ()
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ m_t1.T1::~T1();
+ break;
+ case Selected::Two:
+ m_t2.T2::~T2();
+ break;
+ }
+ }
+ };
+
+} // namespace lldb_utility
+
+#endif // #ifndef liblldb_Either_h_
+
diff --git a/include/lldb/Utility/Iterable.h b/include/lldb/Utility/Iterable.h
index 17c8cf4..2317225 100644
--- a/include/lldb/Utility/Iterable.h
+++ b/include/lldb/Utility/Iterable.h
@@ -10,6 +10,12 @@
#ifndef liblldb_Iterable_h_
#define liblldb_Iterable_h_
+// C Includes
+// C++ Includes
+#include <utility>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Host/Mutex.h"
namespace lldb_private
@@ -34,9 +40,7 @@ template <typename C, typename E, E (*A)(typename C::const_iterator &)> class Ad
{
public:
typedef typename C::const_iterator BackingIterator;
-private:
- BackingIterator m_iter;
-public:
+
// Wrapping constructor
AdaptedConstIterator (BackingIterator backing_iterator) :
m_iter(backing_iterator)
@@ -63,7 +67,7 @@ public:
}
// Destructible
- ~AdaptedConstIterator () { }
+ ~AdaptedConstIterator() = default;
// Comparable
bool operator== (const AdaptedConstIterator &rhs)
@@ -160,6 +164,9 @@ public:
template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
friend void swap(AdaptedConstIterator<C1, E1, A1> &, AdaptedConstIterator<C1, E1, A1> &);
+
+private:
+ BackingIterator m_iter;
};
template <typename C, typename E, E (*A)(typename C::const_iterator &)>
@@ -203,8 +210,6 @@ public:
template <typename C, typename E, E (*A)(typename C::const_iterator &)> class LockingAdaptedIterable : public AdaptedIterable<C, E, A>
{
-private:
- Mutex *m_mutex = nullptr;
public:
LockingAdaptedIterable (C &container, Mutex &mutex) :
AdaptedIterable<C,E,A>(container),
@@ -217,7 +222,7 @@ public:
AdaptedIterable<C,E,A>(rhs),
m_mutex(rhs.m_mutex)
{
- rhs.m_mutex = NULL;
+ rhs.m_mutex = nullptr;
}
~LockingAdaptedIterable ()
@@ -227,9 +232,11 @@ public:
}
private:
+ Mutex *m_mutex = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable);
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_Iterable_h_
diff --git a/include/lldb/Utility/JSON.h b/include/lldb/Utility/JSON.h
index da5e26d..e61c5ee 100644
--- a/include/lldb/Utility/JSON.h
+++ b/include/lldb/Utility/JSON.h
@@ -71,8 +71,8 @@ namespace lldb_private {
JSONString&
operator = (const JSONString& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONString> SP;
@@ -84,8 +84,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::String;
}
- virtual
- ~JSONString () = default;
+ ~JSONString() override = default;
private:
@@ -98,43 +97,79 @@ namespace lldb_private {
class JSONNumber : public JSONValue
{
public:
- JSONNumber ();
- explicit JSONNumber (uint64_t i);
- explicit JSONNumber (double d);
+ typedef std::shared_ptr<JSONNumber> SP;
+
+ // We cretae a constructor for all integer and floating point type with using templates and
+ // SFINAE to avoid having ambiguous overloads because of the implicit type promotion. If we
+ // would have constructors only with int64_t, uint64_t and double types then constructing a
+ // JSONNumber from an int32_t (or any other similar type) would fail to compile.
+
+ template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_unsigned<T>::value>::type* = nullptr>
+ explicit JSONNumber (T u) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Unsigned)
+ {
+ m_data.m_unsigned = u;
+ }
+
+ template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value>::type* = nullptr>
+ explicit JSONNumber (T s) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Signed)
+ {
+ m_data.m_signed = s;
+ }
+
+ template <typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+ explicit JSONNumber (T d) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Double)
+ {
+ m_data.m_double = d;
+ }
+
+ ~JSONNumber() override = default;
JSONNumber (const JSONNumber& s) = delete;
JSONNumber&
operator = (const JSONNumber& s) = delete;
- virtual void
- Write (Stream& s);
-
- typedef std::shared_ptr<JSONNumber> SP;
+ void
+ Write(Stream& s) override;
uint64_t
- GetData () { return m_data; }
+ GetAsUnsigned() const;
+
+ int64_t
+ GetAsSigned() const;
double
- GetAsDouble()
- {
- if (m_is_integer)
- return (double)m_data;
- else
- return m_double;
- }
+ GetAsDouble() const;
static bool classof(const JSONValue *V)
{
return V->GetKind() == JSONValue::Kind::Number;
}
-
- virtual
- ~JSONNumber () = default;
-
+
private:
- bool m_is_integer;
- uint64_t m_data;
- double m_double;
+ enum class DataType : uint8_t
+ {
+ Unsigned,
+ Signed,
+ Double
+ } m_data_type;
+
+ union
+ {
+ uint64_t m_unsigned;
+ int64_t m_signed;
+ double m_double;
+ } m_data;
};
class JSONTrue : public JSONValue
@@ -146,8 +181,8 @@ namespace lldb_private {
JSONTrue&
operator = (const JSONTrue& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONTrue> SP;
@@ -156,8 +191,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::True;
}
- virtual
- ~JSONTrue () = default;
+ ~JSONTrue() override = default;
};
class JSONFalse : public JSONValue
@@ -169,8 +203,8 @@ namespace lldb_private {
JSONFalse&
operator = (const JSONFalse& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONFalse> SP;
@@ -179,8 +213,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::False;
}
- virtual
- ~JSONFalse () = default;
+ ~JSONFalse() override = default;
};
class JSONNull : public JSONValue
@@ -192,8 +225,8 @@ namespace lldb_private {
JSONNull&
operator = (const JSONNull& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONNull> SP;
@@ -202,8 +235,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::Null;
}
- virtual
- ~JSONNull () = default;
+ ~JSONNull() override = default;
};
class JSONObject : public JSONValue
@@ -215,8 +247,8 @@ namespace lldb_private {
JSONObject&
operator = (const JSONObject& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONObject> SP;
@@ -232,8 +264,7 @@ namespace lldb_private {
JSONValue::SP
GetObject (const std::string& key);
- virtual
- ~JSONObject () = default;
+ ~JSONObject() override = default;
private:
typedef std::map<std::string, JSONValue::SP> Map;
@@ -250,8 +281,8 @@ namespace lldb_private {
JSONArray&
operator = (const JSONArray& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONArray> SP;
@@ -280,13 +311,11 @@ namespace lldb_private {
Size
GetNumElements ();
- virtual
- ~JSONArray () = default;
+ ~JSONArray() override = default;
Vector m_elements;
};
-
class JSONParser : public StringExtractor
{
public:
@@ -327,6 +356,6 @@ namespace lldb_private {
JSONValue::SP
ParseJSONArray ();
};
-}
+} // namespace lldb_private
-#endif // utility_ProcessStructReader_h_
+#endif // utility_JSON_h_
diff --git a/include/lldb/Utility/ProcessStructReader.h b/include/lldb/Utility/ProcessStructReader.h
index d053b70..80f90fe 100644
--- a/include/lldb/Utility/ProcessStructReader.h
+++ b/include/lldb/Utility/ProcessStructReader.h
@@ -16,7 +16,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Process.h"
#include <initializer_list>
@@ -29,7 +29,7 @@ namespace lldb_private {
protected:
struct FieldImpl
{
- ClangASTType type;
+ CompilerType type;
size_t offset;
size_t size;
};
@@ -40,7 +40,7 @@ namespace lldb_private {
size_t m_addr_byte_size;
public:
- ProcessStructReader (Process *process, lldb::addr_t base_addr, ClangASTType struct_type)
+ ProcessStructReader (Process *process, lldb::addr_t base_addr, CompilerType struct_type)
{
if (!process)
return;
@@ -55,7 +55,7 @@ namespace lldb_private {
uint64_t bit_offset;
uint32_t bitfield_bit_size;
bool is_bitfield;
- ClangASTType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield);
+ CompilerType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield);
// no support for bitfields in here (yet)
if (is_bitfield)
return;
diff --git a/include/lldb/Utility/PseudoTerminal.h b/include/lldb/Utility/PseudoTerminal.h
index 595b2fc..d732534 100644
--- a/include/lldb/Utility/PseudoTerminal.h
+++ b/include/lldb/Utility/PseudoTerminal.h
@@ -260,7 +260,7 @@ private:
};
-} // namespace lldb
+} // namespace lldb_utility
#endif // #if defined(__cplusplus)
#endif // #ifndef liblldb_PseudoTerminal_h_
diff --git a/include/lldb/Utility/PythonPointer.h b/include/lldb/Utility/PythonPointer.h
deleted file mode 100644
index fe90670..0000000
--- a/include/lldb/Utility/PythonPointer.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===---------------------PythonPointer.h ------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_PythonPointer_h_
-#define utility_PythonPointer_h_
-
-#include <algorithm>
-
-#include "lldb/lldb-python.h"
-
-namespace lldb_private {
-
-template<class T>
-class PythonPointer
-{
-public:
- typedef PyObject* element_type;
-private:
- element_type* ptr_;
- bool my_ref;
-public:
-
- PythonPointer(element_type p, bool steal_ref = false) :
- ptr_(p),
- my_ref(!steal_ref)
- {
- if (my_ref)
- Py_INCREF(ptr_);
- }
-
- PythonPointer(const PythonPointer& r, bool steal_ref = false) :
- ptr_(r.ptr_),
- my_ref(!steal_ref)
- {
- if (my_ref)
- Py_INCREF(ptr_);
- }
-
- ~PythonPointer()
- {
- if (my_ref)
- Py_XDECREF(ptr_);
- }
-
- PythonPointer
- StealReference()
- {
- return PythonPointer(ptr_,true);
- }
-
- PythonPointer
- DuplicateReference()
- {
- return PythonPointer(ptr_, false);
- }
-
- element_type get() const {return ptr_;}
-
- bool IsNull() { return ptr_ == NULL; }
- bool IsNone() { return ptr_ == Py_None; }
-
- operator PyObject* () { return ptr_; }
-};
-
-} // namespace lldb
-
-#endif // utility_PythonPointer_h_
diff --git a/include/lldb/Utility/SharedCluster.h b/include/lldb/Utility/SharedCluster.h
index 3a34d8d..2c03c40 100644
--- a/include/lldb/Utility/SharedCluster.h
+++ b/include/lldb/Utility/SharedCluster.h
@@ -27,14 +27,15 @@ namespace imp
shared_ptr_refcount() : shared_count (0) {}
- virtual ~shared_ptr_refcount ()
+ ~shared_ptr_refcount() override
{
}
- virtual void on_zero_shared ()
+ void on_zero_shared() override
{
manager->DecrementRefCount();
}
+
private:
T *manager;
};
@@ -100,4 +101,5 @@ private:
};
} // namespace lldb_private
+
#endif // utility_SharedCluster_h_
diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h
index 5c77dad..29538bc 100644
--- a/include/lldb/Utility/SharingPtr.h
+++ b/include/lldb/Utility/SharingPtr.h
@@ -10,6 +10,8 @@
#ifndef utility_SharingPtr_h_
#define utility_SharingPtr_h_
+// C Includes
+// C++ Includes
#include <algorithm>
#include <memory>
@@ -22,6 +24,9 @@
#include <atomic>
#endif
+// Other libraries and framework includes
+// Project includes
+
//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
#if defined (ENABLE_SP_LOGGING)
@@ -38,6 +43,13 @@ class shared_count
shared_count(const shared_count&);
shared_count& operator=(const shared_count&);
+public:
+ explicit shared_count(long refs = 0)
+ : shared_owners_(refs) {}
+
+ void add_shared();
+ void release_shared();
+ long use_count() const {return shared_owners_ + 1;}
protected:
#ifdef _MSC_VER
long shared_owners_;
@@ -45,16 +57,9 @@ protected:
std::atomic<long> shared_owners_;
#endif
virtual ~shared_count();
+
private:
virtual void on_zero_shared() = 0;
-
-public:
- explicit shared_count(long refs = 0)
- : shared_owners_(refs) {}
-
- void add_shared();
- void release_shared();
- long use_count() const {return shared_owners_ + 1;}
};
template <class T>
@@ -67,7 +72,7 @@ public:
: data_(p) {}
private:
- virtual void on_zero_shared();
+ void on_zero_shared() override;
// Outlaw copy constructor and assignment operator to keep effective C++
// warnings down to a minimum
@@ -113,7 +118,8 @@ public:
: data_(a0, a1, a2, a3, a4) {}
private:
- virtual void on_zero_shared();
+ void on_zero_shared() override;
+
public:
T* get() {return &data_;}
};
@@ -124,18 +130,20 @@ shared_ptr_emplace<T>::on_zero_shared()
{
}
-} // namespace
+} // namespace imp
template<class T>
class SharingPtr
{
public:
typedef T element_type;
+
private:
element_type* ptr_;
imp::shared_count* cntrl_;
struct nat {int for_bool_;};
+
public:
SharingPtr();
SharingPtr(std::nullptr_t);
@@ -161,7 +169,7 @@ public:
element_type* operator->() const {return ptr_;}
long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
bool unique() const {return use_count() == 1;}
- bool empty() const {return cntrl_ == 0;}
+ bool empty() const {return cntrl_ == nullptr;}
operator nat*() const {return (nat*)get();}
static SharingPtr<T> make_shared();
@@ -182,30 +190,29 @@ public:
static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
private:
-
template <class U> friend class SharingPtr;
};
template<class T>
inline
SharingPtr<T>::SharingPtr()
- : ptr_(0),
- cntrl_(0)
+ : ptr_(nullptr),
+ cntrl_(nullptr)
{
}
template<class T>
inline
SharingPtr<T>::SharingPtr(std::nullptr_t)
-: ptr_(0),
-cntrl_(0)
+: ptr_(nullptr),
+cntrl_(nullptr)
{
}
template<class T>
template<class Y>
SharingPtr<T>::SharingPtr(Y* p)
- : ptr_(p), cntrl_(0)
+ : ptr_(p), cntrl_(nullptr)
{
std::unique_ptr<Y> hold(p);
typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
@@ -431,7 +438,6 @@ make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
}
-
template<class T, class U>
inline
bool
@@ -490,12 +496,8 @@ public:
// action: false means increment just happened
// true means decrement is about to happen
-private:
- Callback cb_;
- void* baton_;
+ LoggingSharingPtr() : cb_(0), baton_(nullptr) {}
-public:
- LoggingSharingPtr() : cb_(0), baton_(0) {}
LoggingSharingPtr(Callback cb, void* baton)
: cb_(cb), baton_(baton)
{
@@ -505,7 +507,7 @@ public:
template <class Y>
LoggingSharingPtr(Y* p)
- : base(p), cb_(0), baton_(0) {}
+ : base(p), cb_(0), baton_(nullptr) {}
template <class Y>
LoggingSharingPtr(Y* p, Callback cb, void* baton)
@@ -568,9 +570,12 @@ public:
cb_ = 0;
baton_ = 0;
}
+
+private:
+ Callback cb_;
+ void* baton_;
};
-
-
+
template <class T>
class IntrusiveSharingPtr;
@@ -637,14 +642,10 @@ public:
imp::shared_count(-1)
{
}
-
- virtual
- ~ReferenceCountedBaseVirtual ()
- {
- }
-
- virtual void on_zero_shared ();
-
+
+ ~ReferenceCountedBaseVirtual() override = default;
+
+ void on_zero_shared() override;
};
template <class T>
@@ -716,7 +717,7 @@ public:
// those would be builds for release. But for debug and release builds
// that are for development, we NULL out the pointers to catch potential
// issues.
- ptr_ = NULL;
+ ptr_ = nullptr;
#endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
}
@@ -754,7 +755,7 @@ public:
}
void
- reset(T* ptr = NULL)
+ reset(T* ptr = nullptr)
{
IntrusiveSharingPtr(ptr).swap(*this);
}
@@ -793,7 +794,7 @@ private:
if (ptr_)
{
#if defined (ENABLE_SP_LOGGING)
- track_sp (this, NULL, ptr_->use_count() - 1);
+ track_sp (this, nullptr, ptr_->use_count() - 1);
#endif
ptr_->release_shared();
}
@@ -838,4 +839,4 @@ inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
} // namespace lldb_private
-#endif // utility_SharingPtr_h_
+#endif // utility_SharingPtr_h_
diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h
index 0f2dbb1..db1b83b 100644
--- a/include/lldb/Utility/StringExtractor.h
+++ b/include/lldb/Utility/StringExtractor.h
@@ -115,6 +115,9 @@ public:
GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true);
bool
+ GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail = true);
+
+ bool
GetNameColonValue (std::string &name, std::string &value);
int32_t
diff --git a/include/lldb/Utility/TaskPool.h b/include/lldb/Utility/TaskPool.h
new file mode 100644
index 0000000..443e2a5
--- /dev/null
+++ b/include/lldb/Utility/TaskPool.h
@@ -0,0 +1,221 @@
+//===--------------------- TaskPool.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_TaskPool_h_
+#define utility_TaskPool_h_
+
+#if defined(__cplusplus) && defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)
+// Compiling MSVC libraries with _HAS_EXCEPTIONS=0, eliminates most but not all
+// calls to __uncaught_exception. Unfortunately, it does seem to eliminate
+// the delcaration of __uncaught_excpeiton. Including <eh.h> ensures that it is
+// declared. This may not be necessary after MSVC 12.
+#include <eh.h>
+#endif
+
+#if defined(_MSC_VER)
+// Due to another bug in MSVC 2013, including <future> will generate hundreds of
+// warnings in the Concurrency Runtime. This can be removed when we switch to
+// MSVC 2015
+#pragma warning(push)
+#pragma warning(disable:4062)
+#endif
+
+#include <cassert>
+#include <cstdint>
+#include <future>
+#include <list>
+#include <queue>
+#include <thread>
+#include <vector>
+
+// Global TaskPool class for running tasks in parallel on a set of worker thread created the first
+// time the task pool is used. The TaskPool provide no gurantee about the order the task will be run
+// and about what tasks will run in parrallel. None of the task added to the task pool should block
+// on something (mutex, future, condition variable) what will be set only by the completion of an
+// other task on the task pool as they may run on the same thread sequentally.
+class TaskPool
+{
+public:
+ // Add a new task to the task pool and return a std::future belonging to the newly created task.
+ // The caller of this function has to wait on the future for this task to complete.
+ template<typename F, typename... Args>
+ static std::future<typename std::result_of<F(Args...)>::type>
+ AddTask(F&& f, Args&&... args);
+
+ // Run all of the specified tasks on the task pool and wait until all of them are finished
+ // before returning. This method is intended to be used for small number tasks where listing
+ // them as function arguments is acceptable. For running large number of tasks you should use
+ // AddTask for each task and then call wait() on each returned future.
+ template<typename... T>
+ static void
+ RunTasks(T&&... tasks);
+
+private:
+ TaskPool() = delete;
+
+ template<typename... T>
+ struct RunTaskImpl;
+
+ static void
+ AddTaskImpl(std::function<void()>&& task_fn);
+};
+
+// Wrapper class around the global TaskPool implementation to make it possible to create a set of
+// tasks and then wait for the tasks to be completed by the WaitForNextCompletedTask call. This
+// class should be used when WaitForNextCompletedTask is needed because this class add no other
+// extra functionality to the TaskPool class and it have a very minor performance overhead.
+template <typename T> // The return type of the tasks what will be added to this task runner
+class TaskRunner
+{
+public:
+ // Add a task to the task runner what will also add the task to the global TaskPool. The
+ // function doesn't return the std::future for the task because it will be supplied by the
+ // WaitForNextCompletedTask after the task is completed.
+ template<typename F, typename... Args>
+ void
+ AddTask(F&& f, Args&&... args);
+
+ // Wait for the next task in this task runner to finish and then return the std::future what
+ // belongs to the finished task. If there is no task in this task runner (neither pending nor
+ // comleted) then this function will return an invalid future. Usually this function should be
+ // called in a loop processing the results of the tasks until it returns an invalid std::future
+ // what means that all task in this task runner is completed.
+ std::future<T>
+ WaitForNextCompletedTask();
+
+ // Convenience method to wait for all task in this TaskRunner to finish. Do NOT use this class
+ // just because of this method. Use TaskPool instead and wait for each std::future returned by
+ // AddTask in a loop.
+ void
+ WaitForAllTasks();
+
+private:
+ std::list<std::future<T>> m_ready;
+ std::list<std::future<T>> m_pending;
+ std::mutex m_mutex;
+ std::condition_variable m_cv;
+};
+
+template<typename F, typename... Args>
+std::future<typename std::result_of<F(Args...)>::type>
+TaskPool::AddTask(F&& f, Args&&... args)
+{
+ auto task_sp = std::make_shared<std::packaged_task<typename std::result_of<F(Args...)>::type()>>(
+ std::bind(std::forward<F>(f), std::forward<Args>(args)...));
+
+ AddTaskImpl([task_sp]() { (*task_sp)(); });
+
+ return task_sp->get_future();
+}
+
+template<typename... T>
+void
+TaskPool::RunTasks(T&&... tasks)
+{
+ RunTaskImpl<T...>::Run(std::forward<T>(tasks)...);
+}
+
+template<typename Head, typename... Tail>
+struct TaskPool::RunTaskImpl<Head, Tail...>
+{
+ static void
+ Run(Head&& h, Tail&&... t)
+ {
+ auto f = AddTask(std::forward<Head>(h));
+ RunTaskImpl<Tail...>::Run(std::forward<Tail>(t)...);
+ f.wait();
+ }
+};
+
+template<>
+struct TaskPool::RunTaskImpl<>
+{
+ static void
+ Run() {}
+};
+
+template <typename T>
+template<typename F, typename... Args>
+void
+TaskRunner<T>::AddTask(F&& f, Args&&... args)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ auto it = m_pending.emplace(m_pending.end());
+ *it = std::move(TaskPool::AddTask(
+ [this, it](F f, Args... args)
+ {
+ T&& r = f(std::forward<Args>(args)...);
+
+ std::unique_lock<std::mutex> lock(this->m_mutex);
+ this->m_ready.splice(this->m_ready.end(), this->m_pending, it);
+ lock.unlock();
+
+ this->m_cv.notify_one();
+ return r;
+ },
+ std::forward<F>(f),
+ std::forward<Args>(args)...));
+}
+
+template <>
+template<typename F, typename... Args>
+void
+TaskRunner<void>::AddTask(F&& f, Args&&... args)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ auto it = m_pending.emplace(m_pending.end());
+ *it = std::move(TaskPool::AddTask(
+ [this, it](F f, Args... args)
+ {
+ f(std::forward<Args>(args)...);
+
+ std::unique_lock<std::mutex> lock(this->m_mutex);
+ this->m_ready.emplace_back(std::move(*it));
+ this->m_pending.erase(it);
+ lock.unlock();
+
+ this->m_cv.notify_one();
+ },
+ std::forward<F>(f),
+ std::forward<Args>(args)...));
+}
+
+template <typename T>
+std::future<T>
+TaskRunner<T>::WaitForNextCompletedTask()
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ if (m_ready.empty() && m_pending.empty())
+ return std::future<T>(); // No more tasks
+
+ if (m_ready.empty())
+ m_cv.wait(lock, [this](){ return !this->m_ready.empty(); });
+
+ std::future<T> res = std::move(m_ready.front());
+ m_ready.pop_front();
+
+ lock.unlock();
+ res.wait();
+
+ return std::move(res);
+}
+
+template <typename T>
+void
+TaskRunner<T>::WaitForAllTasks()
+{
+ while (WaitForNextCompletedTask().valid());
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // #ifndef utility_TaskPool_h_
OpenPOWER on IntegriCloud