[Lldb-commits] [lldb] r194159 - Added Iterable, a class that vends standard C++

Sean Callanan scallanan at apple.com
Wed Nov 6 11:28:40 PST 2013


Author: spyffe
Date: Wed Nov  6 13:28:40 2013
New Revision: 194159

URL: http://llvm.org/viewvc/llvm-project?rev=194159&view=rev
Log:
Added Iterable, a class that vends standard C++
iterators for LLDB's container data structures.
Iterable abstracts over the backing data structure,
ignoring keys for maps for example.  It also provides
locking as a service so that the code

for (ThreadSP thread_sp : process->Threads())
{
  // ... use thread_sp
}

takes the appropriate locks once, without having to
do anything else.

The salient advantages of this system are:

- Much simpler and idiomatic loop code
- Lock once instead of each time an element is fetched
- Less boilerplate to produce the iterators

The intent is that Iterable will replace Get...AtIndex
in most places, and that ForEach(), which solves the
same problem in a less-idiomatic way, be phased out in
favor of this approach.

I've added Iterables to ThreadList, TypeList, and
Process (which is really just forwarding to ThreadList).

Added:
    lldb/trunk/include/lldb/Utility/Iterable.h
Modified:
    lldb/trunk/include/lldb/Symbol/TypeList.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/Target/ThreadList.h
    lldb/trunk/source/Commands/CommandObjectTarget.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp

Modified: lldb/trunk/include/lldb/Symbol/TypeList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/TypeList.h?rev=194159&r1=194158&r2=194159&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/TypeList.h (original)
+++ lldb/trunk/include/lldb/Symbol/TypeList.h Wed Nov  6 13:28:40 2013
@@ -12,6 +12,7 @@
 
 #include "lldb/lldb-private.h"
 #include "lldb/Symbol/Type.h"
+#include "lldb/Utility/Iterable.h"
 #include <map>
 #include <functional>
 
@@ -51,6 +52,15 @@ public:
 
     lldb::TypeSP
     GetTypeAtIndex(uint32_t idx);
+    
+    typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
+    typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
+    
+    TypeIterable
+    Types ()
+    {
+        return TypeIterable(m_types);
+    }
 
     void
     ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const;
@@ -75,7 +85,6 @@ public:
     RemoveMismatchedTypes (lldb::TypeClass type_class);
 
 private:
-    typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
     typedef collection::iterator iterator;
     typedef collection::const_iterator const_iterator;
 

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=194159&r1=194158&r2=194159&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Wed Nov  6 13:28:40 2013
@@ -3305,6 +3305,12 @@ public:
         return m_thread_list;
     }
     
+    ThreadList::ThreadIterable
+    Threads ()
+    {
+        return m_thread_list.Threads();
+    }
+    
     uint32_t
     GetNextThreadIndexID (uint64_t thread_id);
     

Modified: lldb/trunk/include/lldb/Target/ThreadList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadList.h?rev=194159&r1=194158&r2=194159&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadList.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadList.h Wed Nov  6 13:28:40 2013
@@ -14,6 +14,7 @@
 
 #include "lldb/lldb-private.h"
 #include "lldb/Core/UserID.h"
+#include "lldb/Utility/Iterable.h"
 
 
 // FIXME: Currently this is a thread list with lots of functionality for use only by
@@ -69,6 +70,15 @@ public:
     // is a unique index assigned
     lldb::ThreadSP
     GetThreadAtIndex (uint32_t idx, bool can_update = true);
+    
+    typedef std::vector<lldb::ThreadSP> collection;
+    typedef LockingAdaptedIterable<collection, lldb::ThreadSP, vector_adapter> ThreadIterable;
+    
+    ThreadIterable
+    Threads ()
+    {
+        return ThreadIterable(m_threads, GetMutex());
+    }
 
     lldb::ThreadSP
     FindThreadByID (lldb::tid_t tid, bool can_update = true);
@@ -145,7 +155,6 @@ protected:
     void
     NotifySelectedThreadChanged (lldb::tid_t tid);
 
-    typedef std::vector<lldb::ThreadSP> collection;
     //------------------------------------------------------------------
     // Classes that inherit from Process can see and modify these
     //------------------------------------------------------------------

Added: lldb/trunk/include/lldb/Utility/Iterable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/Iterable.h?rev=194159&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Utility/Iterable.h (added)
+++ lldb/trunk/include/lldb/Utility/Iterable.h Wed Nov  6 13:28:40 2013
@@ -0,0 +1,225 @@
+//===-- Iterable.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_Iterable_h_
+#define liblldb_Iterable_h_
+
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private
+{
+    
+template <typename I, typename E> E map_adapter(I &iter)
+{
+    return iter->second;
+}
+    
+template <typename I, typename E> E vector_adapter(I &iter)
+{
+    return *iter;
+}
+    
+template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedConstIterator
+{
+public:
+    typedef typename C::const_iterator BackingIterator;
+private:
+    BackingIterator m_iter;
+public:
+    // Wrapping constructor
+    AdaptedConstIterator (BackingIterator backing_iterator) :
+        m_iter(backing_iterator)
+    {
+    }
+    
+    // Default-constructible
+    AdaptedConstIterator () :
+        m_iter()
+    {
+    }
+    
+    // Copy-constructible
+    AdaptedConstIterator (const AdaptedConstIterator &rhs) :
+        m_iter(rhs.m_iter)
+    {
+    }
+    
+    // Copy-assignable
+    AdaptedConstIterator &operator= (const AdaptedConstIterator &rhs)
+    {
+        m_iter = rhs.m_iter;
+        return *this;
+    }
+    
+    // Destructible
+    ~AdaptedConstIterator () { }
+    
+    // Comparable
+    bool operator== (const AdaptedConstIterator &rhs)
+    {
+        return m_iter == rhs.m_iter;
+    }
+    
+    bool operator!= (const AdaptedConstIterator &rhs)
+    {
+        return m_iter != rhs.m_iter;
+    }
+    
+    // Rvalue dereferenceable
+    E operator* ()
+    {
+        return (*A)(m_iter);
+    }
+    
+    E operator-> ()
+    {
+        return (*A)(m_iter);
+    }
+    
+    // Offset dereferenceable
+    E operator[] (typename BackingIterator::difference_type offset)
+    {
+        return AdaptedConstIterator(m_iter + offset);
+    }
+    
+    // Incrementable
+    AdaptedConstIterator &operator++ ()
+    {
+        m_iter++;
+        return *this;
+    }
+    
+    // Decrementable
+    AdaptedConstIterator &operator-- ()
+    {
+        m_iter--;
+        return *this;
+    }
+    
+    // Compound assignment
+    AdaptedConstIterator &operator+= (typename BackingIterator::difference_type offset)
+    {
+        m_iter += offset;
+        return *this;
+    }
+    
+    AdaptedConstIterator &operator-= (typename BackingIterator::difference_type offset)
+    {
+        m_iter -= offset;
+        return *this;
+    }
+    
+    // Arithmetic
+    AdaptedConstIterator operator+ (typename BackingIterator::difference_type offset)
+    {
+        return AdaptedConstIterator(m_iter + offset);
+    }
+    
+    AdaptedConstIterator operator- (typename BackingIterator::difference_type offset)
+    {
+        return AdaptedConstIterator(m_iter - offset);
+    }
+    
+    // Comparable
+    bool operator< (AdaptedConstIterator &rhs)
+    {
+        return m_iter < rhs.m_iter;
+    }
+    
+    bool operator<= (AdaptedConstIterator &rhs)
+    {
+        return m_iter <= rhs.m_iter;
+    }
+    
+    bool operator> (AdaptedConstIterator &rhs)
+    {
+        return m_iter > rhs.m_iter;
+    }
+    
+    bool operator>= (AdaptedConstIterator &rhs)
+    {
+        return m_iter >= rhs.m_iter;
+    }
+    
+    friend AdaptedConstIterator operator+(typename BackingIterator::difference_type, AdaptedConstIterator &);
+    friend typename BackingIterator::difference_type operator-(AdaptedConstIterator &, AdaptedConstIterator &);
+    friend void swap(AdaptedConstIterator &, AdaptedConstIterator &);
+};
+    
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+AdaptedConstIterator<C, E, A> operator+ (typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type offset, AdaptedConstIterator<C, E, A> &rhs)
+{
+    return rhs.operator+(offset);
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type operator- (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
+{
+    return(lhs.m_iter - rhs.m_iter);
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+void swap (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
+{
+    std::swap(lhs.m_iter, rhs.m_iter);
+}
+    
+template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedIterable
+{
+private:
+    const C &m_container;
+public:
+    AdaptedIterable (const C &container) :
+        m_container(container)
+    {
+    }
+    
+    AdaptedConstIterator<C, E, A> begin ()
+    {
+        return AdaptedConstIterator<C, E, A>(m_container.begin());
+    }
+    
+    AdaptedConstIterator<C, E, A> end ()
+    {
+        return AdaptedConstIterator<C, E, A>(m_container.end());
+    }
+};
+    
+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),
+        m_mutex(&mutex)
+    {
+        m_mutex->Lock();
+    }
+    
+    LockingAdaptedIterable (LockingAdaptedIterable &&rhs) :
+        AdaptedIterable<C,E,A>(rhs),
+        m_mutex(rhs.m_mutex)
+    {
+        rhs.m_mutex = NULL;
+    }
+    
+    ~LockingAdaptedIterable ()
+    {
+        if (m_mutex)
+            m_mutex->Unlock();
+    }
+    
+private:
+    DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable);
+};
+    
+}
+
+#endif

Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=194159&r1=194158&r2=194159&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Wed Nov  6 13:28:40 2013
@@ -1796,10 +1796,8 @@ LookupTypeInModule (CommandInterpreter &
             strm.Printf("%zu match%s found in ", num_matches, num_matches > 1 ? "es" : "");
             DumpFullpath (strm, &module->GetFileSpec(), 0);
             strm.PutCString(":\n");
-            const uint32_t num_types = type_list.GetSize();
-            for (uint32_t i=0; i<num_types; ++i)
+            for (TypeSP type_sp : type_list.Types())
             {
-                TypeSP type_sp (type_list.GetTypeAtIndex(i));
                 if (type_sp)
                 {
                     // Resolve the clang type so that any forward references

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=194159&r1=194158&r2=194159&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Wed Nov  6 13:28:40 2013
@@ -183,24 +183,23 @@ protected:
         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
         {
             Process *process = m_exe_ctx.GetProcessPtr();
-            Mutex::Locker locker (process->GetThreadList().GetMutex());
-            uint32_t num_threads = process->GetThreadList().GetSize();
-            for (uint32_t i = 0; i < num_threads; i++)
+            uint32_t idx = 0;
+            for (ThreadSP thread_sp : process->Threads())
             {
-                ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
+                if (idx != 0)
+                    result.AppendMessage("");
+
                 if (!thread_sp->GetStatus (strm,
                                            m_options.m_start,
                                            m_options.m_count,
                                            num_frames_with_source))
                 {
-                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
+                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
                     result.SetStatus (eReturnStatusFailed);
                     return false;
                 }
                 
-                if (i < num_threads - 1)
-                    result.AppendMessage("");
-                    
+                ++idx;
             }
         }
         else





More information about the lldb-commits mailing list