//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <vector>
#include <cstddef>
#include <string>
#include "get_process_id_name.hpp"

namespace boost {
namespace interprocess {
namespace test {

template <class NodePool>
struct test_node_pool
{
   static bool allocate_then_deallocate(NodePool &pool);
   static bool deallocate_free_blocks(NodePool &pool);
};

template <class NodePool>
bool test_node_pool<NodePool>::allocate_then_deallocate(NodePool &pool)
{
   const std::size_t num_alloc = 1 + 3*pool.get_real_num_node();

   std::vector<void*> nodes;

   //Precondition, the pool must be empty
   if(0 != pool.num_free_nodes()){
      return false;
   }

   //First allocate nodes
   for(std::size_t i = 0; i < num_alloc; ++i){
      nodes.push_back(pool.allocate_node());
   }

   //Check that the free count is correct
   if((pool.get_real_num_node() - 1) != pool.num_free_nodes()){
      return false;
   }
   
   //Now deallocate all and check again
   for(std::size_t i = 0; i < num_alloc; ++i){
       pool.deallocate_node(nodes[i]);
   }

   //Check that the free count is correct
   if(4*pool.get_real_num_node() != pool.num_free_nodes()){
      return false;
   }
   
   pool.deallocate_free_blocks();

   if(0 != pool.num_free_nodes()){
      return false;
   }

   return true;
}

template <class NodePool>
bool test_node_pool<NodePool>::deallocate_free_blocks(NodePool &pool)
{
   const std::size_t max_blocks        = 10;
   const std::size_t max_nodes         = max_blocks*pool.get_real_num_node();
   const std::size_t nodes_per_block   = pool.get_real_num_node();

   std::vector<void*> nodes;

   //Precondition, the pool must be empty
   if(0 != pool.num_free_nodes()){
      return false;
   }

   //First allocate nodes
   for(std::size_t i = 0; i < max_nodes; ++i){
      nodes.push_back(pool.allocate_node());
   }

   //Check that the free count is correct
   if(0 != pool.num_free_nodes()){
      return false;
   }
   
   //Now deallocate one of each block per iteration
   for(std::size_t node_i = 0; node_i < nodes_per_block; ++node_i){
      //Deallocate a node per block
      for(std::size_t i = 0; i < max_blocks; ++i){
         pool.deallocate_node(nodes[i*nodes_per_block + node_i]);
      }

      //Check that the free count is correct
      if(max_blocks*(node_i+1) != pool.num_free_nodes()){
         return false;
      }
      
      //Now try to deallocate free blocks
      pool.deallocate_free_blocks();

      //Until we don't deallocate the last node of every block
      //no node should be deallocated
      if(node_i != (nodes_per_block - 1)){
         if(max_blocks*(node_i+1) != pool.num_free_nodes()){
            return false;
         }
      }
      else{
         //If this is the last iteration, all the memory should
         //have been deallocated.
         if(0 != pool.num_free_nodes()){
            return false;
         }
      }
   }

   return true;
}

template<class node_pool_t>
bool test_all_node_pool()
{
   using namespace boost::interprocess;
   typedef managed_shared_memory::segment_manager segment_manager;

   typedef boost::interprocess::test::test_node_pool<node_pool_t> test_node_pool_t;
   shared_memory_object::remove(test::get_process_id_name());
   {
      managed_shared_memory shm(create_only, test::get_process_id_name(), 4*1024*sizeof(void*));

      typedef deleter<node_pool_t, segment_manager> deleter_t;
      typedef unique_ptr<node_pool_t, deleter_t> unique_ptr_t;

      //Delete the pool when the tests end
      unique_ptr_t p
         (shm.construct<node_pool_t>(anonymous_instance)(shm.get_segment_manager())
         ,deleter_t(shm.get_segment_manager()));

      //Now call each test
      if(!test_node_pool_t::allocate_then_deallocate(*p))
         return false;
      if(!test_node_pool_t::deallocate_free_blocks(*p))
         return false;
   }
   shared_memory_object::remove(test::get_process_id_name());
   return true;
}

}  //namespace test {
}  //namespace interprocess {
}  //namespace boost {

#include <boost/interprocess/detail/config_end.hpp>
