Small update of PIT. Now pit implementation is policy-templated.

Three versions are explicitly instantiated:
- CcnxPitImpl<persistent_policy_traits> ("ns3::CcnxPit")
- CcnxPitImpl<random_policy_traits>     ("ns3::CcnxPitRandom")
- CcnxPitImpl<lru_policy_traits>        ("ns3::CcnxPitLru")
diff --git a/model/pit/ccnx-pit-impl.cc b/model/pit/ccnx-pit-impl.cc
index 9acf867..3699a1e 100644
--- a/model/pit/ccnx-pit-impl.cc
+++ b/model/pit/ccnx-pit-impl.cc
@@ -24,6 +24,11 @@
 #include "ns3/ccnx-content-object-header.h"
 #include "ns3/ccnx-forwarding-strategy.h"
 
+#include "../../utils/empty-policy.h"
+#include "../../utils/persistent-policy.h"
+#include "../../utils/random-policy.h"
+#include "../../utils/lru-policy.h"
+
 #include "ns3/log.h"
 #include "ns3/string.h"
 #include "ns3/uinteger.h"
@@ -37,10 +42,75 @@
 using namespace boost::tuples;
 using namespace boost;
 namespace ll = boost::lambda;
+using namespace ndnSIM;
+
+#define NS_OBJECT_ENSURE_REGISTERED_TEMPL(type, templ)  \
+  static struct X ## type ## templ ## RegistrationClass \
+  {                                                     \
+    X ## type ## templ ## RegistrationClass () {        \
+      ns3::TypeId tid = type<templ>::GetTypeId ();      \
+      tid.GetParent ();                                 \
+    }                                                   \
+  } x_ ## type ## templ ## RegistrationVariable
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED (CcnxPitImpl);
+template<>
+TypeId
+CcnxPitImpl<persistent_policy_traits>::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::CcnxPit")
+    .SetGroupName ("Ccnx")
+    .SetParent<CcnxPit> ()
+    .AddConstructor< CcnxPitImpl< persistent_policy_traits > > ()
+    .AddAttribute ("MaxSize",
+                   "Set maximum number of entries in PIT. If 0, limit is not enforced",
+                   StringValue ("0"),
+                   MakeUintegerAccessor (&CcnxPitImpl< persistent_policy_traits >::GetMaxSize,
+                                         &CcnxPitImpl< persistent_policy_traits >::SetMaxSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+
+  return TypeId ();
+}
+
+template<>
+TypeId
+CcnxPitImpl<random_policy_traits>::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::CcnxPitRandom")
+    .SetGroupName ("Ccnx")
+    .SetParent<CcnxPit> ()
+    .AddConstructor< CcnxPitImpl< random_policy_traits > > ()
+    .AddAttribute ("MaxSize",
+                   "Set maximum number of entries in PIT. If 0, limit is not enforced",
+                   StringValue ("0"),
+                   MakeUintegerAccessor (&CcnxPitImpl< random_policy_traits >::GetMaxSize,
+                                         &CcnxPitImpl< random_policy_traits >::SetMaxSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+
+  return TypeId ();
+}
+
+template<>
+TypeId
+CcnxPitImpl<lru_policy_traits>::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::CcnxPitLru")
+    .SetGroupName ("Ccnx")
+    .SetParent<CcnxPit> ()
+    .AddConstructor< CcnxPitImpl< lru_policy_traits > > ()
+    .AddAttribute ("MaxSize",
+                   "Set maximum number of entries in PIT. If 0, limit is not enforced",
+                   StringValue ("0"),
+                   MakeUintegerAccessor (&CcnxPitImpl< lru_policy_traits >::GetMaxSize,
+                                         &CcnxPitImpl< lru_policy_traits >::SetMaxSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+
+  return TypeId ();
+}
 
 
 // CcnxPitEntryImpl::CcnxPitEntryImpl (CcnxPit &pit,
@@ -57,45 +127,70 @@
 //   static_cast<CcnxPitImpl&> (m_container).i_time.erase (*this);
 // }
 
-TypeId
-CcnxPitImpl::GetTypeId ()
-{
-  static TypeId tid = TypeId ("ns3::CcnxPit")
-    .SetGroupName ("Ccnx")
-    .SetParent<CcnxPit> ()
-    .AddConstructor<CcnxPitImpl> ()
-    .AddAttribute ("MaxSize",
-                   "Set maximum number of entries in PIT. If 0, limit is not enforced",
-                   StringValue ("0"),
-                   MakeUintegerAccessor (&CcnxPitImpl::GetMaxSize, &CcnxPitImpl::SetMaxSize),
-                   MakeUintegerChecker<uint32_t> ())
-    ;
+// TypeId
+// CcnxPitImpl::GetTypeId ()
+// {
+//   static TypeId tid = TypeId ("ns3::CcnxPit")
+//     .SetGroupName ("Ccnx")
+//     .SetParent<CcnxPit> ()
+//     .AddConstructor<CcnxPitImpl> ()
+//     .AddAttribute ("MaxSize",
+//                    "Set maximum number of entries in PIT. If 0, limit is not enforced",
+//                    StringValue ("0"),
+//                    MakeUintegerAccessor (&CcnxPitImpl::GetMaxSize, &CcnxPitImpl::SetMaxSize),
+//                    MakeUintegerChecker<uint32_t> ())
+//     ;
 
-  return tid;
-}
+//   return tid;
+// }
 
-CcnxPitImpl::CcnxPitImpl ()
+
+// template<class AcceptanceAndReplacementPolicy>
+// TypeId
+// CcnxPitImpl::GetTypeId ()
+// {
+//   #error "Not specialized version is not supported"
+//   // static TypeId tid = TypeId ("ns3::CcnxPit")
+//   //   .SetGroupName ("Ccnx")
+//   //   .SetParent<CcnxPit> ()
+//   //   .AddConstructor<CcnxPitImpl> ()
+//   //   .AddAttribute ("MaxSize",
+//   //                  "Set maximum number of entries in PIT. If 0, limit is not enforced",
+//   //                  StringValue ("0"),
+//   //                  MakeUintegerAccessor (&CcnxPitImpl::GetMaxSize, &CcnxPitImpl::SetMaxSize),
+//   //                  MakeUintegerChecker<uint32_t> ())
+//   //   ;
+
+//   return Typeid ();
+// }
+
+template<class Policy>
+CcnxPitImpl<Policy>::CcnxPitImpl ()
 {
 }
 
-CcnxPitImpl::~CcnxPitImpl ()
+template<class Policy>
+CcnxPitImpl<Policy>::~CcnxPitImpl ()
 {
 }
 
+template<class Policy>
 uint32_t
-CcnxPitImpl::GetMaxSize () const
+CcnxPitImpl<Policy>::GetMaxSize () const
 {
-  return getPolicy ().get_max_size ();
+  return super::getPolicy ().get_max_size ();
 }
 
+template<class Policy>
 void
-CcnxPitImpl::SetMaxSize (uint32_t maxSize)
+CcnxPitImpl<Policy>::SetMaxSize (uint32_t maxSize)
 {
-  getPolicy ().set_max_size (maxSize);
+  super::getPolicy ().set_max_size (maxSize);
 }
 
+template<class Policy>
 void 
-CcnxPitImpl::NotifyNewAggregate ()
+CcnxPitImpl<Policy>::NotifyNewAggregate ()
 {
   if (m_fib == 0)
     {
@@ -109,8 +204,9 @@
   CcnxPit::NotifyNewAggregate ();
 }
 
+template<class Policy>
 void 
-CcnxPitImpl::DoDispose ()
+CcnxPitImpl<Policy>::DoDispose ()
 {
   super::clear ();
 
@@ -120,27 +216,31 @@
   CcnxPit::DoDispose ();
 }
 
-void CcnxPitImpl::RescheduleCleaning ()
+template<class Policy>
+void
+CcnxPitImpl<Policy>::RescheduleCleaning ()
 {
   m_cleanEvent.Cancel ();
   if (i_time.empty ())
     {
-      NS_LOG_DEBUG ("No items in PIT");
+      // NS_LOG_DEBUG ("No items in PIT");
       return;
     }
 
   Time nextEvent = i_time.begin ()->GetExpireTime () - Simulator::Now ();
-  if (nextEvent < 0) nextEvent = Seconds (0);
+  if (nextEvent <= 0) nextEvent = Seconds (0);
   
-  NS_LOG_DEBUG ("Schedule next cleaning in " <<
-                nextEvent.ToDouble (Time::S) << "s (at " <<
-                i_time.begin ()->GetExpireTime () << "s abs time");
+  // NS_LOG_DEBUG ("Schedule next cleaning in " <<
+  //               nextEvent.ToDouble (Time::S) << "s (at " <<
+  //               i_time.begin ()->GetExpireTime () << "s abs time");
+  
   m_cleanEvent = Simulator::Schedule (nextEvent,
                                       &CcnxPitImpl::CleanExpired, this);
 }
 
+template<class Policy>
 void
-CcnxPitImpl::CleanExpired ()
+CcnxPitImpl<Policy>::CleanExpired ()
 {
   NS_LOG_LOGIC ("Cleaning PIT. Total: " << i_time.size ());
   Time now = Simulator::Now ();
@@ -148,25 +248,30 @@
   // uint32_t count = 0;
   while (!i_time.empty ())
     {
-      time_index::iterator entry = i_time.begin ();
+      typename time_index::iterator entry = i_time.begin ();
       if (entry->GetExpireTime () <= now) // is the record stale?
         {
           m_forwardingStrategy->WillErasePendingInterest (entry->to_iterator ()->payload ());
           super::erase (entry->to_iterator ());
-      //     // count ++;
+          // count ++;
         }
       else
         break; // nothing else to do. All later records will not be stale
     }
 
+  if (super::getPolicy ().size ())
+    {
+      NS_LOG_DEBUG ("Size: " << super::getPolicy ().size ());
+    }
   RescheduleCleaning ();
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::Lookup (const CcnxContentObjectHeader &header)
+CcnxPitImpl<Policy>::Lookup (const CcnxContentObjectHeader &header)
 {
   /// @todo use predicate to search with exclude filters  
-  super::iterator item = super::longest_prefix_match (header.GetName ());
+  typename super::iterator item = super::longest_prefix_match (header.GetName ());
 
   if (item == super::end ())
     return 0;
@@ -174,14 +279,15 @@
     return item->payload (); // which could also be 0
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::Lookup (const CcnxInterestHeader &header)
+CcnxPitImpl<Policy>::Lookup (const CcnxInterestHeader &header)
 {
-  NS_LOG_FUNCTION (header.GetName ());
+  // NS_LOG_FUNCTION (header.GetName ());
   NS_ASSERT_MSG (m_fib != 0, "FIB should be set");
   NS_ASSERT_MSG (m_forwardingStrategy != 0, "Forwarding strategy  should be set");
 
-  super::iterator foundItem, lastItem;
+  typename super::iterator foundItem, lastItem;
   bool reachLast;
   boost::tie (foundItem, reachLast, lastItem) = super::getTrie ().find (header.GetName ());
 
@@ -191,8 +297,9 @@
     return lastItem->payload (); // which could also be 0
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::Create (Ptr<const CcnxInterestHeader> header)
+CcnxPitImpl<Policy>::Create (Ptr<const CcnxInterestHeader> header)
 {
   Ptr<CcnxFibEntry> fibEntry = m_fib->LongestPrefixMatch (*header);
   if (fibEntry == 0)
@@ -203,7 +310,7 @@
   //                " Prefix = "<< header->GetName() << ", NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
 
   Ptr< entry > newEntry = ns3::Create< entry > (boost::ref (*this), header, fibEntry);
-  std::pair< super::iterator, bool > result = super::insert (header->GetName (), newEntry);
+  std::pair< typename super::iterator, bool > result = super::insert (header->GetName (), newEntry);
   if (result.first != super::end ())
     {
       if (result.second)
@@ -223,19 +330,21 @@
 }
 
 
+template<class Policy>
 void
-CcnxPitImpl::MarkErased (Ptr<CcnxPitEntry> item)
+CcnxPitImpl<Policy>::MarkErased (Ptr<CcnxPitEntry> item)
 {
   // entry->SetExpireTime (Simulator::Now () + m_PitEntryPruningTimout);
   super::erase (StaticCast< entry > (item)->to_iterator ());
 }
 
 
+template<class Policy>
 void
-CcnxPitImpl::Print (std::ostream& os) const
+CcnxPitImpl<Policy>::Print (std::ostream& os) const
 {
   // !!! unordered_set imposes "random" order of item in the same level !!!
-  super::parent_trie::const_recursive_iterator item (super::getTrie ()), end (0);
+  typename super::parent_trie::const_recursive_iterator item (super::getTrie ()), end (0);
   for (; item != end; item++)
     {
       if (item->payload () == 0) continue;
@@ -244,16 +353,18 @@
     }
 }
 
+template<class Policy>
 uint32_t
-CcnxPitImpl::GetSize () const
+CcnxPitImpl<Policy>::GetSize () const
 {
   return super::getPolicy ().size ();
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::Begin ()
+CcnxPitImpl<Policy>::Begin ()
 {
-  super::parent_trie::recursive_iterator item (super::getTrie ()), end (0);
+  typename super::parent_trie::recursive_iterator item (super::getTrie ()), end (0);
   for (; item != end; item++)
     {
       if (item->payload () == 0) continue;
@@ -266,18 +377,20 @@
     return item->payload ();
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::End ()
+CcnxPitImpl<Policy>::End ()
 {
   return 0;
 }
 
+template<class Policy>
 Ptr<CcnxPitEntry>
-CcnxPitImpl::Next (Ptr<CcnxPitEntry> from)
+CcnxPitImpl<Policy>::Next (Ptr<CcnxPitEntry> from)
 {
   if (from == 0) return 0;
   
-  super::parent_trie::recursive_iterator
+  typename super::parent_trie::recursive_iterator
     item (*StaticCast< entry > (from)->to_iterator ()),
     end (0);
   
@@ -294,4 +407,14 @@
 }
 
 
+// explicit instantiation and registering
+template class CcnxPitImpl<persistent_policy_traits>;
+template class CcnxPitImpl<random_policy_traits>;
+template class CcnxPitImpl<lru_policy_traits>;
+
+NS_OBJECT_ENSURE_REGISTERED_TEMPL(CcnxPitImpl, persistent_policy_traits);
+NS_OBJECT_ENSURE_REGISTERED_TEMPL(CcnxPitImpl, random_policy_traits);
+NS_OBJECT_ENSURE_REGISTERED_TEMPL(CcnxPitImpl, lru_policy_traits);
+
+
 } // namespace ns3
diff --git a/model/pit/ccnx-pit-impl.h b/model/pit/ccnx-pit-impl.h
index 2f52604..94709f3 100644
--- a/model/pit/ccnx-pit-impl.h
+++ b/model/pit/ccnx-pit-impl.h
@@ -24,8 +24,6 @@
 #include "ccnx-pit.h"
 
 #include "../../utils/trie-with-policy.h"
-#include "../../utils/empty-policy.h"
-#include "../../utils/persistent-policy.h"
 
 #include "ccnx-pit-entry-impl.h"
 
@@ -37,18 +35,21 @@
  * \ingroup ccnx
  * \brief Class implementing Pending Interests Table
  */
+template<class Policy>
 class CcnxPitImpl : public CcnxPit
                   , protected ndnSIM::trie_with_policy<CcnxNameComponents,
-                                                       ndnSIM::smart_pointer_payload_traits<CcnxPitEntryImpl< CcnxPitImpl > >,
-                                                       ndnSIM::persistent_policy_traits
+                                                       ndnSIM::smart_pointer_payload_traits<CcnxPitEntryImpl< CcnxPitImpl< Policy > > >,
+                                                       // ndnSIM::persistent_policy_traits
+                                                       Policy
                                                        >
 {
 public:
   typedef ndnSIM::trie_with_policy<CcnxNameComponents,
-                                   ndnSIM::smart_pointer_payload_traits<CcnxPitEntryImpl< CcnxPitImpl > >,
-                                   ndnSIM::persistent_policy_traits
+                                   ndnSIM::smart_pointer_payload_traits<CcnxPitEntryImpl< CcnxPitImpl< Policy > > >,
+                                   // ndnSIM::persistent_policy_traits
+                                   Policy
                                    > super;
-  typedef CcnxPitEntryImpl< CcnxPitImpl > entry;
+  typedef CcnxPitEntryImpl< CcnxPitImpl< Policy > > entry;
 
   /**
    * \brief Interface ID
diff --git a/utils/fifo-policy.h b/utils/fifo-policy.h
index 7a61721..7286524 100644
--- a/utils/fifo-policy.h
+++ b/utils/fifo-policy.h
@@ -71,7 +71,7 @@
       inline bool
       insert (typename parent_trie::iterator item)
       {
-        if (policy_container::size () >= max_size_)
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
           {
             base_.erase (&(*policy_container::begin ()));
           }
diff --git a/utils/lru-policy.h b/utils/lru-policy.h
index 92a9953..f828801 100644
--- a/utils/lru-policy.h
+++ b/utils/lru-policy.h
@@ -73,7 +73,7 @@
       inline bool
       insert (typename parent_trie::iterator item)
       {
-        if (policy_container::size () >= max_size_)
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
           {
             base_.erase (&(*policy_container::begin ()));
           }
diff --git a/utils/random-policy.h b/utils/random-policy.h
index 288cd74..2b17fb9 100644
--- a/utils/random-policy.h
+++ b/utils/random-policy.h
@@ -98,7 +98,7 @@
       {
         get_order (item) = u_rand.GetValue ();
 
-        if (policy_container::size () >= max_size_)
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
           {
             if (MemberHookLess<Container>() (*item, *policy_container::begin ()))
               {