implement context-based trace connection
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 02 Mar 2008 21:00:37 +0100
changeset 2531b451b5fc8b57
parent 2530 05f9cec44621
child 2532 86a40c7cbfe9
implement context-based trace connection
src/core/callback.h
src/core/config.cc
src/core/config.h
src/core/object.cc
src/core/object.h
src/core/trace-source-accessor.h
src/core/traced-callback.h
src/core/traced-value.h
     1.1 --- a/src/core/callback.h	Sun Mar 02 06:43:12 2008 +0100
     1.2 +++ b/src/core/callback.h	Sun Mar 02 21:00:37 2008 +0100
     1.3 @@ -237,6 +237,52 @@
     1.4    MEM_PTR m_memPtr;
     1.5  };
     1.6  
     1.7 +// an impl for Bound Functors:
     1.8 +template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
     1.9 +class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,empty> {
    1.10 +public:
    1.11 +  template <typename FUNCTOR, typename ARG>
    1.12 +  BoundFunctorCallbackImpl (FUNCTOR functor, ARG a)
    1.13 +      : m_functor (functor), m_a (a) {}
    1.14 +  virtual ~BoundFunctorCallbackImpl () {}
    1.15 +  R operator() (void) {
    1.16 +      return m_functor (m_a);
    1.17 +  }
    1.18 +  R operator() (T1 a1) {
    1.19 +      return m_functor (m_a,a1);
    1.20 +  }
    1.21 +  R operator() (T1 a1,T2 a2) {
    1.22 +      return m_functor (m_a,a1,a2);
    1.23 +  }
    1.24 +  R operator() (T1 a1,T2 a2,T3 a3) {
    1.25 +      return m_functor (m_a,a1,a2,a3);
    1.26 +  }
    1.27 +  R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
    1.28 +      return m_functor (m_a,a1,a2,a3,a4);
    1.29 +  }
    1.30 +  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
    1.31 +      return m_functor (m_a,a1,a2,a3,a4,a5);
    1.32 +  }
    1.33 +  virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
    1.34 +    BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *otherDerived = 
    1.35 +      dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (PeekPointer (other));
    1.36 +    if (otherDerived == 0)
    1.37 +      {
    1.38 +        return false;
    1.39 +      }
    1.40 +    else if (otherDerived->m_functor != m_functor ||
    1.41 +             otherDerived->m_a != m_a)
    1.42 +      {
    1.43 +        return false;
    1.44 +      }
    1.45 +    return true;
    1.46 +  }
    1.47 +private:
    1.48 +  T m_functor;
    1.49 +  typename TypeTraits<TX>::ReferencedType m_a;
    1.50 +};
    1.51 +
    1.52 +
    1.53  class CallbackBase {
    1.54  public:
    1.55    CallbackBase () : m_impl () {}
    1.56 @@ -299,6 +345,16 @@
    1.57      : CallbackBase (impl)
    1.58    {}
    1.59  
    1.60 +  template <typename T>
    1.61 +  Callback<R,T2,T3,T4,T5,T6> Bind (T a) {
    1.62 +    Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,empty> > impl =
    1.63 +      Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,empty> > (
    1.64 +                                            new BoundFunctorCallbackImpl<
    1.65 +                                            Callback<R,T1,T2,T3,T4,T5,T6>,
    1.66 +                                            R,T1,T2,T3,T4,T5,T6> (*this, a), false);
    1.67 +    return Callback<R,T2,T3,T4,T5,T6> (impl);
    1.68 +  }
    1.69 +
    1.70    bool IsNull (void) const {
    1.71      return (DoPeekImpl () == 0)?true:false;
    1.72    }
    1.73 @@ -363,6 +419,15 @@
    1.74    }
    1.75  };
    1.76  
    1.77 +
    1.78 +template <typename R, typename T1, typename T2,
    1.79 +          typename T3, typename T4,
    1.80 +          typename T5, typename T6>
    1.81 +bool operator != (Callback<R,T1,T2,T3,T4,T5,T6> a, Callback<R,T1,T2,T3,T4,T5,T6> b)
    1.82 +{
    1.83 +  return !a.IsEqual (b);
    1.84 +}
    1.85 +
    1.86  /**
    1.87   * \ingroup core
    1.88   * \defgroup MakeCallback MakeCallback
    1.89 @@ -645,50 +710,6 @@
    1.90   * not yet determined whether or not it is really useful and whether
    1.91   * or not we really want to use it.
    1.92   */
    1.93 -// an impl for Bound Functors:
    1.94 -template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
    1.95 -class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,empty> {
    1.96 -public:
    1.97 -  template <typename FUNCTOR, typename ARG>
    1.98 -  BoundFunctorCallbackImpl (FUNCTOR functor, ARG a)
    1.99 -      : m_functor (functor), m_a (a) {}
   1.100 -  virtual ~BoundFunctorCallbackImpl () {}
   1.101 -  R operator() (void) {
   1.102 -      return m_functor (m_a);
   1.103 -  }
   1.104 -  R operator() (T1 a1) {
   1.105 -      return m_functor (m_a,a1);
   1.106 -  }
   1.107 -  R operator() (T1 a1,T2 a2) {
   1.108 -      return m_functor (m_a,a1,a2);
   1.109 -  }
   1.110 -  R operator() (T1 a1,T2 a2,T3 a3) {
   1.111 -      return m_functor (m_a,a1,a2,a3);
   1.112 -  }
   1.113 -  R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
   1.114 -      return m_functor (m_a,a1,a2,a3,a4);
   1.115 -  }
   1.116 -  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
   1.117 -      return m_functor (m_a,a1,a2,a3,a4,a5);
   1.118 -  }
   1.119 -  virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
   1.120 -    BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *otherDerived = 
   1.121 -      dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (PeekPointer (other));
   1.122 -    if (otherDerived == 0)
   1.123 -      {
   1.124 -        return false;
   1.125 -      }
   1.126 -    else if (otherDerived->m_functor != m_functor ||
   1.127 -             otherDerived->m_a != m_a)
   1.128 -      {
   1.129 -        return false;
   1.130 -      }
   1.131 -    return true;
   1.132 -  }
   1.133 -private:
   1.134 -  T m_functor;
   1.135 -  typename TypeTraits<TX>::ReferencedType m_a;
   1.136 -};
   1.137  
   1.138  template <typename R, typename TX, typename ARG>
   1.139  Callback<R> MakeBoundCallback (R (*fnPtr) (TX), ARG a) {
     2.1 --- a/src/core/config.cc	Sun Mar 02 06:43:12 2008 +0100
     2.2 +++ b/src/core/config.cc	Sun Mar 02 21:00:37 2008 +0100
     2.3 @@ -109,7 +109,7 @@
     2.4    void DoArrayResolve (std::string path, const ObjectVector &vector);
     2.5    void DoResolveOne (Ptr<Object> object, std::string name);
     2.6    std::string GetResolvedPath (std::string name) const;
     2.7 -  virtual void DoOne (Ptr<Object> object, std::string name) = 0;
     2.8 +  virtual void DoOne (Ptr<Object> object, std::string path, std::string name) = 0;
     2.9    std::vector<std::string> m_workStack;
    2.10    std::string m_path;
    2.11  };
    2.12 @@ -142,7 +142,7 @@
    2.13  Resolver::DoResolveOne (Ptr<Object> object, std::string name)
    2.14  {
    2.15    NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
    2.16 -  DoOne (object, name);
    2.17 +  DoOne (object, GetResolvedPath (name), name);
    2.18  }
    2.19  
    2.20  void
    2.21 @@ -160,7 +160,7 @@
    2.22      {
    2.23        std::string attributeName = path.substr (1, path.size ()-1);
    2.24        NS_LOG_DEBUG ("handle attr="<<attributeName);
    2.25 -      DoOne (root, attributeName);
    2.26 +      DoOne (root, GetResolvedPath (attributeName), attributeName);
    2.27        return;
    2.28      }
    2.29    std::string item = path.substr (1, next-1);
    2.30 @@ -267,6 +267,7 @@
    2.31  public:
    2.32    void Set (std::string path, Attribute value);
    2.33    void Connect (std::string path, const CallbackBase &cb);
    2.34 +  void ConnectWithContext (std::string path, const CallbackBase &cb);
    2.35    void Disconnect (std::string path, const CallbackBase &cb);
    2.36  
    2.37    void RegisterRootNamespaceObject (Ptr<Object> obj);
    2.38 @@ -287,7 +288,7 @@
    2.39        : Resolver (path),
    2.40  	m_value (value) {}
    2.41    private:
    2.42 -    virtual void DoOne (Ptr<Object> object, std::string name) {
    2.43 +    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
    2.44        object->SetAttribute (name, m_value);
    2.45      }
    2.46      Attribute m_value;
    2.47 @@ -307,7 +308,7 @@
    2.48        : Resolver (path),
    2.49  	m_cb (cb) {}
    2.50    private:
    2.51 -    virtual void DoOne (Ptr<Object> object, std::string name) {
    2.52 +    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
    2.53        object->TraceSourceConnect (name, m_cb);
    2.54      }
    2.55      CallbackBase m_cb;
    2.56 @@ -327,7 +328,7 @@
    2.57        : Resolver (path),
    2.58  	m_cb (cb) {}
    2.59    private:
    2.60 -    virtual void DoOne (Ptr<Object> object, std::string name) {
    2.61 +    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
    2.62        object->TraceSourceDisconnect (name, m_cb);
    2.63      }
    2.64      CallbackBase m_cb;
    2.65 @@ -338,6 +339,26 @@
    2.66      }
    2.67  }
    2.68  void 
    2.69 +ConfigImpl::ConnectWithContext (std::string path, const CallbackBase &cb)
    2.70 +{
    2.71 +  class ConnectWithContextResolver : public Resolver 
    2.72 +  {
    2.73 +  public:
    2.74 +    ConnectWithContextResolver (std::string path, const CallbackBase &cb)
    2.75 +      : Resolver (path),
    2.76 +	m_cb (cb) {}
    2.77 +  private:
    2.78 +    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
    2.79 +      object->TraceSourceConnectWithContext (name, path, m_cb);
    2.80 +    }
    2.81 +    CallbackBase m_cb;
    2.82 +  } resolver = ConnectWithContextResolver (path, cb);
    2.83 +  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
    2.84 +    {
    2.85 +      resolver.Resolve (*i);
    2.86 +    }
    2.87 +}
    2.88 +void 
    2.89  ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
    2.90  {
    2.91    m_roots.push_back (obj);
    2.92 @@ -379,6 +400,11 @@
    2.93  {
    2.94    Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
    2.95  }
    2.96 +void 
    2.97 +ConnectWithContext (std::string path, const CallbackBase &cb)
    2.98 +{
    2.99 +  Singleton<ConfigImpl>::Get ()->ConnectWithContext (path, cb);
   2.100 +}
   2.101  
   2.102  void RegisterRootNamespaceObject (Ptr<Object> obj)
   2.103  {
   2.104 @@ -505,7 +531,9 @@
   2.105    virtual bool RunTests (void);
   2.106  private:
   2.107    void ChangeNotification (int16_t old, int16_t newValue);
   2.108 +  void ChangeNotificationWithPath (std::string path, int16_t old, int16_t newValue);
   2.109    int16_t m_traceNotification;
   2.110 +  std::string m_tracePath;
   2.111  };
   2.112  
   2.113  static ConfigTest g_configTestUnique;
   2.114 @@ -520,6 +548,13 @@
   2.115    m_traceNotification = newValue;
   2.116  }
   2.117  
   2.118 +void 
   2.119 +ConfigTest::ChangeNotificationWithPath (std::string path, int16_t old, int16_t newValue)
   2.120 +{
   2.121 +  m_traceNotification = newValue;
   2.122 +  m_tracePath = path;
   2.123 +}
   2.124 +
   2.125  bool
   2.126  ConfigTest::RunTests (void)
   2.127  {
   2.128 @@ -639,6 +674,34 @@
   2.129    d1->SetAttribute ("Source", Integer (-4));
   2.130    NS_TEST_ASSERT_EQUAL (m_traceNotification, 0);
   2.131  
   2.132 +  
   2.133 +  Config::ConnectWithContext ("/NodeA/NodeB/NodesB/[0-1]|3/Source", 
   2.134 +			      MakeCallback (&ConfigTest::ChangeNotificationWithPath, this));
   2.135 +  m_traceNotification = 0;
   2.136 +  // this should trigger no notification
   2.137 +  d2->SetAttribute ("Source", Integer (-2));
   2.138 +  NS_TEST_ASSERT_EQUAL (m_traceNotification, 0);
   2.139 +  m_traceNotification = 0;
   2.140 +  m_tracePath = "";
   2.141 +  // this should trigger a notification
   2.142 +  d1->SetAttribute ("Source", Integer (-3));
   2.143 +  NS_TEST_ASSERT_EQUAL (m_traceNotification, -3);
   2.144 +  NS_TEST_ASSERT_EQUAL (m_tracePath, "/NodeA/NodeB/NodesB/1/Source")
   2.145 +  m_traceNotification = 0;
   2.146 +  m_tracePath = "";
   2.147 +  // this should trigger a notification
   2.148 +  d3->SetAttribute ("Source", Integer (-3));
   2.149 +  NS_TEST_ASSERT_EQUAL (m_traceNotification, -3);
   2.150 +  NS_TEST_ASSERT_EQUAL (m_tracePath, "/NodeA/NodeB/NodesB/3/Source");
   2.151 +  // Yes, disconnection _cannot_ work with 'context-based connection.
   2.152 +  // XXX: what do we do about this ?
   2.153 +  Config::Disconnect ("/NodeA/NodeB/NodesB/[0-1]|3/Source", 
   2.154 +		      MakeCallback (&ConfigTest::ChangeNotificationWithPath, this));
   2.155 +  m_traceNotification = 0;
   2.156 +  // this should _not_ trigger a notification
   2.157 +  d1->SetAttribute ("Source", Integer (-4));
   2.158 +  NS_TEST_ASSERT_EQUAL (m_traceNotification, 0);
   2.159 +
   2.160  
   2.161  
   2.162    return result;
     3.1 --- a/src/core/config.h	Sun Mar 02 06:43:12 2008 +0100
     3.2 +++ b/src/core/config.h	Sun Mar 02 21:00:37 2008 +0100
     3.3 @@ -15,6 +15,7 @@
     3.4  void SetGlobal (std::string name, Attribute value);
     3.5  void Connect (std::string path, const CallbackBase &cb);
     3.6  void Disconnect (std::string path, const CallbackBase &cb);
     3.7 +void ConnectWithContext (std::string path, const CallbackBase &cb);
     3.8  
     3.9  void RegisterRootNamespaceObject (Ptr<Object> obj);
    3.10  
     4.1 --- a/src/core/object.cc	Sun Mar 02 06:43:12 2008 +0100
     4.2 +++ b/src/core/object.cc	Sun Mar 02 21:00:37 2008 +0100
     4.3 @@ -1173,6 +1173,17 @@
     4.4    return ok;
     4.5  }
     4.6  bool 
     4.7 +Object::TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb)
     4.8 +{
     4.9 +  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
    4.10 +  if (accessor == 0)
    4.11 +    {
    4.12 +      return false;
    4.13 +    }
    4.14 +  bool ok = accessor->ConnectWithContext (this, context, cb);
    4.15 +  return ok;
    4.16 +}
    4.17 +bool 
    4.18  Object::TraceSourceDisconnect (std::string name, const CallbackBase &cb)
    4.19  {
    4.20    Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
     5.1 --- a/src/core/object.h	Sun Mar 02 06:43:12 2008 +0100
     5.2 +++ b/src/core/object.h	Sun Mar 02 21:00:37 2008 +0100
     5.3 @@ -396,6 +396,7 @@
     5.4    Attribute GetAttribute (std::string name) const;
     5.5  
     5.6    bool TraceSourceConnect (std::string name, const CallbackBase &cb);
     5.7 +  bool TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb);
     5.8    bool TraceSourceDisconnect (std::string name, const CallbackBase &cb);
     5.9  
    5.10    TypeId GetRealTypeId (void) const;
     6.1 --- a/src/core/trace-source-accessor.h	Sun Mar 02 06:43:12 2008 +0100
     6.2 +++ b/src/core/trace-source-accessor.h	Sun Mar 02 21:00:37 2008 +0100
     6.3 @@ -17,6 +17,7 @@
     6.4    void Unref (void) const;
     6.5  
     6.6    virtual bool Connect (ObjectBase *obj, const CallbackBase &cb) const = 0;
     6.7 +  virtual bool ConnectWithContext (ObjectBase *obj, std::string context, const CallbackBase &cb) const = 0;
     6.8    virtual bool Disconnect (ObjectBase *obj, const CallbackBase &cb) const = 0;
     6.9  private:
    6.10    mutable uint32_t m_count;
    6.11 @@ -44,6 +45,15 @@
    6.12        (p->*m_source).Connect (cb);
    6.13        return true;
    6.14      }
    6.15 +    virtual bool ConnectWithContext (ObjectBase *obj, std::string context, const CallbackBase &cb) const {
    6.16 +      T *p = dynamic_cast<T*> (obj);
    6.17 +      if (p == 0)
    6.18 +	{
    6.19 +	  return false;
    6.20 +	}
    6.21 +      (p->*m_source).ConnectWithContext (cb, context);
    6.22 +      return true;
    6.23 +    }
    6.24      virtual bool Disconnect (ObjectBase *obj, const CallbackBase &cb) const {
    6.25        T *p = dynamic_cast<T*> (obj);
    6.26        if (p == 0)
     7.1 --- a/src/core/traced-callback.h	Sun Mar 02 06:43:12 2008 +0100
     7.2 +++ b/src/core/traced-callback.h	Sun Mar 02 21:00:37 2008 +0100
     7.3 @@ -41,6 +41,7 @@
     7.4  public:
     7.5    TracedCallback ();
     7.6    void Connect (const CallbackBase & callback);
     7.7 +  void ConnectWithContext (const CallbackBase & callback, std::string path);
     7.8    void Disconnect (const CallbackBase & callback);
     7.9    void operator() (void) const;
    7.10    void operator() (T1 a1) const;
    7.11 @@ -48,7 +49,7 @@
    7.12    void operator() (T1 a1, T2 a2, T3 a3) const;
    7.13    void operator() (T1 a1, T2 a2, T3 a3, T4 a4) const;
    7.14  
    7.15 -private:
    7.16 +private:  
    7.17    typedef std::list<Callback<void,T1,T2,T3,T4> > CallbackList;
    7.18    CallbackList m_callbackList;
    7.19  };
    7.20 @@ -59,7 +60,6 @@
    7.21  
    7.22  namespace ns3 {
    7.23  
    7.24 -
    7.25  template<typename T1, typename T2, 
    7.26           typename T3, typename T4>
    7.27  TracedCallback<T1,T2,T3,T4>::TracedCallback ()
    7.28 @@ -77,6 +77,16 @@
    7.29  template<typename T1, typename T2, 
    7.30           typename T3, typename T4>
    7.31  void 
    7.32 +TracedCallback<T1,T2,T3,T4>::ConnectWithContext (const CallbackBase & callback, std::string path)
    7.33 +{
    7.34 +  Callback<void,std::string,T1,T2,T3,T4> cb;
    7.35 +  cb.Assign (callback);
    7.36 +  Callback<void,T1,T2,T3,T4> realCb = cb.Bind (path);
    7.37 +  m_callbackList.push_back (realCb);
    7.38 +}
    7.39 +template<typename T1, typename T2, 
    7.40 +         typename T3, typename T4>
    7.41 +void 
    7.42  TracedCallback<T1,T2,T3,T4>::Disconnect (const CallbackBase & callback)
    7.43  {
    7.44    for (typename CallbackList::iterator i = m_callbackList.begin ();
     8.1 --- a/src/core/traced-value.h	Sun Mar 02 06:43:12 2008 +0100
     8.2 +++ b/src/core/traced-value.h	Sun Mar 02 21:00:37 2008 +0100
     8.3 @@ -53,6 +53,9 @@
     8.4    void Connect (const CallbackBase &cb) {
     8.5      m_cb.Connect (cb);
     8.6    }
     8.7 +  void ConnectWithContext (const CallbackBase &cb, std::string path) {
     8.8 +    m_cb.ConnectWithContext (cb, path);
     8.9 +  }
    8.10    void Disconnect (const CallbackBase &cb) {
    8.11      m_cb.Disconnect (cb);
    8.12    }