text:
/*
 * Copyright (c) 2018 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <algorithm>
#include <boost/range/combine.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/combine.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#include <experimental/iterator>
#include <founder_sequences/founder_sequences.hh>
#include <founder_sequences/generate_context.hh>
#include <founder_sequences/rmq.hh>
#include <libbio/algorithm.hh>
#include <libbio/consecutive_alphabet.hh>
#include <libbio/counting_sort.hh>
#include <libbio/fasta_reader.hh>
#include <libbio/line_reader.hh>
#include <libbio/sdsl_boost_serialization.hh>
#include <libbio/vector_source.hh>
#include <memory>
#include <vector>

namespace lb	= libbio;
namespace lsr	= libbio::sequence_reader;

namespace founder_sequences { namespace detail {

	std::size_t progress_indicator_gc_data_source::progress_step_max() const
	{
		return m_ctx->m_step_max;
	}

	std::size_t progress_indicator_gc_data_source::progress_current_step() const
	{
		return m_ctx->m_current_step.load(std::memory_order_relaxed);
	}

	void progress_indicator_lp_generate_traceback_data_source::progress_log_extra() const
	{
		auto const sample_count(m_context->current_pbwt_sample_count());

		std::cerr << ", " << sample_count;
		if (1 == sample_count)
			std::cerr << " sample";
		else
			std::cerr << " samples";
	}
}}

namespace founder_sequences {

	void generate_context::load_input(char const *input_path, lsr::input_format const input_file_format)
	{
		lb::log_time(std::cerr);
		std::cerr << "Loading the input…" << std::flush;

		lsr::read_input(input_path, input_file_format, m_sequence_container);
		m_sequence_container->to_spans(m_sequences);

		if (0 == m_sequences.size())
		{
			std::cerr << "\nThe input file contained no sequences." << std::endl;
			exit(EXIT_SUCCESS);
		}

		auto const seq_length(m_sequences.front().size());
		std::cerr << " length: " << seq_length << std::endl;
	}

	void generate_context::check_input() const
	{
		lb::log_time(std::cerr);
		std::cerr << "Checking the input…" << std::endl;

		// Check that all the vectors have equal lengths.
		auto const sequence_length(m_sequences.front().size());
		bool stop(false);
		std::size_t i(1);
		for (auto const &vec : m_sequences | ranges::view::drop(1))
		{
			if (vec.size() != sequence_length)
			{
				stop = true;
				std::cerr
					<< "The length of the sequence at index " << i << " was " << vec.size()
					<< " while that of the first one was " << sequence_length << '.' << std::endl;
			}
			++i;
		}

		if (stop)
			exit(EXIT_FAILURE);
	}

	void generate_context::generate_alphabet_and_continue()
	{
		auto const sequence_length(m_sequences.front().size());

		if (0 == m_pbwt_sample_rate)
		{
			libbio::log_time(std::cerr);
			std::cerr << "PBWT sampling shall not be done." << std::endl;
			m_pbwt_sample_rate = 1 + sequence_length;
		}
		else
		{
			auto const multiplier(m_pbwt_sample_rate);
			m_pbwt_sample_rate = std::ceil(multiplier * std::sqrt(sequence_length));
			libbio::log_time(std::cerr);
			std::cerr << "Using " << multiplier << "√n = " << m_pbwt_sample_rate << " as the sample rate." << std::endl;
		}

		libbio::log_time(std::cerr);
		std::cerr << "Generating a compressed alphabet…" << std::endl;

		m_current_step = 0;
		m_step_max = m_sequences.size();
		m_progress_indicator_data_source.reset(new detail::progress_indicator_gc_data_source(*this));

		dispatch_async(*m_parallel_queue, ^{
			lb::consecutive_alphabet_as_builder <std::uint8_t> builder;

			builder.init();
			std::size_t i(0);
			for (auto const &vec : m_sequences)
			{
				builder.prepare(vec);
				m_current_step.fetch_add(1, std::memory_order_relaxed);
			}
			builder.compress();

			using std::swap;
			swap(m_alphabet, builder.alphabet());

			dispatch_async(dispatch_get_main_queue(), ^{
				m_progress_indicator.end_logging_mt();
				m_current_step = 0;
				m_step_max = 0;
				calculate_segmentation(0, sequence_length);
			});
		});

		m_progress_indicator.log_with_progress_bar("\t", *m_progress_indicator_data_source);
	}

	void generate_context::calculate_segmentation_short_path(std::size_t const lb, std::size_t const rb)
	{
		segmentation_sp_context ctx(*this, lb, rb);
		ctx.process();
		std::cerr << "Outputting…" << std::endl;
		ctx.output_founders();

		if (m_segments_ostream_ptr)
			ctx.output_segments();

		// Finish.
		finish();
		lb::log_time(std::cerr);
		std::cerr << "Done." << std::endl;
		exit(EXIT_SUCCESS);
	}

	void generate_context::calculate_segmentation_long_path(std::size_t const lb, std::size_t const rb)
	{
		assert(m_segment_length < rb - lb);
		assert(0 == lb); // FIXME: handle ranges that don't start from zero.

		auto *ctx(new segmentation_lp_context(*this, m_parallel_queue, m_serial_queue)); // Uses callbacks, deleted in the final one.
		m_progress_indicator_data_source.reset(new detail::progress_indicator_lp_generate_traceback_data_source(*ctx));

		ctx->generate_traceback(lb, rb);
		m_progress_indicator.log_with_progress_bar("\t", *m_progress_indicator_data_source);
	}

	void generate_context::check_traceback_size(segmentation_context &ctx)
	{
		if (! (ctx.max_segment_size() < sequence_count()))
		{
			finish();
			std::cerr << "Unable to reduce the number of sequences; the maximum segment size is equal to the number of input sequences." << std::endl;
			exit(EXIT_FAILURE);
		}
	}

	void generate_context::context_did_finish_traceback(segmentation_sp_context &ctx)
	{
		check_traceback_size(ctx);
	}

	void generate_context::context_will_follow_traceback(segmentation_lp_context &ctx)
	{
		// Not main queue.

		// Update the progress indicator.
		m_progress_indicator.end_logging(); // Uses dispatch_sync.

		dispatch_async(dispatch_get_main_queue(), ^{
			lb::log_time(std::cerr);
			std::cerr << "Following the traceback…" << std::flush;
		});

	}

	void generate_context::context_did_finish_traceback(segmentation_lp_context &ctx, std::size_t const segment_count, std::size_t const max_segment_size)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		std::cerr << " there were " << segment_count << " segments the maximum size of which was " << max_segment_size << '.' << std::endl;
		check_traceback_size(ctx);

		lb::log_time(std::cerr);
		std::cerr << "Updating the PBWT samples to traceback positions…" << std::endl;

		ctx.update_samples_to_traceback_positions();
	}

	void generate_context::context_will_start_update_samples_tasks(segmentation_lp_context &ctx)
	{
		// Not main queue.

		m_progress_indicator_data_source.reset(new detail::progress_indicator_lp_generic_data_source(ctx));
		m_progress_indicator.log_with_progress_bar("\t", *m_progress_indicator_data_source);
	}

	void generate_context::context_did_start_update_samples_tasks(segmentation_lp_context &ctx)
	{
		// Not main queue.
	}

	void generate_context::context_did_update_pbwt_samples_to_traceback_positions(segmentation_lp_context &ctx)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		m_progress_indicator.end_logging_mt();

		lb::log_time(std::cerr);
		std::cerr << "Reducing the number of segments…" << std::endl;

		ctx.find_segments_greedy();
	}

	void generate_context::context_will_merge_segments(segmentation_lp_context &ctx)
	{
		// Not main queue.

		m_progress_indicator_data_source.reset(new detail::progress_indicator_lp_generic_data_source(ctx));
		m_progress_indicator.log_with_progress_bar("\t", *m_progress_indicator_data_source);
	}

	void generate_context::context_did_merge_segments(segmentation_lp_context &ctx, segmentation_container &&container)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		m_progress_indicator.end_logging_mt();

		// Context no longer needed, deallocate.
		ctx.cleanup();

		if (m_segmentation_ostream.is_open())
			save_segmentation_to_file(container);

		if (running_mode::GENERATE_FOUNDERS == m_running_mode)
			join_segments_and_output(std::move(container));
		else
			finish_lp();
	}

	void generate_context::load_segmentation_from_file(segmentation_container &container)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());
		assert(m_segmentation_istream.is_open());

		lb::log_time(std::cerr);
		std::cerr << "Loading the segmentation…" << std::flush;
		std::string stored_input_path;
		boost::archive::text_iarchive archive(m_segmentation_istream);
		archive >> stored_input_path;
		archive >> m_segment_length;
		archive >> m_alphabet;
		archive >> container;

		std::cerr << " done.\n";
		std::cerr << "\tStored input path: '" << stored_input_path << "'\n";
		std::cerr << "\tSegment length bound: " << m_segment_length << std::endl;
	}

	void generate_context::save_segmentation_to_file(segmentation_container const &container)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());
		assert(m_segmentation_ostream.is_open());

		lb::log_time(std::cerr);
		std::cerr << "Saving the segmentation…" << std::endl;

		boost::archive::text_oarchive archive(m_segmentation_ostream);
		archive << m_sequence_container->path();
		archive << m_segment_length;
		archive << m_alphabet;
		archive << container;
	}

	void generate_context::join_segments_and_output(segmentation_container &&container)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		lb::log_time(std::cerr);
		std::cerr << "Joining the remaining segments…" << std::endl;

		auto *ctx(new join_context(*this, m_parallel_queue, m_serial_queue, std::move(container), m_random_seed)); // Uses callbacks, deleted in the final one.
		ctx->join_segments_and_output(m_segment_joining_method);
	}

	void generate_context::context_will_output_founders(join_context &ctx)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		lb::log_time(std::cerr);
		std::cerr << "Outputting the founders…" << std::endl;
	}

	void generate_context::context_did_output_founders(join_context &ctx)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		if (m_segments_ostream_ptr)
		{
			lb::log_time(std::cerr);
			std::cerr << "Outputting the segments…" << std::endl;
			ctx.output_segments(m_segment_joining_method);
		}

		ctx.cleanup();
		finish_lp();
	}

	void generate_context::finish_lp()
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		// Finish.
		finish();
		lb::log_time(std::cerr);
		std::cerr << "Done." << std::endl;
		exit(EXIT_SUCCESS);
	}

	void generate_context::calculate_segmentation(std::size_t const lb, std::size_t const rb)
	{
		assert(dispatch_get_current_queue() == dispatch_get_main_queue());

		lb::log_time(std::cerr);
		std::cerr << "Calculating the segmentation…" << std::endl;

		if (rb - lb < 2 * m_segment_length)
			calculate_segmentation_short_path(lb, rb);
		else
			calculate_segmentation_long_path(lb, rb);
	}

	void generate_context::prepare(
		char const *segmentation_input_path,
		char const *segmentation_output_path,
		char const *output_founders_path,
		char const *output_segments_path
	)
	{
		if (m_use_single_thread)
		{
			lb::dispatch_ptr <dispatch_queue_t> queue(dispatch_queue_create("fi.iki.tsnorri.worker-queue", DISPATCH_QUEUE_SERIAL), false);
			m_parallel_queue = queue;
			m_serial_queue = queue;
		}
		else
		{
			m_parallel_queue.reset(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), true);
			m_serial_queue.reset(dispatch_queue_create("fi.iki.tsnorri.processing-queue", DISPATCH_QUEUE_SERIAL), false);
		}

		if (segmentation_input_path)
			lb::open_file_for_reading(segmentation_input_path, m_segmentation_istream);
		else if (segmentation_output_path)
			lb::open_file_for_writing(segmentation_output_path, m_segmentation_ostream, lb::writing_open_mode::CREATE);

		if (output_founders_path)
			lb::open_file_for_writing(output_founders_path, m_founders_ostream, lb::writing_open_mode::CREATE);

		if (output_segments_path)
		{
			if ('-' == output_segments_path[0] && '\0' == output_segments_path[1])
				m_segments_ostream_ptr = &std::cout;
			else
			{
				lb::open_file_for_writing(output_segments_path, m_segments_ostream, lb::writing_open_mode::CREATE);
				m_segments_ostream_ptr = &m_segments_ostream;
			}
		}

		if (m_progress_indicator.is_stderr_interactive())
			m_progress_indicator.install();
	}

	void generate_context::load_and_generate(
		char const *input_path,
		lsr::input_format const input_file_format
	)
	{
		load_input(input_path, input_file_format);
		check_input();

		if (m_segmentation_istream.is_open())
		{
			segmentation_container container;
			load_segmentation_from_file(container);
			join_segments_and_output(std::move(container));
		}
		else
		{
			generate_alphabet_and_continue();
		}
	}

	void generate_context::finish()
	{
		m_progress_indicator.uninstall();
		cleanup();
	}
}

max_stars_repo_name: tsnorri/founder-sequences

max_issues_repo_name: tsnorri/founder-sequences

max_forks_repo_name: tsnorri/founder-sequences


text:
/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <eosio/producer_heartbeat_plugin/producer_heartbeat_plugin.hpp>
#include <eosio/chain/types.hpp>
#include <boost/asio/steady_timer.hpp>
#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>
#include <eosio/chain/abi_serializer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <cctype>
#include <locale>

namespace eosio {
   using namespace eosio::chain;
   template<typename I>
   std::string itoh(I n, size_t hlen = sizeof(I)<<1) {
      static const char* digits = "0123456789abcdef";
      std::string r(hlen, '0');
      for(size_t i = 0, j = (hlen - 1) * 4 ; i < hlen; ++i, j -= 4)
         r[i] = digits[(n>>j) & 0x0f];
      return r;
   }
   static appbase::abstract_plugin& _template_plugin = app().register_plugin<producer_heartbeat_plugin>();

// https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
        return !std::isspace(ch);
    }));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
        return !std::isspace(ch);
    }).base(), s.end());
}

// trim from both ends (in place)
static inline void trim(std::string &s) {
    ltrim(s);
    rtrim(s);
}

// trim (copying)
static inline std::string trim_copy(std::string s) {
    trim(s);
    return s;
}

class producer_heartbeat_plugin_impl {
   public:
      unique_ptr<boost::asio::steady_timer> timer;
      unique_ptr<boost::asio::steady_timer> retry_timer;
      boost::asio::steady_timer::duration timer_period;
      boost::asio::steady_timer::duration retry_timer_period;
      fc::optional<boost::signals2::scoped_connection> accepted_block_conn;
      int interval;
      int retry_max = 0;
      uint8_t curr_retry = 0;
      account_name heartbeat_contract = "";
      account_name heartbeat_blacklist_contract = "";
      std::string heartbeat_permission = "";
      std::string oncall = "telegram:nobody";
      account_name producer_name;
      std::string actor_blacklist_hash = "";
      uint32_t actor_blacklist_count = 0;
      uint64_t state_db_size = 0;
      uint64_t total_memory = 0;
      std::string cpu_info = "";
      std::string virtualization_type = "";
      fc::crypto::private_key _heartbeat_private_key;
      chain::public_key_type _heartbeat_public_key;
      boost::mutex mtx;
   	mutable_variant_object latencies;
   	map<std::string,std::pair<int64_t, uint32_t>> latencies_sum_count;

      void on_accepted_block(const block_state_ptr& block_state){
        if(producer_name == block_state->block->producer)
            return;
        boost::mutex::scoped_lock lock(mtx, boost::try_to_lock);
        if (lock){
           uint32_t latency = (fc::time_point::now() - block_state->block->timestamp).count()/1000;
           auto producer_name_str = block_state->block->producer.to_string();
           auto sumcount = latencies_sum_count.find(producer_name_str);
           if(sumcount == latencies_sum_count.end()){
               latencies_sum_count[producer_name_str] = std::pair<int64_t, uint32_t>(1, latency);
               latencies(producer_name_str, latency);
           }
           else{
              auto oldpair = sumcount->second;
              auto pair = std::pair<int64_t, uint32_t>(oldpair.first + 1, oldpair.second + latency);
              latencies_sum_count[producer_name_str] = pair;
              latencies(producer_name_str, pair.second / pair.first);
           }
        }
      }
      mutable_variant_object collect_metadata(controller& cc){
         boost::mutex::scoped_lock lock(mtx);
         // get latencies table & clear table
         auto latencies_to_use = latencies;
         latencies = mutable_variant_object();
         latencies_sum_count.clear();
         lock.unlock();

         return mutable_variant_object()
               ("hb_version", "1.8.1")
               ("version", itoh(static_cast<uint32_t>(app().version())))
               ("version_string", app().version_string())
               ("abl_hash", actor_blacklist_hash)
               ("abl_cnt", actor_blacklist_count)
               ("interval", interval)
               ("cpu", cpu_info)
               ("oncall", oncall)
               ("vtype", virtualization_type)
               ("memory", total_memory)
               ("db_size", state_db_size)
               ("latencies", latencies_to_use)
               ("head",  cc.fork_db_head_block_num());
      }
      void send_heartbeat_transaction(int retry = 0){
            auto& plugin = app().get_plugin<chain_plugin>();

            auto chainid = plugin.get_chain_id();
            auto abi_serializer_max_time = plugin.get_abi_serializer_max_time();
            // auto rw_api = plugin.get_read_write_api();

            controller& cc = plugin.chain();
            auto* account_obj = cc.db().find<account_object, by_name>(heartbeat_contract);
            if(account_obj == nullptr)
               return;
            abi_def abi;
            if (!abi_serializer::to_abi(account_obj->abi, abi))
               return;
            if(!producer_name)
               return;
            abi_serializer eosio_serializer(abi, abi_serializer_max_time);
            signed_transaction trx;
            action act;
            act.account = heartbeat_contract;
            act.name = N(heartbeat);
            act.authorization = vector<permission_level>{{producer_name,heartbeat_permission}};
            auto metadata_obj = collect_metadata(cc);
            auto metadata_json = fc::json::to_string( metadata_obj );
            act.data = eosio_serializer.variant_to_binary("heartbeat",mutable_variant_object()
               ("_user", producer_name)
               ("_metadata_json", metadata_json),
               abi_serializer_max_time);
            trx.actions.push_back(act);

            auto* account_obj_bl = cc.db().find<account_object, by_name>(heartbeat_blacklist_contract);
            if(account_obj_bl != nullptr)
            {
               abi_def abi_bl;
               if (abi_serializer::to_abi(account_obj_bl->abi, abi_bl))
               {
                  abi_serializer eosio_serializer_bl(abi_bl, abi_serializer_max_time);
                  action act_bl;
                  if(heartbeat_blacklist_contract != ""){
                     act_bl.account = heartbeat_blacklist_contract;
                     act_bl.name = N(sethash);
                     act_bl.authorization = vector<permission_level>{{producer_name,heartbeat_permission}};
                     act_bl.data = eosio_serializer_bl.variant_to_binary("sethash", chain::mutable_variant_object()
                        ("producer", producer_name)
                        ("hash", actor_blacklist_hash),
                        abi_serializer_max_time);
                     trx.actions.push_back(act_bl);

                  }
               }
            }

            trx.expiration = cc.head_block_time() + fc::seconds(30);
            trx.set_reference_block(cc.head_block_id());
            trx.sign(_heartbeat_private_key, chainid);
            curr_retry = retry;
            plugin.accept_transaction( packed_transaction(trx),[=](const fc::static_variant<fc::exception_ptr, transaction_trace_ptr>& result){
                   if (result.contains<fc::exception_ptr>()) {
                     if(curr_retry < retry_max - 1){
                        elog("heartbeat failed - retry: ${err}", ("err", result.get<fc::exception_ptr>()->to_detail_string()));
                        retry_timer->expires_from_now(retry_timer_period);
                        retry_timer->async_wait( [this](boost::system::error_code ec) {
                           send_heartbeat_transaction(curr_retry + 1);
                        });
                     }
                     else
                        elog("heartbeat failed: ${err}", ("err", result.get<fc::exception_ptr>()->to_detail_string()));
                  } else {
                     dlog("heartbeat success");
                  }
            });
      }
      void start_timer( ) {
         timer->expires_from_now(timer_period);
         timer->async_wait( [this](boost::system::error_code ec) {
               start_timer();
               if(!ec) {
                  try{
                     send_heartbeat_transaction();
                  }
                  FC_LOG_AND_DROP();

               }
               else {
                  elog( "Error from heartbeat timer: ${m}",( "m", ec.message()));
               }
            });
      }
};

producer_heartbeat_plugin::producer_heartbeat_plugin():my(new producer_heartbeat_plugin_impl()){
   my->timer.reset(new boost::asio::steady_timer( app().get_io_service()));
   my->retry_timer.reset(new boost::asio::steady_timer( app().get_io_service()));
   my->latencies = mutable_variant_object();
}
producer_heartbeat_plugin::~producer_heartbeat_plugin(){}

void producer_heartbeat_plugin::set_program_options(options_description&, options_description& cfg) {
   cfg.add_options()
         ("heartbeat-period", bpo::value<int>()->default_value(1500),
          "Heartbeat transaction period in seconds")
         ("heartbeat-retry-max", bpo::value<int>()->default_value(3),
          "Heartbeat max retries")
         ("heartbeat-retry-delay-seconds", bpo::value<int>()->default_value(10),
          "Heartbeat retry delay")
         ("heartbeat-signature-provider", bpo::value<string>()->default_value("HEARTBEAT_PUB_KEY=KEY:HEARTBEAT_PRIVATE_KEY"),
          "Heartbeat key provider")
         ("heartbeat-contract", bpo::value<string>()->default_value("eosheartbeat"),
          "Heartbeat Contract")
         ("heartbeat-permission", bpo::value<string>()->default_value("heartbeat"),
          "Heartbeat permission name")
         ("heartbeat-blacklist-contract", bpo::value<string>()->default_value("theblacklist"),
          "Heartbeat Blacklist Contract")
         ("heartbeat-oncall", bpo::value<string>()->default_value("telegram:nobody"),
          "Heartbeat Oncall Contacts")

         ;
}

#define LOAD_VALUE_SET(options, name, container, type) \
if( options.count(name) ) { \
   const std::vector<std::string>& ops = options[name].as<std::vector<std::string>>(); \
   std::copy(ops.begin(), ops.end(), std::inserter(container, container.end())); \
}

std::string get_cpuinfo() {
    std::string token;
    std::ifstream file("/proc/cpuinfo");
    while(file >> token) {
        if(token == "model") {
            std::string mem;
            if(!(file >> mem))
               return 0;
            if(mem == "name"){
               if(!(file >> mem))
                  return 0;
               std::getline(file,mem);
               return mem;
            }
        }
        // ignore rest of the line
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return ""; // nothing found
}

std::string get_cpu_type(){
   std::string token;
   std::ifstream file("/sys/devices/virtual/dmi/id/product_name");
   if(!file)
      return "unknown";
   file >> token;

   if(token == "HVM" || token == "Droplet"){
      return "HVM";
   }
   if(token == "VMware"){
      return "VMware";
   }
   return "Bare-metal";
}
unsigned long get_mem_total() {
    std::string token;
    std::ifstream file("/proc/meminfo");
    while(file >> token) {
        if(token == "MemTotal:") {
            unsigned long mem;
            if(file >> mem) {
                return mem;
            } else {
                return 0;
            }
        }
        // ignore rest of the line
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return 0; // nothing found
}

template <typename T>
void remove_duplicates(std::vector<T>& vec)
{
  std::sort(vec.begin(), vec.end());
  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}

std::string build_blacklist_line(std::string element){
   std::ostringstream stringStream;
   stringStream << "actor-blacklist=" << element << "\n";
   return stringStream.str();
}

void producer_heartbeat_plugin::plugin_initialize(const variables_map& options) {
   try {
      my->total_memory = get_mem_total();
      my->cpu_info = trim_copy(get_cpuinfo());
      my->virtualization_type = get_cpu_type();
      if( options.count( "heartbeat-period" )) {
         my->interval = options.at( "heartbeat-period" ).as<int>();
         my->timer_period = std::chrono::seconds( my->interval );
      }
      if( options.count( "heartbeat-retry-delay-seconds" )) {
         my->retry_timer_period = std::chrono::seconds( options.at( "heartbeat-retry-delay-seconds" ).as<int>() );
      }
      if( options.count( "heartbeat-retry-max" )) {
         my->retry_max = options.at( "heartbeat-retry-max" ).as<int>();
      }
      if( options.count( "heartbeat-contract" )) {
         my->heartbeat_contract = options.at( "heartbeat-contract" ).as<string>();
      }
      if( options.count( "heartbeat-blacklist-contract" )) {
         my->heartbeat_blacklist_contract = options.at( "heartbeat-blacklist-contract" ).as<string>();
      }
      if( options.count( "heartbeat-permission" )) {
         my->heartbeat_permission = options.at( "heartbeat-permission" ).as<string>();
      }
      if(options.count("producer-name")){
         const std::vector<std::string>& ops = options["producer-name"].as<std::vector<std::string>>();
         my->producer_name = ops[0];
      }
      if(options.count("chain-state-db-size-mb")){
         my->state_db_size = options["chain-state-db-size-mb"].as<uint64_t>();
      }
      if(options.count("heartbeat-oncall")){
         my->oncall = options["heartbeat-oncall"].as<std::string>();
      }

      if(options.count("actor-blacklist")){
         auto blacklist_actors = options["actor-blacklist"].as<std::vector<std::string>>();
         remove_duplicates(blacklist_actors);
         sort(blacklist_actors.begin(), blacklist_actors.end());

         std::vector<std::string> ret;
         ret.reserve(blacklist_actors.size());
         for (const auto &v : blacklist_actors) {
            ret.push_back(build_blacklist_line(v));
         }

         auto output = ret;
         std::string actor_blacklist_str = std::accumulate(output.begin(), output.end(), std::string(""));
         my->actor_blacklist_hash = (string)fc::sha256::hash(actor_blacklist_str);
         my->actor_blacklist_count = blacklist_actors.size();
      }
      if( options.count("heartbeat-signature-provider") ) {
            auto key_spec_pair = options["heartbeat-signature-provider"].as<std::string>();

            try {
               auto delim = key_spec_pair.find("=");
               EOS_ASSERT(delim != std::string::npos, eosio::chain::plugin_config_exception, "Missing \"=\" in the key spec pair");
               auto pub_key_str = key_spec_pair.substr(0, delim);
               auto spec_str = key_spec_pair.substr(delim + 1);

               auto spec_delim = spec_str.find(":");
               EOS_ASSERT(spec_delim != std::string::npos, eosio::chain::plugin_config_exception, "Missing \":\" in the key spec pair");
               auto spec_type_str = spec_str.substr(0, spec_delim);
               auto spec_data = spec_str.substr(spec_delim + 1);

               auto pubkey = public_key_type(pub_key_str);

               if (spec_type_str == "KEY") {
                  ilog("Loaded heartbeat key");
                  my->_heartbeat_private_key = fc::crypto::private_key(spec_data);
                  my->_heartbeat_public_key = pubkey;
               } else if (spec_type_str == "KEOSD") {
                  elog("KEOSD heartbeat key not supported");
                  // not supported
               }

            } catch (...) {
               elog("Malformed signature provider: \"${val}\", ignoring!", ("val", key_spec_pair));
            }
         }

   }
   FC_LOG_AND_RETHROW()
}

void producer_heartbeat_plugin::plugin_startup() {
   ilog("producer heartbeat plugin:  plugin_startup() begin");
   try{
      auto& chain = app().find_plugin<chain_plugin>()->chain();
      my->accepted_block_conn.emplace(chain.accepted_block.connect(
         [&](const block_state_ptr& b_state) {
            my->on_accepted_block(b_state);
      }));
      my->send_heartbeat_transaction();
   }
   FC_LOG_AND_DROP();
   my->start_timer();
}

void producer_heartbeat_plugin::plugin_shutdown() {
   my->accepted_block_conn.reset();
}

}

ext: cpp


text:
/*
 *  neolib.hpp
 *
 *  Copyright (c) 2007 Leigh Johnston.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 *     * Neither the name of Leigh Johnston nor the names of any
 *       other contributors to this software may be used to endorse or
 *       promote products derived from this software without specific prior
 *       written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <type_traits>
#include <cstdint>
#include <utility>
#include <variant>
#include <optional>
#include <chrono>

#include <neolib/neolib_export.hpp>

#ifdef NDEBUG
constexpr bool ndebug = true;
#else
constexpr bool ndebug = false;
#endif

#define rvalue_cast static_cast

#define GENERATE_HAS_MEMBER_TYPE(Type)                                            \
                                                                                \
template <class T, bool OK = std::is_class_v<T>>                                  \
class HasMemberType_##Type                                                        \
{                                                                                \
public:                                                                           \
    static constexpr bool RESULT = false;                                         \
};                                                                                \
                                                                                \
template <class T>                                                                \
class HasMemberType_##Type<T, true>                                               \
{                                                                                \
private:                                                                          \
    using Yes = char[2];                                                          \
    using  No = char[1];                                                          \
                                                                                \
    struct Fallback { struct Type { }; };                                         \
    struct Derived : T, Fallback { };                                             \
                                                                                \
    template < class U >                                                          \
    static No& test ( typename U::Type* );                                        \
    template < typename U >                                                       \
    static Yes& test ( U* );                                                      \
                                                                                \
public:                                                                           \
    static constexpr bool RESULT = sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
};                                                                                \
                                                                                \
template < class T >                                                              \
struct has_member_type_##Type                                                     \
: public std::integral_constant<bool, HasMemberType_##Type<T>::RESULT>            \
{ };

GENERATE_HAS_MEMBER_TYPE(abstract_type)

namespace neolib
{
    struct sfinae {};

    template <typename T>
    using to_const_reference_t = const std::remove_reference_t<T>&;
    template <typename T>
    inline to_const_reference_t<T> to_const(T&& object)
    {
        return const_cast<to_const_reference_t<T>>(object);
    }

    template <typename T, typename... Ts>
    struct variadic_index;

    template <typename T, typename... Ts>
    struct variadic_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};

    template <typename T, typename Tail, typename... Ts>
    struct variadic_index<T, Tail, Ts...> : std::integral_constant<std::size_t, 1 + variadic_index<T, Ts...>::value> {};

    template <typename T, typename... Ts>
    constexpr std::size_t index_of_v = variadic_index<T, Ts...>::value;

    template <typename T1, typename T2>
    class pair;

    namespace detail
    {
        template <typename T>
        struct is_pair { static constexpr bool value = false; };
        template <typename T1, typename T2>
        struct is_pair<std::pair<T1, T2>> { static constexpr bool value = true; };
        template <typename T1, typename T2>
        struct is_pair<const std::pair<T1, T2>> { static constexpr bool value = true; };
        template <typename T>
        constexpr bool is_pair_v = is_pair<T>::value;

        template <typename T>
        constexpr bool abstract_class_possible_v = std::is_class_v<T> && has_member_type_abstract_type<T>::value;

        template <typename T, typename AT, typename = sfinae>
        struct correct_const;
        template <typename T, typename AT>
        struct correct_const<T, AT, typename std::enable_if_t<!std::is_const_v<T>, sfinae>> { typedef AT type; };
        template <typename T, typename AT>
        struct correct_const<T, AT, typename std::enable_if_t<std::is_const_v<T>, sfinae>> { typedef const AT type; };

        template <typename T, typename AT>
        using correct_const_t = typename correct_const<T, AT>::type;

        template <typename, typename = sfinae>
        struct abstract_type : std::false_type {};
        template <typename T>
        struct abstract_type<T, typename std::enable_if_t<abstract_class_possible_v<T>, sfinae>> : std::true_type { typedef correct_const_t<T, typename T::abstract_type> type; };
        template <typename T>
        struct abstract_type<T, typename std::enable_if_t<std::is_arithmetic_v<T>, sfinae>> : std::true_type { typedef correct_const_t<T, T> type; };
        template <typename T>
        struct abstract_type<T, typename std::enable_if_t<std::is_enum_v<T>, sfinae>> : std::true_type { typedef correct_const_t<T, T> type; };
        template <typename T>
        struct abstract_type<T, typename std::enable_if_t<std::is_pointer_v<T>, sfinae>> : std::true_type { typedef correct_const_t<T, T> type; };
        template <typename T1, typename T2>
        struct abstract_type<std::pair<T1, pair<T1, T2>>> : std::false_type { typedef typename abstract_type<pair<T1, T2>>::type type; };
        template <typename T1, typename T2>
        struct abstract_type<const std::pair<T1, pair<T1, T2>>> : std::false_type { typedef typename abstract_type<const pair<T1, T2>>::type type; };
        template <>
        struct abstract_type<std::monostate> : std::true_type { typedef std::monostate type; };
        template <typename Rep, typename Period>
        struct abstract_type<std::chrono::duration<Rep, Period>> : std::true_type { typedef std::chrono::duration<Rep, Period> type; };
    }

    template <typename T>
    using abstract_t = typename detail::abstract_type<T>::type;

    template <typename T, typename = std::enable_if_t<detail::abstract_type<T>::value, sfinae>>
    inline const abstract_t<T>& to_abstract(const T& aArgument)
    {
        return static_cast<const abstract_t<T>&>(aArgument);
    }

    template <typename T, typename = std::enable_if_t<detail::abstract_type<T>::value, sfinae>>
    inline abstract_t<T>& to_abstract(T& aArgument)
    {
        return static_cast<abstract_t<T>&>(aArgument);
    }

    template <typename T1, typename T2>
    inline const abstract_t<pair<T1, T2>>& to_abstract(const std::pair<T1, pair<T1, T2>>& aArgument)
    {
        return static_cast<const abstract_t<pair<T1, T2>>&>(aArgument.second);
    }

    template <typename T1, typename T2>
    inline abstract_t<neolib::pair<T1, T2>>& to_abstract(std::pair<T1, pair<T1, T2>>& aArgument)
    {
        return static_cast<abstract_t<pair<T1, T2>>&>(aArgument.second);
    }

    namespace detail
    {
        template <typename T, typename = sfinae>
        struct abstract_return_type { typedef abstract_t<T>& type; };
        template <typename T>
        struct abstract_return_type<T, std::enable_if_t<std::is_scalar_v<T>, sfinae>> { typedef std::remove_const_t<T> type; };
    }

    template <typename T>
    using abstract_return_t = typename detail::abstract_return_type<T>::type;
}

#ifdef NEOLIB_HOSTED_ENVIRONMENT

// SIMD support
#ifndef NO_SIMD
#ifndef USE_AVX_DYNAMIC
#define USE_AVX
#endif
#ifndef USE_EMM_DYNAMIC
#define USE_EMM
#endif
#endif

#define USING_BOOST
#define BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING

#ifdef _WIN32
#include <neolib/core/win32/win32.hpp>
#endif

#ifdef USING_BOOST
#ifndef API
#include <boost/dll.hpp>
#define API extern "C" BOOST_SYMBOL_EXPORT
#endif
#endif

#endif // NEOLIB_HOSTED_ENVIRONMENT

ext: hpp


text:
//----------------------------------------------------------
// @file   : pot_tracker_double.cpp
// @author : Watanabe Yuuta
// @version: Ver0.1.4 (since 2014.05.02)
// @date   : 2016.06.09
//----------------------------------------------------------

#include <ros/ros.h>
#include <pthread.h>
#include <std_msgs/String.h>
#include <tms_msg_ss/pot_tracking_points.h>
#include <tms_msg_ss/pot_tracking_grid.h>

pthread_mutex_t mutex_laser = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_target = PTHREAD_MUTEX_INITIALIZER;

#include "opencv/cv.h"
#include <sensor_msgs/LaserScan.h>
#include "tms_ss_pot/define.h"
#include "tms_ss_pot/Target.h"
#include "tms_ss_pot/Laser.h"
#include "tms_ss_pot/Particle_filter.h"
#include "tms_ss_pot/Multiple_particle_filter.h"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <string>
#include <iostream>
#include <ctime>
#include <time.h>
#include <iostream>
#include <fstream>
#include <string>

std::vector<float> scanData;
CLaser laser;
bool CallbackCalled = false;
IDparam tmp_param;
std::vector< IDparam > idparam;
std::vector< IDparam >::iterator v;

void *Visualization( void *ptr )
{
    int count = 0;
    int   ID;
    float X;
    float Y;
    ros::Rate r(10);
    ros::Publisher *pub = (ros::Publisher *)ptr;

    tmp_param.id = 0;
    tmp_param.flag = 0;
    tmp_param.count = 0;
    tmp_param.start_pos.x = 0.0;
    tmp_param.start_pos.y = 0.0;
    tmp_param.tmp_pos.x = 0.0;
    tmp_param.tmp_pos.y = 0.0;
    tmp_param.end_pos.x = 0.0;
    tmp_param.end_pos.y = 0.0;
    tmp_param.vector.x = 0.0;
    tmp_param.vector.y = 0.0;
    idparam.push_back(tmp_param);

    while (ros::ok())
    {
        pthread_mutex_lock(&mutex_target);
        //std::cout << "visual_start"<<std::endl;
        tms_msg_ss::pot_tracking_grid grid;
        tms_msg_ss::pot_tracking_points points;

        for (int i = 0; i < MAX_TRACKING_OBJECT; i++)
        {
            if (laser.m_pTarget[i] != NULL)
            {
                if (laser.m_pTarget[i]->cnt < 200)
                {
                    //cout << laser.m_pTarget[i]->cnt << endl;
                    continue;
                }
                //std::cout << "laser.m_pTarget " << laser.m_pTarget[i]->cnt << std::endl;
                ID =  (laser.m_pTarget[i]->id);
                X  = -(laser.m_pTarget[i]->py);
                Y  =  (laser.m_pTarget[i]->px);
                //std::cout << "ID " << ID << "X " << X << "Y " << Y << std::endl;

                for (v = idparam.begin(); v != idparam.end(); ++v)
                {
                    v -> flag = 0;
                }

                for (v = idparam.begin(); v != idparam.end(); ++v)
                {
                    if ( v -> id == ID)
                    {
                        v -> flag = 1;
                        v -> count++;
                        if ((v -> count) % 10 == 0)
                        {
                            v -> vector.x = X - (v -> tmp_pos.x);
                            v -> vector.y = Y - (v -> tmp_pos.y);
                            v -> tmp_pos.x = X;
                            v -> tmp_pos.y = Y;
                        }
                        v -> end_pos.x = X;
                        v -> end_pos.y = Y;
                        //std::cout << "v = id " << std::endl;
                        break;
                    }
                    else if (v == idparam.end() - 1 )
                    {
                        tmp_param.id = ID;
                        tmp_param.flag = 1;
                        tmp_param.count = 0;
                        tmp_param.start_pos.x = X;
                        tmp_param.start_pos.y = Y;
                        tmp_param.tmp_pos.x = X;
                        tmp_param.tmp_pos.y = Y;
                        tmp_param.end_pos.x = X;
                        tmp_param.end_pos.y = Y;
                        tmp_param.vector.x = X;
                        tmp_param.vector.y = Y;
                        idparam.insert(idparam.begin(), tmp_param);
                        break;
                    }
                }

                for (v = idparam.begin(); v != idparam.end(); ++v)
                {
                    grid.id = v -> id;
                    grid.flag = v -> flag;
                    grid.count = v -> count;
                    grid.start_x = v -> start_pos.x;
                    grid.start_y = v -> start_pos.y;
                    grid.tmp_x = v -> tmp_pos.x;
                    grid.tmp_y = v -> tmp_pos.y;
                    grid.end_x = v -> end_pos.x;
                    grid.end_y = v -> end_pos.y;
                    grid.vector_x = v -> vector.x;
                    grid.vector_y = v -> vector.y;

                    //std::cout << "id " << grid.id << "flag " << grid.flag << "x " << grid.end_x << "y " << grid.end_y << std::endl;
                    points.pot_tracking_grid.push_back(grid);
                }

                    for (v = idparam.begin(); v != idparam.end(); ++v)
                    {
                        //std::cout << "v -> flag" << v -> flag << std::endl;
                        if (v -> flag == 0 && v -> id != 0)
                        {
                            idparam.erase (v);
                        }
                    }
            }

        }

        pthread_mutex_unlock(&mutex_target);
        pub->publish(points);
        //std::cout << "visual_end"<<std::endl;
        count++;
        r.sleep();
    }
    return 0;
}

void *Processing( void *ptr )
{
    //  CParticleFilter m_PF;
    CMultipleParticleFilter m_PF;
    //ros::Rate r(30);
    ros::Rate r(30);
    laser.Init();

    //  int area[2]={STAGE_X, STAGE_Y};
    //  m_PF.initialize(area, MAX_PARTICLE_NUM, MAX_PARTICLE_NUM_MCMC);

    /**********************************/
    laser.m_bNodeActive[0] = true;
    laser.m_nConnectNum = 1;
    laser.GetLRFParam();
    laser.m_nStep[0] = laser.m_LRFParam[0].step;
    laser.m_StartAngle[0] = -laser.m_LRFParam[0].viewangle / 2.0;
    laser.m_DivAngle[0] = laser.m_LRFParam[0].divangle;
    /**********************************/

    CvMat *m_Rotate = cvCreateMat(2, 2, CV_64F);
    CvMat *m_Translate = cvCreateMat(2, 1, CV_64F);
    CvMat *Temp = cvCreateMat(2, 1, CV_64F);
    int count;
    double theta, range;

    if (laser.m_bNodeActive[0])
        while (!CallbackCalled) r.sleep();

    if (laser.m_bResetBackRangeData == true)
    {
        for (int it = 0; it < laser.m_ring; it++)
        {
            for (int n = 0; n < laser.m_cnMaxConnect; n++)
            {
                if (laser.m_bNodeActive[n])
                {

                    pthread_mutex_lock(&mutex_laser);

                    laser.m_LRFData[n].clear();
                    laser.m_LRFData[n].resize(scanData.size());
                    for (int i = 0; i < scanData.size(); i++) laser.m_LRFData[n][i] = scanData[i];

                    pthread_mutex_unlock(&mutex_laser);

                }
            }
            //      laser.GetBackLRFData();
            laser.GetBackLRFDataGaussian();
            r.sleep();
        }
        laser.m_bResetBackRangeData = false;
        std::cout << "Back range data is stored" << std::endl;
    }

    int iteration = 0;
    while (ros::ok())
    {
        if (laser.m_bResetBackRangeData == false)
        {
            for (int n = 0; n < laser.m_cnMaxConnect; n++)
            {
                if (laser.m_bNodeActive[n])
                {

                    pthread_mutex_lock(&mutex_laser);

                    laser.m_LRFData[n].clear();
                    laser.m_LRFData[n].resize(scanData.size());
                    for (int i = 0; i < scanData.size(); i++)
                    {
                        laser.m_LRFData[n][i] = scanData[i];
                    }

                    pthread_mutex_unlock(&mutex_laser);

                    laser.GetDiffLRFCluster(n);

                    cvmSet(m_Rotate, 0, 0, cos(deg2rad(laser.m_LRFParam[n].rz)));
                    cvmSet(m_Rotate, 0, 1, -sin(deg2rad(laser.m_LRFParam[n].rz)));
                    cvmSet(m_Rotate, 1, 0, sin(deg2rad(laser.m_LRFParam[n].rz)));
                    cvmSet(m_Rotate, 1, 1, cos(deg2rad(laser.m_LRFParam[n].rz)));
                    cvmSet(m_Translate, 0, 0, laser.m_LRFParam[n].tx);
                    cvmSet(m_Translate, 1, 0, laser.m_LRFParam[n].ty);

                    laser.m_LRFPoints[n].clear();
                    laser.m_LRFPoints[n].resize(laser.m_DiffLRFData[n].size());

                    for ( int i = 0; i < laser.m_DiffLRFData[n].size(); i++)
                    {
                        count = laser.m_DiffLRFData[n][i].n;
                        range = laser.m_DiffLRFData[n][i].range;
                        theta = laser.m_DivAngle[0] * count + laser.m_StartAngle[0];

                        cvmSet(laser.m_LRFPos[n][i], 0, 0, range * cos(deg2rad(theta)));
                        cvmSet(laser.m_LRFPos[n][i], 1, 0, range * sin(deg2rad(theta)));
                        cvmMul(m_Rotate, laser.m_LRFPos[n][i], Temp);    //
                        cvmAdd(m_Translate, Temp, laser.m_LRFPos[n][i]);  //
                        laser.m_LRFPoints[n][i].x = cvmGet(laser.m_LRFPos[n][i], 0, 0) * 1000.0;
                        laser.m_LRFPoints[n][i].y = cvmGet(laser.m_LRFPos[n][i], 1, 0) * 1000.0;
                    }

                    // Number of clusters
                    // std::cout << "Number of clusters " << laser.m_LRFClsData[n].size() << std::endl;

                    laser.m_LRFClsPoints[n].clear();
                    laser.m_LRFClsPoints[n].resize(laser.m_LRFClsData[n].size());
                    for (int i = 0; i < laser.m_LRFClsData[n].size(); i++)
                    {
                        count = laser.m_LRFClsData[n][i].n;
                        range = laser.m_LRFClsData[n][i].range;
                        theta = laser.m_DivAngle[0] * count + laser.m_StartAngle[0];

                        cvmSet(laser.m_LRFClsPos[n][i], 0, 0, range * cos(deg2rad(theta)));
                        cvmSet(laser.m_LRFClsPos[n][i], 1, 0, range * sin(deg2rad(theta)));
                        cvmMul(m_Rotate, laser.m_LRFClsPos[n][i], Temp);    //
                        cvmAdd(m_Translate, Temp, laser.m_LRFClsPos[n][i]);  //
                        laser.m_LRFClsPoints[n][i].x = cvmGet(laser.m_LRFClsPos[n][i], 0, 0) * 1000.0;
                        laser.m_LRFClsPoints[n][i].y = cvmGet(laser.m_LRFClsPos[n][i], 1, 0) * 1000.0;

                        //std::cout << laser.m_LRFClsPoints[n][i].x << " " << laser.m_LRFClsPoints[n][i].y << std::endl;

                    }
                }
            }
        }
        pthread_mutex_lock(&mutex_target);
        m_PF.update(&laser);
        pthread_mutex_unlock(&mutex_target);

        ros::Time begin = ros::Time::now();
        if (m_PF.m_ParticleFilter.size() > 0) std::cout << "Time " << begin << " Number of PFs " << m_PF.m_ParticleFilter.size() << std::endl;

        if (!(iteration % 100)) laser.GetBackLRFDataGaussian();

        r.sleep();
        iteration ++;
    }

    cvReleaseMat(&Temp);
    cvReleaseMat(&m_Rotate);
    cvReleaseMat(&m_Translate);

}

void LaserSensingCallback(const sensor_msgs::LaserScan::ConstPtr &scan)
{
    pthread_mutex_lock(&mutex_laser);
    int num = floor((scan->angle_max - scan->angle_min) / scan->angle_increment);

    if ( scanData.size() == 0 ) scanData.resize(num);

    for (int i = 0; i < num ; i++)
    {
        if (isnan(scan->ranges[i]) == 0)
        {
            scanData[i] = scan->ranges[i];
        }
        else
        {
            scanData[i] = 5.6;
        }
    }
    pthread_mutex_unlock(&mutex_laser);
    CallbackCalled = true;
}

int main( int argc, char **argv )
{
    std::cout << "tracker_start" << std::endl;
    pthread_t thread_p;
    pthread_t thread_v;
    ros::MultiThreadedSpinner spinner(0);

    ros::init(argc, argv, "pot_tracker_msg");
    ros::NodeHandle n;
    ros::Publisher  pub = n.advertise<tms_msg_ss::pot_tracking_points>("tracking_point_inf", 10);
    ros::Subscriber sub = n.subscribe("/LaserTracker0", 1000, LaserSensingCallback);
    if ( pthread_create( &thread_v, NULL, Visualization, (void *)&pub) )
    {
        printf("error creating thread.");
        abort();
    }

    if ( pthread_create( &thread_p, NULL, Processing, NULL) )
    {
        printf("error creating thread.");
        abort();
    }
    spinner.spin(); // spin() will not return until the node has been shutdown

    ros::waitForShutdown();

    if ( pthread_join( thread_p, NULL) )
    {
        printf("error joining thread.");
        abort();
    }
    if ( pthread_join( thread_v, NULL) )
    {
        printf("error joining thread.");
        abort();
    }

    scanData.clear();

    return 0;
}


text:
#include "Tiling.h"
#include "Stage.h"

#include <Eigen/Core>
using namespace Eigen;

namespace mylib
{
#include <image.h>
}

#include <iostream>
#include <functional>

//#define DEBUG__WRITE_IMAGES
//#define DEBUG__SHOW

#ifdef DEBUG__SHOW
#define SHOW(e) std::cout << "---" << std::endl << #e << " is " << std::endl << (e) << std::endl << "~~~"  << std::endl;
#else
#define SHOW(e)
#endif

#define PANIC(e) do{if(!(e)) error("%s(%d)"ENDL "\tExpression evaluated to false."ENDL "\t%s"ENDL,__FILE__,__LINE__,#e);}while(0)

/// Simple mutex wrapper for scoped locking/unlocking
class AutoLock
{ Mutex *l_;
public:
  AutoLock(Mutex* l):l_(l) {Mutex_Lock(l_);}
  ~AutoLock() {Mutex_Unlock(l_);}
};
// AutoLock lock(lock_);

namespace fetch {
namespace device {

  typedef uint8_t  uint8;
  typedef uint32_t uint32;

  //////////////////////////////////////////////////////////////////////
  //  StageTiling  /////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////

  //  Constructors  ////////////////////////////////////////////////////
  StageTiling::StageTiling(const device::StageTravel &travel,
                           const FieldOfViewGeometry &fov,
                           const Mode                 alignment)
    :
      attr_(NULL),
      cursor_(0),
      current_plane_offset_(0),
      sz_plane_nelem_(0),
      latticeToStage_(),
      fov_(fov),
      z_offset_um_(0.0),
      travel_(travel),
      lock_(0),
      mode_(alignment)
  {
    PANIC(lock_=Mutex_Alloc());
    computeLatticeToStageTransform_(fov,alignment);
    initAttr_(computeLatticeExtents_(travel_));
    //markAddressable_(&travel_);
  }

  //  Destructor  /////////////////////////////////////////////////////
  StageTiling::~StageTiling()
  {
    if(attr_) Free_Array(attr_);
    if(lock_) Mutex_Free(lock_);
  }

  //  computeLatticeToStageTransform_  /////////////////////////////////
  //
  //  For an index vector i, compute T, such that T*i are the nodes of
  //  the lattice in stage space.
  //
  //  FOV angle should be between 0 and pi/2 (180 degrees).
  void StageTiling::computeLatticeToStageTransform_
                          (const FieldOfViewGeometry &fov,
                           const Mode                 alignment)
  { latticeToStage_ = TTransform::Identity();
    Vector3f sc = fov.field_size_um_ - fov.overlap_um_;
    switch(alignment)
    {
// should probably do the zoffset before rotate/shear but
// they're orthogonal to z so it doesn't matter.
    case Mode::Stage_TilingMode_PixelAligned:
        // Rotate the lattice
        latticeToStage_
          .rotate( AngleAxis<float>(fov.rotation_radians_,Vector3f::UnitZ()) )
          .translate(Vector3f(0,0,z_offset_um_))
          .scale(sc)
          ;
        SHOW(latticeToStage_.matrix());
        return;
    case Mode::Stage_TilingMode_StageAligned:
        // Shear the lattice
        float th = fov.rotation_radians_;
        latticeToStage_.linear() =
          (Matrix3f() <<
            1.0f/cos(th), -sin(th), 0,
                       0,  cos(th), 0,
                       0,        0, 1).finished();
        latticeToStage_.translate(Vector3f(0,0,z_offset_um_))
                       .scale(sc)
                       ;
        return;
    }
  }

 void StageTiling::set_z_offset_um(f64 z_um)
 { z_offset_um_=z_um;
   computeLatticeToStageTransform_(fov_,mode_);
 }
 void StageTiling::inc_z_offset_um(f64 z_um)
 { z_offset_um_+=z_um;
   computeLatticeToStageTransform_(fov_,mode_);
 }
 f64 StageTiling::z_offset_um()
 { return z_offset_um_;
 }

  //  computeLatticeExtents_  //////////////////////////////////////////
  //
  //  Find the range of indexes that cover the stage.
  //  This is done by applying the inverse latticeToStage_ transform to the
  //    rectangle described by the stage extents, and then finding extreema.
  //  The latticeToStage_ transfrom is adjusted so the minimal extrema is the
  //    origin.  That is, [min extremal] = T(0,0,0).

  mylib::Coordinate* StageTiling::computeLatticeExtents_(const device::StageTravel& travel)
  {
    Matrix<float,8,3> sabox; // vertices of the cube, stage aligned
    sabox << // travel is in mm
         travel.x.min,   travel.y.min,   travel.z.min,
         travel.x.min,   travel.y.max,   travel.z.min,
         travel.x.max,   travel.y.max,   travel.z.min,
         travel.x.max,   travel.y.min,   travel.z.min,

         travel.x.min,   travel.y.min,   travel.z.max,
         travel.x.min,   travel.y.max,   travel.z.max,
         travel.x.max,   travel.y.max,   travel.z.max,
         travel.x.max,   travel.y.min,   travel.z.max;
    sabox *= 1000.0; //mm to um

    Matrix<float,3,8> labox; // vertices of the cube, lattice aligned
    labox.noalias() = latticeToStage_.inverse() * sabox.transpose();

    Vector3f maxs,mins;
    maxs.noalias() = labox.rowwise().maxCoeff();
    mins.noalias() = labox.rowwise().minCoeff();

    latticeToStage_.translate(mins);
    Vector3z c((maxs-mins).unaryExpr(std::ptr_fun<float,float>(ceil)).cast<size_t>());
    SHOW(sabox);
    SHOW(labox);
    SHOW(mins);
    SHOW(maxs);
    SHOW(c);

    mylib::Coordinate* out = mylib::Coord3(c(2)+1,c(1)+1,c(0)+1); //shape of the lattice
    return out;
  }

  //  initAttr_  ///////////////////////////////////////////////////////
  //

  void StageTiling::initAttr_(mylib::Coordinate *shape)
  { AutoLock lock(lock_);
    attr_ = mylib::Make_Array_With_Shape(
      mylib::PLAIN_KIND,
      mylib::UINT32_TYPE,
      shape); // shape gets free'd here

    memset(attr_->data,0,sizeof(uint32_t)*attr_->size); //unset
    sz_plane_nelem_ = attr_->dims[0] * attr_->dims[1];
  }

  //  resetCursor  /////////////////////////////////////////////////////
  //

#define ON_PLANE(e)    (((e)>=current_plane_offset_) && ((e)<(current_plane_offset_ + sz_plane_nelem_)))
#define ON_LATTICE(e)  ((e) < (attr_->size))

  typedef mylib::Dimn_Type Dimn_Type;
  void StageTiling::resetCursor()
  { AutoLock lock(lock_);
    cursor_ = 0;

    uint32_t* mask     = AUINT32(attr_);
    uint32_t  attrmask = Addressable | Safe | Active | Done,
              attr     = Addressable | Safe | Active;

    while( (mask[cursor_] & attrmask) != attr
        && ON_LATTICE(cursor_) )
    {++cursor_;}

    if(ON_LATTICE(cursor_) &&  (mask[cursor_] & attrmask) == attr)
    { mylib::Coordinate *c = mylib::Idx2CoordA(attr_,cursor_);
      current_plane_offset_ = ADIMN(c)[2] * sz_plane_nelem_;
      mylib::Free_Array(c);
      cursor_ -= 1; // so next*Cursor will be the first tile
    } else
      cursor_=0;
  }

  //  setCursorToPlane  ////////////////////////////////////////////////
  //

  /// \todo bounds checking
  void StageTiling::setCursorToPlane(size_t iplane)
  { AutoLock lock(lock_);
    cursor_=current_plane_offset_=iplane*sz_plane_nelem_;
    cursor_--; // always incremented before query, so subtracting one here means first tile will not be skipped
  }

  //  nextInPlanePosition  /////////////////////////////////////////////
  //

  bool StageTiling::nextInPlanePosition(Vector3f &pos)
  { lock();
    uint32_t* mask = AUINT32(attr_);
    uint32_t attrmask = Addressable | Safe | Active | Done,
             attr     = Addressable | Safe | Active;

    do{++cursor_;}
    while( (mask[cursor_] & attrmask) != attr
        && ON_PLANE(cursor_) );

    if(ON_PLANE(cursor_) &&  (mask[cursor_] & attrmask) == attr)
    { pos = computeCursorPos();
      unlock();
      notifyNext(cursor_,pos);
      return true;
    } else
    { unlock();
      return false;
    }
  }

  //  nextInPlane                    /////////////////////////////////////////////
  //
  bool StageTiling::nextInPlaneQuery(Vector3f &pos,uint32_t attrmask,uint32_t attr)
  { lock();
    uint32_t* mask = AUINT32(attr_);
    do{++cursor_;}
    while( (mask[cursor_] & attrmask) != attr
        && ON_PLANE(cursor_) );

    if(ON_PLANE(cursor_) &&  (mask[cursor_] & attrmask) == attr)
    { pos = computeCursorPos();
      unlock();
      notifyNext(cursor_,pos);
      return true;
    } else
    { unlock();
      return false;
    }
  }

  //  nextInPlaneExplorablePosition  /////////////////////////////////////////////
  //

  /** Return the next tile-position to explore in the current tile-plane.

      Exclude tiles that are not Addressable, or that have already been
      marked Active or Done.
  */

  bool StageTiling::nextInPlaneExplorablePosition(Vector3f &pos)
  { lock();
    uint32_t* mask = AUINT32(attr_);
    uint32_t attrmask = Explorable | Safe | Explored | Addressable | Active | Done,
             attr     = Explorable | Safe | Addressable;

    do{++cursor_;}
    while( (mask[cursor_] & attrmask) != attr
        && ON_PLANE(cursor_) );

    if(ON_PLANE(cursor_) &&  (mask[cursor_] & attrmask) == attr)
    { pos = computeCursorPos();
      unlock();
      notifyNext(cursor_,pos);
      return true;
    } else
    { unlock();
      return false;
    }
  }

  //  nextPosition  ////////////////////////////////////////////////////
  //
  bool StageTiling::nextPosition(Vector3f &pos)
  { lock();
    uint32_t* mask    = AUINT32(attr_);
    uint32_t attrmask = Addressable | Safe | Active | Done,
             attr     = Addressable | Safe | Active;

    do {++cursor_;}
    while( (mask[cursor_] & attrmask) != attr
        && ON_LATTICE(cursor_) );

    if(ON_LATTICE(cursor_))
    { pos = computeCursorPos();
      unlock();
      notifyNext(cursor_,pos);
      return true;
    } else
    { unlock();
      return false;
    }
  }

  //  nextSearchPosition  //////////////////////////////////////////////
  //
  // *ctx should be NULL on the first call.  It will be internally managed.

  struct tile_search_parent_t
  { uint32_t *c,dir,n;
  };

    tile_search_history_t::tile_search_history_t():history(0),i(0),n(0){}
    tile_search_history_t::~tile_search_history_t() {if (history) {free(history);}}
    /** Returns 0 on error (memory) */
    int tile_search_history_t::push(uint32_t *c,int dir,int n)
    { if(!request(i+1)) return 0;
      ++i;
      history[i].c  =c;
      history[i].dir=(uint32_t)dir;
      history[i].n  =(uint32_t)n;
      return 1;
    }
    /** Returns 0 on underflow */
    int tile_search_history_t::pop(uint32_t **pc, uint32_t *pdir, uint32_t* pn)
    { if(i<=0) return 0; // zero is never written to, it's reserved for signalling empty
      *pc  =history[i].c;
      *pdir=history[i].dir;
      *pn  =history[i].n;
      --i;
      return 1;
    }
    int tile_search_history_t::pop(uint32_t **pc, int *pdir, int *pn)
    { uint32_t d,n;
      int ret=pop(pc,&d,&n);
      *pdir=d;
      *pn=n;
      return ret;
    }
    /** returns 0 on failure, otherwise 1 */
    int tile_search_history_t::request(size_t  i_)
    { if(i_>=n)
      { size_t oldn=n;
        n=1.2*i_+50;
        history=(tile_search_parent_t*)realloc(history,sizeof(tile_search_parent_t)*n);
        memset(history+oldn,0,sizeof(tile_search_parent_t)*(n-oldn));
      }
      return (history!=NULL);
    }
    void tile_search_history_t::flush() {i=0;}

    TileSearchContext::TileSearchContext(StageTiling *t,int radius/*=0*/) : tiling(t), c(0),n(0),dir(0),mode(0),radius(radius) {}
    TileSearchContext::~TileSearchContext()
    { if(tiling) tiling->tileSearchCleanup(this);
    }
    void TileSearchContext::sync()
    {  c    =AUINT32(tiling->attr_)+tiling->cursor_;
       line =tiling->attr_->dims[0];
       plane=tiling->sz_plane_nelem_;
       n=0;
    }
    void TileSearchContext::set_outline_mode(bool tf/*=true*/) { mode=tf; if(!tf) flush();}
    bool TileSearchContext::is_outline_mode() {return mode;}
    bool TileSearchContext::is_hunt_mode()    {return !mode;}
    uint32_t *TileSearchContext::next_neighbor()
    { int steps[]={-1,-line,1,line};
      uint32_t *p=c+steps[ (dir+n)%4 ];
      ++n;
      if(n<4 && tiling->on_plane(p))
        return p;
      return 0;
    }
    void TileSearchContext::flush() {n=dir=0;history.flush();}
    /** returns 0 on failure, otherwise 1 */
    int TileSearchContext::push(uint32_t* p)
    { if(!history.push(c,dir,n))
        return 0;
      c=p;
      tiling->cursor_=c-AUINT32(tiling->attr_);
      dir=(dir+n-2)%4; // remmber n is the next neighbor, subtract 1 for current, subtract another 1 to start with left turn
      n=0;
      return 1;
    }
    int TileSearchContext::pop()
    { if(!history.pop(&c,&dir,&n))
        return false;
      tiling->cursor_=c-AUINT32(tiling->attr_);
      return true;
    }
#define CHECK(e,flag) ((*(e)&(flag))==(flag))
#define MARK(e,flag)  (*(e)|=(flag))
    bool TileSearchContext::detected() {return CHECK(c,StageTiling::Detected); }
    void TileSearchContext::reserve()  { MARK(c,StageTiling::Reserved); }

  bool StageTiling::on_plane(uint32_t *p)
  { return ON_PLANE(p-AUINT32(attr_));
  }

  void StageTiling::tileSearchCleanup(TileSearchContext *ctx)
  { const uint32_t *beg = AUINT32(attr_)+current_plane_offset_,
                   *end = beg+sz_plane_nelem_;
    int iplane=current_plane_offset_/sz_plane_nelem_;
    lock();
    for(uint32_t *t=(uint32_t*)beg;t<end;++t) // Reset Reserved
      *t = t[0]&~Reserved;
    if(ctx->is_outline_mode())
    { unlock(); // FIXME: possible race condition
      fillHoles(iplane,Detected);
      if(ctx->radius)
        dilate(iplane,ctx->radius,Detected,Explorable,0);
      lock();
      ctx->set_outline_mode(false);
    }
    cursor_=beg-AUINT32(attr_); // reset to start of plane
    // Copy explorable to next plane
    if( (current_plane_offset_/sz_plane_nelem_)<(attr_->dims[2]-1)) // if not last plane
    { uint32_t *c,*n;
      for(c=(uint32_t*)beg,n=(uint32_t*)end;c<end;++c,++n)
        *n|=(*c&Explorable);
    }
    unlock();
  }

#define ELIGABLE(e)          ((*(e)&eligable_mask)==eligable)
#define ALREADY_DETECTED(e)  ((*(e)&(Addressable|Explorable|Detected|Reserved))==(Addressable|Explorable|Detected))
//#define IMPLY_DETECTED(e)    ((*(e)&(Done))==(Done)) | ((*(e)&(Active))==(Active))

  /* Sorry for the goto's.  don't hate. */
  bool StageTiling::nextSearchPosition(int iplane, int radius, Vector3f &pos,TileSearchContext **pctx)
  { const uint32_t eligable_mask = Addressable | Safe | Explorable | Explored /*| Active | Done*/, // Active/Done do not imply detection and we don't want them to
                   eligable      = Addressable | Safe | Explorable,
                  *beg = AUINT32(attr_)+current_plane_offset_,
                  *end = beg+sz_plane_nelem_;
    if(!pctx) return 0;
    TileSearchContext *ctx=*pctx;
    lock();
    if(!ctx)
    { *pctx=ctx=new TileSearchContext(this,radius);
    }
    ctx->sync();
Start:
    if(ctx->detected())
    { ctx->reserve();
      ctx->set_outline_mode();
    }
    if(ctx->is_outline_mode())
    { uint32_t *n;
      if(ctx->detected())
      { while(n=ctx->next_neighbor())
        { if(CHECK(n,Reserved)) // BOOM DONE - the loop is closed
          { goto DoneOutlining;
          }
#if 0 // Actually don't want to infer detected from any other flags
          if(IMPLY_DETECTED(n)) //infer_detected - some flags imply tile is detected
            *n|=Detected;
#endif
          if(ALREADY_DETECTED(n))
          { ctx->push(n); // treat previously detected as ok part of the perimeter
            goto Start;   // don't need to detect again
          }
          if(ELIGABLE(n))
          { ctx->push(n);
            goto Yield;
          }
        }
      }
      if(ctx->pop())      // Back up.  Also part of handling dead end - no neighbors eligable or reserved
        goto Start;
      goto DoneOutlining; // underflow...The found region is just a strip, not a closed loop.
    }
Hunt:
    if(ctx->is_hunt_mode())
    { unlock(); // FIXME: racy
      return nextInPlaneQuery(pos,
        Addressable|Safe|Explorable|Explored|Detected|Active|Done,  // skip explored,detected,active or done tiles.
        Addressable|Safe|Explorable                              );
      lock();
    }
    // ALL DONE
    delete ctx;
    *pctx=0;
    unlock();
    return false;
Yield:
    pos=computeCursorPos();
    unlock();
    notifyNext(cursor_,pos);
    return true;
DoneOutlining:
    unlock(); // FIXME - racy
    tileSearchCleanup(ctx); // this cleans up the outlining and resets to hunt mode
    lock();
    goto Hunt;
  }
#undef CHECK
#undef MARK
#undef ELIGABLE

  //  markDone  ////////////////////////////////////////////////////////
  //
  void StageTiling::markDone(bool success)
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      *m |= Done;
      if(!success)
        *m |= TileError;
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markSafe  ////////////////////////////////////////////////////////
  //
  void StageTiling::markSafe(bool success)
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      *m |= Safe;
      if(!success)
        *m |= TileError;
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markExplored  //////////////////////////////////////////////////////
  //
  void StageTiling::markExplored(bool tf)
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      if(tf)
        *m |= Explored;
      else
        *m &= ~Explored;
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markDetected  //////////////////////////////////////////////////////
  //
  void StageTiling::markDetected(bool tf)
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      if(tf)
        *m |= Detected;
      else
        *m &= ~Detected;
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markActive  ////////////////////////////////////////////////////////
  //
  void StageTiling::markActive()
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      *m |= Active;
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markUserReset  /////////////////////////////////////////////////////
  //
  void StageTiling::markUserReset()
  { uint32_t *m=0;
    { AutoLock lock(lock_);
      m = AUINT32(attr_) + cursor_;
      *m &= ~( Active|Detected|Explored|Explorable|Safe|Done );
    }
    notifyDone(cursor_,computeCursorPos(),*m);
  }

  //  markAddressable  ///////////////////////////////////////////////////
  //
  static inline unsigned in(const Vector3f &a,const Vector3f &b,const Vector3f &v)
  { return (a[0]<v[0]) && (v[0]<b[0])
         &&(a[1]<v[1]) && (v[1]<b[1])
         &&(a[2]<v[2]) && (v[2]<b[2]);
  }
  /** Marks the indicated plane as addressable according to the travel.
  */
  void StageTiling::markAddressable(size_t iplane)
  {
    size_t old = cursor_;
    setCursorToPlane(iplane); // FIXME: chance for another thread to change the cursor...recursive locks not allowed
    AutoLock lock(lock_);
    Vector3f a = Vector3f(travel_.x.min,travel_.y.min,travel_.z.min),
             b = Vector3f(travel_.x.max,travel_.y.max,travel_.z.max);
    uint32_t* v = AUINT32(attr_);
    while(ON_PLANE(++cursor_))
      v[cursor_]|=Addressable*in(a,b,computeCursorPos()*0.001);
    cursor_=old; // restore cursor
  }

  //  anyExplored  ///////////////////////////////////////////////////////////////
  //
  int StageTiling::anyExplored(int iplane)
  {
    setCursorToPlane(iplane);// FIXME: chance for another thread to change the cursor...recursive locks not allowed
    AutoLock lock(lock_);
    uint32_t* mask = AUINT32(attr_);
    uint32_t attrmask = Explorable|Addressable,
             attr     = Explorable|Addressable;

    do{++cursor_;}
    while( (mask[cursor_] & attrmask) != attr
        && ON_PLANE(cursor_) );
    return ON_PLANE(cursor_);
  }

  //  fillHolesInActive  /////////////////////////////////////////////////
  //

  /// Private stack implementation for non-recursive flood fill.
  typedef struct _stack_t
  { size_t     n,cap;
    uint32_t **data;
  } stack_t;
  static void grow(stack_t *s)
  { if(s->n==s->cap-1)
    { size_t newsize = s->cap*1.2+50;
      Guarded_Realloc((void**)&s->data,newsize,"grow stack");
      memset(s->data+s->cap,0,(newsize-s->cap)*sizeof(uint32_t*));
      s->cap=newsize;
    }
  }
  static void push(stack_t *s, uint32_t* v)
  { grow(s);
    s->data[s->n++] = v;
  }
  static uint32_t* pop(stack_t *s)
  { return s->data[--s->n];
  }
  static stack_t make_stack(size_t reserve)
  { stack_t s;
    s.n=0;
    s.data=(uint32_t**)Guarded_Calloc(s.cap=reserve,sizeof(uint32_t*),"make stack");
    return s;
  }
  static void destroy_stack(stack_t *s)
  { if(s && s->data) free(s->data);
  }

  /**
    Looks at tiles in this plane and the previous plane for detection events in
    order to determine whether tiles in the plane should be marked Active

    \returns 1 if any tiles were marked active, otherwise 0.
  */
  int StageTiling::updateActive(size_t iplane)
  { int any=0;
    setCursorToPlane(iplane);// FIXME: chance for another thread to change the cursor...recursive locks not allowed
    AutoLock lock(lock_);
    uint32_t *c,*p,
             *beg  = AUINT32(attr_)+current_plane_offset_,
             *end  = beg+sz_plane_nelem_,
             *prev = beg-sz_plane_nelem_;
    #define DETECTED(e) ((*(e)&Detected)==Detected)
    for(c=beg,p=prev;c<end;c++,p++)
    { if( DETECTED(c) || ((iplane>0)?DETECTED(p):0) )
      { *c |= Active;
        any=1;
      }
    }
    #undef DETECTED
    return any;
  }

  /** Fill holes in regions marked as active

    Filled regions are 4-connected.
  */
  void StageTiling::fillHolesInActive(size_t iplane)
  { fillHoles(iplane,Active);}

  void StageTiling::fillHoles(size_t iplane, StageTiling::Flags flag)
  {
    setCursorToPlane(iplane);// FIXME: chance for another thread to change the cursor...recursive locks not allowed
    AutoLock lock(lock_);
    uint32_t *c,
             *beg = AUINT32(attr_)+current_plane_offset_,
             *end = beg+sz_plane_nelem_;
    int is_open=0;
    const unsigned w=attr_->dims[0],
                   h=attr_->dims[1];
    stack_t stack = make_stack(sz_plane_nelem_);
    for(c=beg;c<end;)
    { uint32 *n,*next;
      uint32 mask = flag | Reserved;
      // mark connected and do bounds test for region
      is_open=0;
      push(&stack,0); // push 0 to detect underflow when the fill is done
      push(&stack,c);
      while(n=pop(&stack))
      {   unsigned x = (n-beg)%w,
                   y = (n-beg)/w;
#if 0
          debug("%3d %3d %15s %15s %15s %15s\n",x,y,
                (n[0]&Reserved)?"Reserved":".",
                (n[0]&flag)?"flag":".",
                (n[0]&Explorable)?"Explorable":".",
                (n[0]&Addressable)?"Addressable":".");
#endif
          *n |= Reserved;
          is_open |= ((x==0)||(x==w-1)||(y==0)||(y==h-1)); // is the region connected to the plane bounds?
          if(!(y>=(h-1) || *(next=(n+w))&mask )) {*next|=Reserved; push(&stack,next);}  // down
          if(!(y<=0     || *(next=(n-w))&mask )) {*next|=Reserved; push(&stack,next);}  // up
          if(!(x<=0     || *(next=(n-1))&mask )) {*next|=Reserved; push(&stack,next);}  // left
          if(!(x>=(w-1) || *(next=(n+1))&mask )) {*next|=Reserved; push(&stack,next);}  // right
      } // end first fill
      if(!is_open)                             // second fill to mark interior as flag
      { mask = flag;                         // edges and self are labeled flag
        push(&stack,0);
        push(&stack,c);
        while(n=pop(&stack))
        {   unsigned x = (n-beg)%w,
                     y = (n-beg)/w;
#if 0
            debug("%3d %3d %15s %15s %15s %15s\n",x,y,
                (n[0]&Reserved)?"Reserved":".",
                (n[0]&flag)?"flag":".",
                (n[0]&Explorable)?"Explorable":".",
                (n[0]&Addressable)?"Addressable":".");
#endif
            *n |= flag;
            if(!(y>=(h-1) || *(next=(n+w))&mask )) {*next|=flag; push(&stack,next);}  // down
            if(!(y<=0     || *(next=(n-w))&mask )) {*next|=flag; push(&stack,next);}  // up
            if(!(x<=0     || *(next=(n-1))&mask )) {*next|=flag; push(&stack,next);}  // left
            if(!(x>=(w-1) || *(next=(n+1))&mask )) {*next|=flag; push(&stack,next);}  // right
        } // end second fill
      }

      while(c++<end && *c&(Reserved|flag));  // move to next unreserved
    } // done searching for regions
    destroy_stack(&stack);
    for(c=beg;c<end;++c)                       // mark all unreserved
      *c = c[0]&~Reserved;
  }

  //  dilateActive  //////////////////////////////////////////////////////
  //
  #define countof(e) (sizeof(e)/sizeof(*e))
  /** Mark tiles as Active if they are 8-connected to an Active tile. */
  void StageTiling::dilateActive(size_t iplane)
  { dilate(iplane,1,Active,Active,1 /*restrict to explorable */);
  }

  // dilate         //////////////////////////////////////////////////////
  //
  // Does not dilate into Done tiles.
  // Optionally restricts dilation to explorable tiles.
  //
  //
  void StageTiling::dilate(size_t iplane, int n, StageTiling::Flags query_flag, StageTiling::Flags write_flag, int explorable_only)
  {
    setCursorToPlane(iplane); // FIXME: chance for another thread to change the cursor...recursive locks not allowed
    AutoLock lock(lock_);
    uint32_t *c,
             *beg = AUINT32(attr_)+current_plane_offset_,
             *end = beg+sz_plane_nelem_;
    const unsigned w=attr_->dims[0],
                   h=attr_->dims[1];
    unsigned       x,y,j;

    const int offsets[] = {-w-1,-w,-w+1,-1,1,w-1,w,w+1};
    const unsigned top=1,left=2,bot=4,right=8; // bit flags
#define MAYBE_EXPLORABLE ((explorable_only)?Explorable:0)
    const unsigned masks[]   = {top|left,top,top|right,left,right,bot|left,bot,bot|right};
    const unsigned attrmask = Reserved|Safe|Addressable|Done|MAYBE_EXPLORABLE,            // attr is the neighbor query
                   attr     = Reserved|Safe|Addressable     |MAYBE_EXPLORABLE,
                   lblmask  = Addressable|MAYBE_EXPLORABLE;                          // lblmask selects for valid write points
#undef MAYBE_EXPLORABLE
    for(c=beg;c<end;++c)                             // mark original active tiles as reserved
      *c |= ((*c&query_flag)==query_flag)*Reserved;  // this way only the originally labelled tiles will be dilated from
    while(n-->0)
    { for(y=0;y<h;++y)
      { unsigned rowmask = ((y==0)*top)|((y==h-1)*bot);
        for(x=0;x<w;++x)
        { const unsigned colmask = ((x==0)*left)|((x==w-1)*right),
                            mask = rowmask|colmask;
          c=beg+y*w+x;
          if((*c&lblmask)==lblmask)                // mark only tile that are addressable and explorable
            for(j=0;j<countof(offsets);++j)
              if(  (mask&masks[j])==0              // is neighbor in bounds
                && (c[offsets[j]]&attrmask)==attr) // query neighbor attribute for match
              { *c|=(write_flag|Reserved2); break;
              }
        }
      }
      for(c=beg;c<end;++c)                     // make query transitive over dilation radius
        if(*c&Reserved2)
        { *c|=Reserved;
          *c = c[0]&~Reserved2;
        }
    }
    for(c=beg;c<end;++c)                       // mark all unreserved
      *c = c[0]&~Reserved;
  }

  // minDistTo ///////////////////////////////////////////////////////////////
  //
  // returns -1 on error, otherwise
  //         the lattice distance from the current tile to the nearest tile
  //         in plane satisfying the query.
  //
  // Algorithm is breadth first search.  So it requires a FIFO queue.
  //
  // NOT THREAD SAFE
  // - right now this is only called by AdaptiveTilingTask
  // - to make it thread safe
  //   - make estore and friends non-static
  //   or
  //   - protext estore and friends
  //   - deallocation has to track which elements are used and which are free
  //   - occasionally repack estore
  //

  class q_t
  { typedef struct e_t_ {int dist; uint32_t *tile; struct e_t_* next;}* e_t;
    e_t head,tail;

    // block allocate elements
    // - have to do this or lock's during free (called by ~q_t()) get too time consuming
    e_t estore;
    size_t estore_sz;
    size_t estore_i;
    e_t elem() { // alloc new element
      estore_i++;
      if(estore_i>=estore_sz)
        return 0;
      return estore+(estore_i-1);
    }
    void free_elem(e_t e) { /* release element -- no op */ }
    e_t bind(uint32_t* v,int dist) {
      e_t e=elem();
      if(!e) return 0;
      e->tile=v; e->next=NULL; e->dist=dist;
      return e;
    }
  public:
    q_t(size_t n):head(0),tail(0),estore(0),estore_sz(n),estore_i(0) {estore=(e_t)calloc(n,sizeof(struct e_t_));}
    ~q_t() { free(estore); } //e_t e=head; while(e) {e_t t=e->next; free_elem(e); e=t; } estore_i=0;}
    q_t* push(uint32_t* v, int dist) throw(const char*) {
      e_t e=0;
      if(!v) return this; // no-op -- to allow implicit filtering of inputs
      e=bind(v,dist);
      if(!e) throw "allocation error";    // memory allocation error
      if(!head) { head=tail=e; }          // first elem. must test head bc of how I pop
      else      { tail->next=e; tail=e;}
      return this;
    }
    uint32_t* pop(int *dist) {
      uint32_t* v=0;
      int d=-1;
      e_t e=head;
      if(head) { head=head->next; v=e->tile; d=e->dist; free_elem(e);}
      if(dist) *dist=d;
      return v;
    }
  };

  int StageTiling::minDistTo(
    uint32_t search_mask,uint32_t search_flags, // area to search
    uint32_t query_mask,uint32_t query_flags)  // tile to find
  {
    int dist=0;
    const unsigned w=attr_->dims[0],
                   h=attr_->dims[1];
    const int offsets[] = {-w-1,-w,-w+1,-1,1,w-1,w,w+1}; // moves
    uint32_t *c = AUINT32(attr_)+cursor_,
             *beg = AUINT32(attr_)+current_plane_offset_,
             *end = beg+sz_plane_nelem_;
    q_t q(w*h);

    for(uint32_t *t=(uint32_t*)beg;t<end;++t) // Reset Reserved
      *t = t[0]&~Reserved;

    #define isvalid(p)    ((*(p)&(search_mask|Reserved)) == search_flags)
    #define isinbounds(p) (beg<=(p) && (p)<end)
    #define maybe(p)      ( (isvalid(p)&&isinbounds(p)) ?(p):NULL)
    try
    { q.push(maybe(c),0);
      while(c=q.pop(&dist))
      { *c |= Reserved; // mark it as looked at
        if((*c&query_mask)==query_flags) {goto Finalize;}
        for(int i=0;i<countof(offsets);++i)
          q.push(maybe(c+offsets[i]),dist+1);
      }
      dist=0; // - no tiles found or started in a bad spot
    }
    catch(const char* msg)
    { debug("%s(%d): %s()\r\n\t%s\r\n",__FILE__,__LINE__,__FUNCTION__,msg);
      dist = -1;
    }
    #undef isvalid
    #undef isinbounds
    #undef maybe
  Finalize:
    for(uint32_t *t=(uint32_t*)beg;t<end;++t) // Reset Reserved
      *t = t[0]&~Reserved;
    return dist;
  }

  void StageTiling::notifyDone(size_t index, const Vector3f& pos, uint32_t sts)
  { TListeners::iterator i;
    for(i=listeners_.begin();i!=listeners_.end();++i)
      (*i)->tile_done(index,pos,sts);
  }

  void StageTiling::notifyNext(size_t index, const Vector3f& pos)
  { TListeners::iterator i;
    for(i=listeners_.begin();i!=listeners_.end();++i)
      (*i)->tile_next(index,pos);
  }

  const Vector3f StageTiling::computeCursorPos()
  {
    mylib::Coordinate *c = mylib::Idx2CoordA(attr_,cursor_);
    mylib::Dimn_Type *d = (mylib::Dimn_Type*)ADIMN(c);
    Vector3z r;
    r << d[0],d[1],d[2];
    Vector3f pos = latticeToStage_ * r.transpose().cast<float>();
    Free_Array(c);
    return pos;
  }

  float StageTiling::plane_mm()
  {
    Vector3f r(0,0,(float)plane());
    r = latticeToStageTransform() * r * 0.001;
    return r(2);
  }

}} // end namespace fetch::device

max_stars_repo_name: TeravoxelTwoPhotonTomography/fetch

max_issues_repo_name: TeravoxelTwoPhotonTomography/fetch

max_forks_repo_name: TeravoxelTwoPhotonTomography/fetch


text:
#pragma once

// ref: https://boost-ext.github.io/sml/index.html
// https://boost-ext.github.io/sml/examples.html, hello world
#include <iostream>
#include <iomanip>
#include <functional>
#include <boost/sml.hpp>
#include "CommonDef.h"

using namespace std;
namespace sml = boost::sml;

// used in state machine and callback
struct BtnEnables {
   bool SelectTm;
   bool SetInputStr;
   bool Rewind;
   bool StepBack;
   bool Pause;
   bool StepForward;
   bool Run;
   bool SaveComputation;
}; // end struct

// callback from the state machine
template<typename T>
void SetBtnState(T btn, bool state) {(state == true ? btn->activate() : btn->deactivate());}

// anonymous namespace
namespace {

// events
struct eInit {};
struct eSelectTm {AppStatus status;};
struct eSetInput {AppStatus status;};
struct eTmReady {AppStatus status;};
struct ePause {AppStatus status;};
struct eLoop {AppStatus status;};
struct eStepForward {AppStatus status;};
struct eStepBackward {AppStatus status;};
struct eRewind {AppStatus status;};
struct eHalt {AppStatus status;};

// for this implementation, states are just empty classes
class Idle;
class SetTm;
class SetString;
class Paused;
class Running;
class Halt;

// transition table
// example: src_state +event<>[guard] / action = dst_state,
// transition from src_state to dst_state on event with guard and action
class tmsim_control_enables {
   using self = tmsim_control_enables;
public:

   tmsim_control_enables() {
      AllOff();
   } // end ctor

   int SetStateMachineCB(std::function<void(const BtnEnables &)> cb){
      int ret = 0;
      _cb = cb;
      return ret;
   } // end SetStateMachineCB

   int SetHasHistoryCB(std::function<bool(void)> hasHistory){
      int ret = 0;
      _hasHistory = hasHistory;
      return ret;
   } // end SetHasHistoryCB

   auto operator()()  {
      using namespace sml;

      // guards
      auto validTm = [] (const auto &event) -> bool {
         return event.status.validTm;
      }; // end validTm

      auto validString = [] (const auto &event) -> bool {
         return event.status.validInput;
      }; // end validString

      auto inProgress = [] (const auto &event) -> bool {
         return event.status.tm == TmStatus::InProgress;
      }; // end inProgress

      auto ready = [] (const auto &event) -> bool {
         return event.status.tm == TmStatus::Ready;
      }; // end inProgress

      auto halt = [] (const auto &event) -> bool {
         return event.status.complete;
      }; // end halt

      return make_transition_table (

// example: src_state + event<eEvent>[guard] / action = dst_state,

         *state<Idle> + event<eInit> / [] {cout << "SetTm\n"; } = state<SetTm>,
         state<SetTm> + event<eSelectTm>[validTm] / [] {cout << "SetString\n"; } = state<SetString>,
         state<SetString> + event<eSetInput>[validString] / [] {cout << "Paused\n"; } = state<Paused>,

         state<Paused> + event<eLoop>[(ready || inProgress)] / [] {cout << "Running\n"; } = state<Running>,
         state<Paused> + event<eStepForward>[inProgress] / [] {cout << "Paused\n"; } = state<Paused>,
         state<Paused> + event<eStepBackward>[inProgress] / [] {cout << "Paused\n"; } = state<Paused>,
         state<Paused> + event<ePause> / [] {cout << "Paused\n"; } = state<Paused>,

         state<Running> + event<eLoop>[inProgress] / [] {cout << "Running\n"; } = state<Running>,
         state<Running> + event<ePause>[inProgress] / [] {cout << "Paused\n"; } = state<Paused>,
         state<Running> + event<eLoop>[inProgress] / [] {cout << "Running\n"; } = state<Running>,
         state<Running> + event<eHalt>[halt] / [] {cout << "Paused\n"; } = state<Paused>,

         state<Halt> + event<eRewind> / [] {cout << "Paused\n"; } = state<Paused>,
         state<Halt> + event<eStepBackward> / [] {cout << "Paused\n"; } = state<Paused>,

         state<SetTm> + sml::on_entry<sml::back::_> / [&] { setTmAction(); },
         state<SetString> + sml::on_entry<sml::back::_> / [&] { setStringAction();},
         state<Paused> + sml::on_entry<sml::back::_> / [&] { pausedAction(); },
         state<Running> + sml::on_entry<sml::back::_> / [&] { runningAction(); },
         state<Halt> + sml::on_entry<sml::back::_> / [&] { haltAction(); }

      );

   } // end operator()

private:

   BtnEnables _be;
   std::function<void(const BtnEnables &)> _cb;
   std::function<bool(void)> _hasHistory;

   void AllOff() {
      _be.SelectTm = false;
      _be.SetInputStr = false;
      _be.Rewind = false;
      _be.StepBack = false;
      _be.Pause = false;
      _be.StepForward = false;
      _be.Run = false;
      _be.SaveComputation = false;
   } // end DisableGroupControlBtns

   void setTmAction(){
      AllOff();
      _be.SelectTm = true;
      _cb(_be);
   } // end setTmAction

   void setStringAction(){
      AllOff();
      _be.SelectTm = true;
      _be.SetInputStr = true;
      _be.SaveComputation = true;
      _cb(_be);
   } // end setStringAction

   void pausedAction(){
      AllOff();
      _be.SelectTm = true;
      _be.SetInputStr = true;
      _be.Run = true;
      _be.StepForward = true;
      _be.SaveComputation = true;

      if(_hasHistory()) {
         _be.Rewind = true;
         _be.StepBack = true;
      } // end if

      _cb(_be);
   } // end pausedAction

   void runningAction(){
      AllOff();
      _be.Pause = true;
      _cb(_be);
   } // end runningAction

   void haltAction(){
      AllOff();

      if(_hasHistory()) {
         _be.Rewind = true;
         _be.StepBack = true;
      } // end if

      _be.SaveComputation = true;
      _cb(_be);
   } // end haltAction

}; // end struct

} // end anonymous namespace


text:
////#include "../TraceSimilarity/interface.h"
//#include <boost/asio.hpp>
//#include <windows.h>
//#include <string>
//#include <time.h>
//#include <vector>
//#include <boost/bind.hpp>
//#include <iostream>
//#include "xNES.h"
//#pragma comment(lib, "WS2_32")
//
//using namespace std;
//
////#define UNICODE
//
//#define RESULTPORT 15777
//#define REQUESTPORT 15777
//#define PARAMPORT 15778
//#define IP "127.0.0.1"
//#define MAX_BUFFER 8192
//
//using namespace boost::asio;
//
//char SendBuffer[MAX_BUFFER];
//char ReceiveBuffer[MAX_BUFFER];
//
//typedef std::function<void(struct Boost_Sock *, char *, size_t)> MSGHANDLER;
//boost::asio::io_service ioservice;
//ip::tcp::socket sock(ioservice);
//
//struct paramop_msg {
//	char op[256];
//	paramop_msg() {
//		memset(op, '\0', 256);
//	}
//};
//
//struct Boost_Sock {
//	boost::asio::ip::tcp::socket sock;
//	boost::asio::ip::tcp::endpoint ep;
//	std::string ip;
//	std::string name;
//	unsigned short port;
//	size_t max_buffer;
//	MSGHANDLER handler;
//	Boost_Sock(std::string ip, unsigned short port, MSGHANDLER msghandler = nullptr, std::string name = "") :ip(ip), port(port), sock(ioservice)
//		, ep(boost::asio::ip::address::from_string(ip), port), handler(msghandler), name(name) {
//	}
//	void send_str(const char * str, size_t len) {
//		using namespace boost::asio;
//		if (sock.send(buffer(str, len)) == SOCKET_ERROR)
//		{
//			cout << "Send Data Error::" << GetLastError() << endl;
//		}
//	}
//	void msg_loop() {
//		using namespace boost::asio;
//		try {
//			boost::system::error_code error;
//			sock.connect(ep, error);
//			if (error == boost::asio::error::connection_refused) {
//				cout << "No Remote Server At: " << this->name << endl;
//				return;
//			}
//		}
//		catch (...) {
//
//		}
//		int bytes = 0;
//		while (true)
//		{
//			//if ((bytes = sock.receive(buffer(ReceiveBuffer))) == SOCKET_ERROR)
//			//{
//			//	printf("recv error!\n"); exit(-1);
//			//}
//			boost::system::error_code error;
//			bytes = sock.read_some(buffer(ReceiveBuffer), error);
//			if (error == boost::asio::error::eof || error == boost::asio::error::shut_down || error == boost::asio::error::connection_aborted || error == boost::asio::error::connection_reset) {
//				sock.close();
//				return; // Connection closed cleanly by peer.
//			}
//			if (this->handler == nullptr) {
//				ReceiveBuffer[bytes] = '\0';
//				printf("%s\n", ReceiveBuffer);
//			}
//			else {
//				this->handler(this, ReceiveBuffer, bytes);
//			}
//			//char IPdotdec[20];inet_ntop(AF_INET, 0, IPdotdec, 16); printf("Message from %s:%s\n", inet_ntoa(clientAddr.sin_addr), ReceiveBuffer); //deprecated
//		}
//	}
//private:
//	char ReceiveBuffer[MAX_BUFFER];
//};
//
//void send_param_message(const paramop_msg & msg) {
//	int bytes = 0;
//	boost::system::error_code error;
//	//strncpy(SendBuffer, msg.c_str(), msg.size());
//	strncpy(SendBuffer, (char*)&msg, sizeof(msg));
//	if (sock.write_some(buffer(SendBuffer, sizeof(msg))) == SOCKET_ERROR)
//	{
//		cout << "Param Optimizer Error: " << GetLastError() << endl;
//	}
//	bytes = sock.read_some(buffer(ReceiveBuffer), error);
//	if (error == boost::asio::error::eof || error == boost::asio::error::shut_down || error == boost::asio::error::connection_aborted || error == boost::asio::error::connection_reset) {
//		sock.close();
//		return; // Connection closed cleanly by peer.
//	}
//	printf("Param Optimizer Finished: %s\n", ReceiveBuffer);
//}
//
//void init_param_server(int port = PARAMPORT) {
//	using namespace std;
//	ip::tcp::acceptor acceptor(ioservice, ip::tcp::endpoint(ip::tcp::v4(), PARAMPORT));
//	acceptor.accept(sock);
//	//int bytes = read(sock, buffer(ReceiveBuffer), boost::bind(send_param_message, ReceiveBuffer, _1, _2));
//	//std::string msg(buff, bytes);
//	//sock.write_some(buffer(msg));
//	return;
//}
//
//int wmain(int argc, TCHAR* argv[], TCHAR* env[]) {
//	//while (true) {
//	cout << "Listening" << endl;
//	init_param_server();
//	paramop_msg pm;
//	strcpy(pm.op, "rate, 0.55, 0.9");
//	send_param_message(pm);
//	cout << "Connection End" << endl;
//	//}
//	system("pause");
//	return 0;
//}
//
//
//void return_server() {
//	//	WSADATA wsaData;
//	//	// init Winsock.dll
//	//	if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
//	//	{
//	//		printf("fail to init winsock.dll!\n");
//	//		exit(-1);
//	//	}
//	//	// creat socket
//	//	SOCKET servSoc;
//	//	// SOCK_STREAM is TCP
//	//	if ((servSoc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
//	//	{
//	//		printf("create socket error!\n");
//	//		exit(-1);
//	//	}
//	//
//	//	struct sockaddr_in servAddr;
//	//	memset(&servAddr, 0, sizeof(sockaddr_in));
//	//	servAddr.sin_family = AF_INET;
//	//	servAddr.sin_port = htons(RESULTPORT);
//	//	servAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//	//
//	//	// bind addr
//	//	if (bind(servSoc, (sockaddr*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
//	//	{
//	//		printf("bind error! port:%d\n", RESULTPORT);
//	//		exit(-1);
//	//	}
//	//	// max connection = 2
//	//	if (listen(servSoc, 2) == SOCKET_ERROR)
//	//	{
//	//		printf("listen error!\n");
//	//		exit(-1);
//	//	}
//	//	printf("Server %d is listening...\n", RESULTPORT);
//	//
//	//	SOCKET clientSoc;
//	//	struct sockaddr_in clientAddr;
//	//	memset(&clientAddr, 0, sizeof(clientAddr));
//	//	int addrlen = sizeof(clientAddr);
//	//	// accept
//	//	if ((clientSoc = accept(servSoc, (sockaddr*)&clientAddr, &addrlen)) == INVALID_SOCKET)
//	//	{
//	//		printf("accept error!\n");
//	//		exit(-1);
//	//	}
//	//	printf("Accept connection from %s\n", inet_ntoa(clientAddr.sin_addr));
//	//	char SendBuffer[] = "Message Received.";
//	//	char ReceiveBuffer[MAX_BUFFER];
//	//	while (1)
//	//	{
//	//		int bytes;
//	//		if ((bytes = recv(clientSoc, ReceiveBuffer, sizeof(ReceiveBuffer), 0)) == SOCKET_ERROR)
//	//		{
//	//			printf("recv error!\n");
//	//			exit(-1);
//	//		}
//	//		ReceiveBuffer[bytes] = '\0';
//	//		printf("Message from %s:%s\n", inet_ntoa(clientAddr.sin_addr), ReceiveBuffer);
//	//		if (send(clientSoc, SendBuffer, bytes, 0) == SOCKET_ERROR)
//	//		{
//	//			printf("send error!\n");
//	//			exit(-1);
//	//		}
//	//	}
//	//	// clean socket
//	//	WSACleanup();
//}

max_stars_repo_name: CalvinNeo/TraceSimilarity

max_issues_repo_name: CalvinNeo/TraceSimilarity

max_forks_repo_name: CalvinNeo/TraceSimilarity


text:
/*!
@file
Defines `boost::hana::Hashable`.

@copyright Louis Dionne 2016
@copyright Jason Rice 2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_CONCEPT_HASHABLE_HPP
#define BOOST_HANA_CONCEPT_HASHABLE_HPP

#include <boost/hana/fwd/concept/hashable.hpp>

#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/hash.hpp>

BOOST_HANA_NAMESPACE_BEGIN
    template <typename T>
    struct Hashable {
        using Tag = typename tag_of<T>::type;
        static constexpr bool value = !is_default<hash_impl<Tag>>::value;
    };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_HASHABLE_HPP

max_stars_repo_name: EuroLine/nheqminer

max_issues_repo_name: EuroLine/nheqminer

max_forks_repo_name: EuroLine/nheqminer