text:
/**
 * @file       sorting_algorithm.inst.cpp
 * @brief
 * @date       2020-09-19
 * @author     Peter
 * @copyright
 *      Peter of [ThinkSpirit Laboratory](http://thinkspirit.org/)
 *   of [Nanjing University of Information Science & Technology](http://www.nuist.edu.cn/)
 *   all rights reserved
 */

#include "template_instantiation/sorting_algorithm.inst.hpp"

template void std::sort(Iter first, Iter last, BinaryPredict cmp);
template void std::stable_sort(Iter first, Iter last, BinaryPredict cmp);

#include <parallel/algorithm>

void std_parallel_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	std::__parallel::sort(first, last, cmp);
}

void std_parallel_stable_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	std::__parallel::stable_sort(first, last, cmp);
}

#include <cstdlib>

void cqsort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	typedef typename kerbal::iterator::iterator_traits<Iter>::value_type value_type;

	static BinaryPredict * cmp_sta(&cmp); // qsort can not receive lambda with capture list

	cmp_sta = &cmp; // reassign the cmp object

	qsort(&*first, last - first, sizeof(value_type), [](const void * a, const void * b) {
		value_type arg1 = *static_cast<const value_type*>(a);
		value_type arg2 = *static_cast<const value_type*>(b);

		if ((*cmp_sta)(arg1, arg2))
			return -1;
		if ((*cmp_sta)(arg2, arg1))
			return 1;
		return 0;
	});
}

template void kerbal::algorithm::bubble_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::selection_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::heap_sort(Iter first, Iter last, BinaryPredict cmp);
void std_make_heap_then_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	std::make_heap(first, last, cmp);
	std::sort_heap(first, last, cmp);
}

template void kerbal::algorithm::merge_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::inplace_merge_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::stable_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::insertion_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::directly_insertion_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::quick_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::nonrecursive_qsort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::intro_sort(Iter first, Iter last, BinaryPredict cmp);
template void kerbal::algorithm::nonrecursive_intro_sort(Iter first, Iter last, BinaryPredict cmp);

void shell_sort_hibbard_sequence_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	typedef typename kerbal::iterator::iterator_traits<Iter>::difference_type difference_type;
	kerbal::algorithm::shell_sort(first, last, cmp, kerbal::algorithm::shell_sort_hibbard_policy<difference_type>());
}

void shell_sort_minimun_limit_hibbard_sequence_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	typedef typename kerbal::iterator::iterator_traits<Iter>::difference_type difference_type;
	kerbal::algorithm::shell_sort(first, last, cmp, kerbal::algorithm::shell_sort_minimun_limit_hibbard_policy<difference_type>());
}

void shell_sort_reduce_by_half_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	typedef typename kerbal::iterator::iterator_traits<Iter>::difference_type difference_type;
	kerbal::algorithm::shell_sort(first, last, cmp, kerbal::algorithm::shell_sort_reduce_by_half_policy<difference_type>());
}

void shell_sort_q_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	typedef typename kerbal::iterator::iterator_traits<Iter>::difference_type difference_type;
	kerbal::algorithm::shell_sort(first, last, cmp, kerbal::algorithm::shell_sort_q_policy<difference_type>());
}

#include <kerbal/algorithm/sort/contiguously_radix_sort.hpp>

void radix_sort_wrapper(Iter first, Iter last, BinaryPredict)
{
	kerbal::algorithm::detail::contiguously_radix_sort(first, last, kerbal::type_traits::false_type(), std::forward_iterator_tag());
//	kerbal::algorithm::radix_sort(first, last);
}

#include <kerbal/ompalgo/sort/quick_sort.hpp>
#include <kerbal/ompalgo/sort/shell_sort.hpp>

void omp_quick_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	::omp_set_num_threads(4);
	kerbal::ompalgo::quick_sort(first, last, cmp);
}

void omp_shell_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	::omp_set_num_threads(4);
	kerbal::ompalgo::shell_sort(first, last, cmp);
}

#if BOOST_SORT_SUPPORT

template void boost::sort::block_indirect_sort(Iter first, Iter last, BinaryPredict cmp);
template void boost::sort::flat_stable_sort(Iter first, Iter last, BinaryPredict cmp);
template void boost::sort::heap_sort(Iter first, Iter last, BinaryPredict cmp);
template void boost::sort::pdqsort(Iter first, Iter last, BinaryPredict cmp);
template void boost::sort::sample_sort(Iter first, Iter last, BinaryPredict cmp);
template void boost::sort::spinsort(Iter first, Iter last, BinaryPredict cmp);

void boost_spreadsort_wrapper(Iter first, Iter last, BinaryPredict)
{
	boost::sort::spreadsort::spreadsort(first, last);
}

#include <boost/sort/parallel_stable_sort/parallel_stable_sort.hpp>

void boost_parallel_stable_sort_wrapper(Iter first, Iter last, BinaryPredict cmp)
{
	std::cout << omp_get_max_threads() << std::endl;
	boost::sort::parallel_stable_sort(first, last, cmp, omp_get_max_threads());
}

#else

#pragma message "boost::sort not support"

#endif

template void gfx::timsort(Iter first, Iter last, BinaryPredict cmp);

#include <omp.h>

//void parallel_merge(int threads_num, size_t per, int i, int j)
//{
//
//}

template <typename ForwardIterator, typename BinaryPredict>
void omp_inplace_merge(ForwardIterator first, ForwardIterator mid, ForwardIterator last, BinaryPredict cmp)
{
	typedef ForwardIterator iterator;
	typedef typename kerbal::iterator::iterator_traits<iterator>::difference_type difference_type;

	difference_type left_len(kerbal::iterator::distance(first, mid));
	difference_type right_len(kerbal::iterator::distance(mid, last));

	if (left_len == 0) {
		return;
	}
	if (right_len == 0) {
		return;
	}
	if (left_len == 1 && right_len == 1) {
		if (cmp(*mid, *first)) { // *first > *mid
			kerbal::algorithm::iter_swap(first, mid);
		}
		return;
	}

	iterator lmid(first);
	iterator rmid(mid);

	if (left_len >= right_len) {
		lmid = kerbal::iterator::midden_iterator(first, mid);
		rmid = kerbal::algorithm::lower_bound(mid, last, *lmid, cmp);
	} else {
		rmid = kerbal::iterator::midden_iterator(mid, last);
		lmid = kerbal::algorithm::upper_bound(first, mid, *rmid, cmp);
	}
	mid = kerbal::algorithm::rotate(lmid, mid, rmid);

#	pragma omp parallel sections
	{
#		pragma omp section
		{
			kerbal::algorithm::inplace_merge(first, lmid, mid, cmp);
		}
#		pragma omp section
		{
			kerbal::algorithm::inplace_merge(mid, rmid, last, cmp);
		}
	}
}

#include <kerbal/algorithm/sort/msvc_like_intro_sort.hpp>

void freedom_implement(Iter first, Iter last, BinaryPredict cmp)
{
	kerbal::algorithm::msvc_like_intro_sort(first, last, cmp);
}

void multi_sort(Iter first, Iter last, BinaryPredict cmp)
{
	typedef Iter iterator;
	typedef typename kerbal::iterator::iterator_traits<iterator>::difference_type difference_type;

	const difference_type dist(kerbal::iterator::distance(first, last));
	int threads_num = 0;
	difference_type per = 0;

#	pragma omp parallel
	{
#		pragma omp single
		{
			threads_num = omp_get_num_threads();
			per = (dist / threads_num) + (dist % threads_num != 0);
		}
#		pragma omp barrier

		int thrd_id = omp_get_thread_num();
		iterator section_first(kerbal::iterator::next(first, thrd_id * per));
		iterator section_last((thrd_id == threads_num - 1) ? last : kerbal::iterator::next(section_first, per));
		kerbal::algorithm::sort(section_first, section_last, cmp);

	} // omp parallel

	omp_set_nested(6);

	struct re_merge
	{
			iterator first;
			iterator last;
			int threads_num;
			difference_type per;
			BinaryPredict & cmp;

			void operator()(int i, int j)
			{
				if (j - i == 1 or j - i == 0) {
					return;
				}
				int h = (j - i) / 2;
				int m = i + h;

#				pragma omp parallel sections
				{
#					pragma omp section
					{
						(*this)(i, m);
					}
#					pragma omp section
					{
						(*this)(m, j);
					}
				}
				iterator section_first(kerbal::iterator::next(first, i * per));
				iterator section_mid(kerbal::iterator::next(section_first, h * per));
				iterator section_last((j == threads_num - 1) ? last : kerbal::iterator::next(section_mid, (j - m) * per));
				omp_inplace_merge(section_first, section_mid, section_last, cmp);
//				std::inplace_merge(section_first, section_mid, section_last, cmp);
			}
	};

	re_merge re{first, last, threads_num, per, cmp};

//	struct re_merge
//	{
//			iterator first;
//			iterator last;
//			int threads_num;
//			difference_type per;
//			BinaryPredict cmp;
//
//			void operator()(int i, int j)
//			{
//				if (j - i == 1 or j - i == 0) {
//					return;
//				}
//				int h = (j - i) / 2;
//				int m = i + h;
//
//#				pragma omp parallel sections
//				{
//#					pragma omp section
//					{
//						(*this)(i, m);
//					}
//#					pragma omp section
//					{
//						(*this)(m, j);
//					}
//				}
//				iterator section_first(kerbal::iterator::next(first, i * per));
//				iterator section_mid(kerbal::iterator::next(section_first, h * per));
//				iterator section_last((j == threads_num - 1) ? last : kerbal::iterator::next(section_mid, (j - m) * per));
////				kerbal::algorithm::inplace_merge(section_first, section_mid, section_last);
//				std::inplace_merge(section_first, section_mid, section_last, cmp);
//			}
//	};
//
//	re_merge re{first, last, threads_num, per, cmp};

	re(0, threads_num);
}

max_stars_repo_name: WentsingNee/Visual-Sort

max_issues_repo_name: WentsingNee/Visual-Sort

max_forks_repo_name: WentsingNee/Visual-Sort


text:
//  Copyright (c) 2005-2009 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include <saga/saga/error.hpp>
#include <saga/saga/adaptors/instance_data.hpp>
#include <saga/saga/adaptors/packages/stream_cpi_instance_data.hpp>
#include <saga/saga/adaptors/packages/stream_server_cpi_instance_data.hpp>

#include <saga/saga/packages/stream/version.hpp>
#include <saga/impl/packages/stream/stream_serialization.hpp>

#include <saga/impl/packages/stream/stream.hpp>
#include <saga/impl/packages/stream/stream_server.hpp>

///////////////////////////////////////////////////////////////////////////////
// Register the serialization factory type
SAGA_PACKAGE_REGISTER(saga::impl::stream_serialization);

///////////////////////////////////////////////////////////////////////////////
namespace saga { namespace impl
{

    stream_serialization::~stream_serialization()
    {
    }

    std::string
    stream_serialization::serialize(TR1::shared_ptr<saga::impl::object> obj)
    {
        // get the type of the object (has been serialized already)
        saga::object::type type = obj->get_type();
        if (saga::object::Stream != type &&
            saga::object::StreamServer != type)
        {
            SAGA_THROW_VERBATIM(obj.get(), "stream_serialization::serialize: "
                "Unknwon object type", saga::BadParameter);
        }

        SAGA_OSSTREAM strm;
        {
            using namespace boost::serialization;
            using namespace boost::archive;

            // the object actually is a impl::file or impl::directory, so the
            // following cast should succeed
            saga::impl::proxy *proxy = dynamic_cast<saga::impl::proxy *>(obj.get());
            if (NULL == proxy)
            {
                SAGA_THROW_VERBATIM(obj.get(), "stream_serialization::serialize: "
                    "Unknwon object type", saga::BadParameter);
            }

            // save package version
            text_oarchive oa(strm);
            unsigned int version = SAGA_VERSION_PACKAGE_STREAM_FULL;
            oa << make_nvp("version", version);

            if (saga::object::Stream == type) {
            // serialize the stream_cpi_instance data
                typedef saga::adaptors::v1_0::stream_cpi_instance_data
                    instance_data;

            saga::adaptors::instance_data<instance_data> data(proxy);
            std::string url(data->location_.get_url());

                oa << make_nvp("location", url);
            }
            else {
            // saga::object::StreamServer == type: serialize the
            // server_cpi_instance data
                typedef saga::adaptors::v1_0::stream_server_cpi_instance_data
                    instance_data;

            saga::adaptors::instance_data<instance_data> data(proxy);
            std::string url(data->location_.get_url());

                oa << make_nvp("location", url);
            }
        }
        return SAGA_OSSTREAM_GETSTRING(strm);
    }

    TR1::shared_ptr<saga::impl::object>
    stream_serialization::deserialize(saga::session s, saga::object::type type,
        std::string const& data)
    {
        if (saga::object::Stream != type &&
            saga::object::StreamServer != type)
        {
            SAGA_THROW_VERBATIM(s, "stream_serialization::deserialize: "
                "Unknwon object type", saga::BadParameter);
        }

        using namespace boost::serialization;
        using namespace boost::archive;

        SAGA_ISSTREAM strm(data);
        text_iarchive ia(strm);

        // save package version
        unsigned int version = 0;
        ia >> make_nvp("version", version);
        if (!SAGA_VERSION_PACKAGE_STREAM_ISCOMPATIBLE_EX(version))
        {
            SAGA_THROW_VERBATIM(s, "stream_serialization::deserialize: "
                "Deserialization failed: incompatible version of SAGA stream "
                "package module.", saga::NoSuccess);
        }

        TR1::shared_ptr<saga::impl::object> impl;
        if (saga::object::Stream == type) {
        // deserialize the stream_cpi_instance data
        std::string location;

            ia >> make_nvp("location", location);
            impl.reset(new saga::impl::stream(s, location));
        }
        else {
            // saga::object::StreamServer == type: deserialize the
            // server_cpi_instance data
            std::string location;
            // int mode = 0;

            ia >> make_nvp("location", location);
            impl.reset(new saga::impl::server(s, location));
        }

        return impl;
    }

///////////////////////////////////////////////////////////////////////////////
}}    // namespace saga::impl

ext: cpp

max_stars_repo_name: saga-project/saga-cpp

max_issues_repo_name: saga-project/saga-cpp

max_forks_repo_name: saga-project/saga-cpp


text:
#define BOOST_BIND_GLOBAL_PLACEHOLDERS

//它可以让VC在编译时的output窗口中输出程序具体链接了哪些boost库以及链接顺序。
#define BOOST_LIB_DIAGNOSTIC

//告诉boost禁用自动链接。
#define BOOST_ALL_NO_LIB

#define BOOST_PYTHON_STATIC_LIB

//test_class_wrapper.cpp
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "test_class.h"

bool operator==(const B& left, const B& right);

bool operator==(const A& left, const A& right)
{
    if (left.get() != right.get() || left.publicVal != right.publicVal)
        return false;
    if (left.m_vB.size() != right.m_vB.size())
        return false;
    for (size_t i = 0; i < left.m_vB.size(); i ++)
    {
        if (!(left.m_vB[i] == right.m_vB[i]))
            return false;
    }
    return true;
}

bool operator==(const B& left, const B& right)
{
    return (left.pos == right.pos && left.len == right.len);
}

BOOST_PYTHON_MODULE(test_class)
{
    using namespace boost::python;
    class_<A>("A", init<>())                            //如果默认构造函数没有参数，可以省略
        .def(init<int>())                               //其他构造函数
        .def("get", &A::get)                            //成员函数
        .def("set", &A::set)                            //成员函数
        .def("cs", &A::cs)                            //成员函数
        .def_readwrite("publicVal", &A::publicVal)      //数据成员，当然是公共的
        .def_readwrite("vB", &A::m_vB)
        ;
    class_<std::vector<A> >("VecA")
        .def(vector_indexing_suite<std::vector<A> >())
        ;
    class_<B>("B")
        .def_readwrite("pos", &B::pos)
        .def_readwrite("len", &B::len)
        ;
    class_<std::vector<B> >("VecB")
        .def(vector_indexing_suite<std::vector<B> >())
        ;
    def("printA", &printA);
    def("addA", &addA);
    def("accumulate", &accumulate);
}

max_stars_repo_name: demsheng/QtBoostPythonHelloWorld

max_issues_repo_name: demsheng/QtBoostPythonHelloWorld

max_forks_repo_name: demsheng/QtBoostPythonHelloWorld


text:
#include <array>
#include <algorithm>
//#include <iterator>
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <deque>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
//#include <boost/thread.hpp>
#include <boost/program_options.hpp>

#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
//#include <utime.h>
//#include <unistd.h>
//#include <getopt.h>
#include <pcap.h>
//#include <endian.h>
//#include <fcntl.h>

//#define DEBUG_PCAP
//#define DEBUG_ASIO
#define DEBUG_THROUGHPUT

static constexpr uint8_t MARKER_DATA = 0;
static constexpr uint8_t MARKER_ACK = 1;

extern "C"
{
#include "radiotap.h"
}

static constexpr uint16_t DEFAULT_PORT = 8000;

static constexpr size_t MAX_PACKET_SIZE = 4192;
static constexpr size_t MAX_USER_PACKET_SIZE = 1470;

static constexpr size_t DEFAULT_RATE_HZ = 26000000;

// this is the template radiotap header we send packets out with
static constexpr uint8_t RADIOTAP_HEADER_original[] =
{

    0x00, //version
    0x00, //pad
    0x0c, 0x00, // <- radiotap header lengt
    0x04, 0x80, 0x00, 0x00, // <-- bitmap (RATE + TX FLAGS)
    0x22, //rate
    0x0,//padding
    0x18, 0x00
};

std::vector<uint8_t> RADIOTAP_HEADER;

#define SRC_MAC_LASTBYTE 15
#define DST_MAC_LASTBYTE 21

// Penumbra IEEE80211 header
static uint8_t IEEE_HEADER[] =
{
    0x08, 0x01, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
    0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
    0x10, 0x86,
};

// this is where we store a summary of the
// information from the radiotap header

#pragma pack(push, 1)

struct Penumbra_Radiotap_Header
{
    int32_t channel = 0;
    int32_t channel_flags = 0;
    int32_t rate = 0;
    int32_t antenna = 0;
    int32_t radiotap_flags = 0;
};

#pragma pack(pop)

static bool g_exit = false;

static size_t g_max_packet_size = MAX_USER_PACKET_SIZE;
static size_t g_rate_hz = DEFAULT_RATE_HZ;

static uint8_t g_local_id = 0;

static size_t g_tx_packet_header_length = 0;

static constexpr size_t MAX_INTERFACES = 32;
static size_t g_interface_count = 0;

typedef std::shared_ptr<std::vector<uint8_t>> Buffer;

struct PCAP
{
    std::mutex pcap_mutex;
    std::string interface;

    pcap_t* pcap = nullptr;
    int rx_selectable_fd = 0;

    std::array<uint8_t, MAX_PACKET_SIZE> tx_buffer;

    size_t _80211_header_length = 0;

    struct Stats
    {
        struct pcap_stat pcap;
        size_t rx_bytes = 0;
        size_t tx_bytes = 0;
        std::chrono::system_clock::time_point last_tp = std::chrono::system_clock::now();
    } stats;

} g_pcap[MAX_INTERFACES];

struct ASIO
{
    std::thread thread;

    boost::asio::io_service io_service;
    boost::asio::ip::udp::endpoint tx_endpoint;
    boost::asio::ip::udp::endpoint rx_endpoint;
    std::unique_ptr<boost::asio::ip::udp::socket> socket;

    std::array<uint8_t, MAX_USER_PACKET_SIZE> rx_buffer;

    std::mutex tx_buffer_mutex;
    std::vector<Buffer> tx_buffer_pool;
    std::deque<Buffer> tx_buffer_queue; //to send

    Buffer tx_buffer_in_transit;

    boost::function<void(const boost::system::error_code& error, std::size_t bytes_transferred)> tx_callback;
    boost::function<void(const boost::system::error_code& error, std::size_t bytes_transferred)> rx_callback;
} g_asio;

static bool prepare_filter(PCAP& pcap)
{
    struct bpf_program program;
    char program_src[512];

    int link_encap = pcap_datalink(pcap.pcap);

    switch (link_encap)
    {
    case DLT_PRISM_HEADER:
        std::cout << "DLT_PRISM_HEADER Encap\n";
        pcap._80211_header_length = 0x20; // ieee80211 comes after this
        sprintf(program_src, "radio[0x4a:4]==0x13223344 && radio[0x4e:2] != 0x55%.2x", g_local_id);
        break;

    case DLT_IEEE802_11_RADIO:
        std::cout << "DLT_IEEE802_11_RADIO Encap\n";
        pcap._80211_header_length = 0x18; // ieee80211 comes after this
        sprintf(program_src, "ether[0x0a:4]==0x13223344 && ether[0x0e:2] != 0x55%.2x", g_local_id);
        break;

    default:
        std::cout << "!!! unknown encapsulation\n";
        return false;
    }

    if (pcap_compile(pcap.pcap, &program, program_src, 1, 0) == -1)
    {
        std::cout << "Failed to compile program: " << program_src << ": " << pcap_geterr(pcap.pcap) << "\n";
        return false;
    }
    if (pcap_setfilter(pcap.pcap, &program) == -1)
    {
        pcap_freecode(&program);
        std::cout << "Failed to set program: " << program_src << ": " << pcap_geterr(pcap.pcap) << "\n";
        return false;
    }
    pcap_freecode(&program);

    pcap.rx_selectable_fd = pcap_get_selectable_fd(pcap.pcap);
    return true;
}

static void radiotap_add_u8(uint8_t*& dst, size_t& idx, uint8_t data)
{
    *dst++ = data;
    idx++;
}
static void radiotap_add_u16(uint8_t*& dst, size_t& idx, uint16_t data)
{
    if ((idx & 1) == 1) //not aligned, pad first
    {
        radiotap_add_u8(dst, idx, 0);
    }
    *reinterpret_cast<uint16_t*>(dst) = data;
    dst += 2;
    idx += 2;
}

static void prepare_radiotap_header(size_t rate_hz)
{
    RADIOTAP_HEADER.resize(1024);
    ieee80211_radiotap_header& hdr = reinterpret_cast<ieee80211_radiotap_header&>(*RADIOTAP_HEADER.data());
    hdr.it_version = 0;
    hdr.it_present = 0
                    | (1 << IEEE80211_RADIOTAP_RATE)
                    | (1 << IEEE80211_RADIOTAP_TX_FLAGS)
                    | (1 << IEEE80211_RADIOTAP_RTS_RETRIES)
                    | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
//                    | (1 << IEEE80211_RADIOTAP_MCS)
                    ;

    auto* dst = RADIOTAP_HEADER.data() + sizeof(ieee80211_radiotap_header);
    size_t idx = dst - RADIOTAP_HEADER.data();

    if (hdr.it_present & (1 << IEEE80211_RADIOTAP_RATE))
    {
        radiotap_add_u8(dst, idx, std::min(static_cast<uint8_t>(rate_hz / 500000), uint8_t(1)));
    }
    if (hdr.it_present & (1 << IEEE80211_RADIOTAP_TX_FLAGS))
    {
        radiotap_add_u16(dst, idx, IEEE80211_RADIOTAP_F_TX_NOACK); //used to be 0x18
    }
    if (hdr.it_present & (1 << IEEE80211_RADIOTAP_RTS_RETRIES))
    {
        radiotap_add_u8(dst, idx, 0x0);
    }
    if (hdr.it_present & (1 << IEEE80211_RADIOTAP_DATA_RETRIES))
    {
        radiotap_add_u8(dst, idx, 0x0);
    }
    if (hdr.it_present & (1 << IEEE80211_RADIOTAP_MCS))
    {
        radiotap_add_u8(dst, idx, IEEE80211_RADIOTAP_MCS_HAVE_MCS);
        radiotap_add_u8(dst, idx, 0);
        radiotap_add_u8(dst, idx, 18);
    }

    //finish it
    hdr.it_len = static_cast<__le16>(idx);
    RADIOTAP_HEADER.resize(idx);

//    RADIOTAP_HEADER.resize(sizeof(RADIOTAP_HEADER_original));
//    memcpy(RADIOTAP_HEADER.data(), RADIOTAP_HEADER_original, sizeof(RADIOTAP_HEADER_original));
}

static void prepare_tx_packet_header(uint8_t* buffer)
{
    //prepare the buffers with headers
    uint8_t* pu8 = buffer;

    memcpy(pu8, RADIOTAP_HEADER.data(), RADIOTAP_HEADER.size());
    pu8 += RADIOTAP_HEADER.size();

    memcpy(pu8, IEEE_HEADER, sizeof (IEEE_HEADER));
    pu8 += sizeof (IEEE_HEADER);
}

static void update_stats(PCAP& pcap, size_t rx_bytes, size_t tx_bytes)
{
#ifdef DEBUG_THROUGHPUT
    struct pcap_stat stats;
    pcap_stats(pcap.pcap, &stats);

    pcap.stats.pcap.ps_drop += stats.ps_drop;
    pcap.stats.pcap.ps_ifdrop += stats.ps_ifdrop;
    pcap.stats.pcap.ps_recv += stats.ps_recv;

    pcap.stats.rx_bytes += rx_bytes;
    pcap.stats.tx_bytes += tx_bytes;
    auto now = std::chrono::system_clock::now();
    if (now - pcap.stats.last_tp >= std::chrono::seconds(1))
    {
        float r = std::chrono::duration<float>(now - pcap.stats.last_tp).count();
        size_t rx_kb = size_t(float(pcap.stats.rx_bytes)/r/1024.f);
        size_t tx_kb = size_t(float(pcap.stats.tx_bytes)/r/1024.f);

        std::cout << pcap.interface << "> TX: " << tx_kb << " KB/s, RX: " << rx_kb << "KB/s" <<
                     " Drop: " << pcap.stats.pcap.ps_drop << " IFDrop: " << pcap.stats.pcap.ps_ifdrop << " RECV: " << pcap.stats.pcap.ps_recv << "\n";
        pcap.stats.tx_bytes -= tx_kb * 1024;
        pcap.stats.rx_bytes -= rx_kb * 1024;
        pcap.stats.last_tp = now;

        pcap.stats.pcap.ps_drop = 0;
        pcap.stats.pcap.ps_ifdrop = 0;
        pcap.stats.pcap.ps_recv = 0;
    }
#endif
}

static void send_asio_packet_locked();

static void send_ack()
{
    std::lock_guard<std::mutex> lg(g_asio.tx_buffer_mutex);
    Buffer buffer;
    if (g_asio.tx_buffer_pool.empty())
    {
        buffer = std::make_shared<Buffer::element_type>(1);
    }
    else
    {
        buffer = std::move(g_asio.tx_buffer_pool.back());
        g_asio.tx_buffer_pool.pop_back();
        buffer->resize(1);
    }

    buffer->front() = MARKER_ACK;
    g_asio.tx_buffer_queue.push_back(std::move(buffer));

    send_asio_packet_locked();
}

static void asio_rx_callback(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    if (error)
    {
        if (error != boost::asio::error::eof)
        {
            g_asio.socket->close();
        }
    }
    else
    {
        if (bytes_transferred > 0)
        {
            if (g_asio.rx_buffer[0] == MARKER_DATA)
            {
                uint8_t* rx_buffer_ptr = g_asio.rx_buffer.data() + 1;
                bytes_transferred--;

                if (bytes_transferred > g_max_packet_size)
                {
                    std::cout << "Packet too big: " << bytes_transferred << ". Clamping to max packet size: " << g_max_packet_size;
                    bytes_transferred = g_max_packet_size;
                }

#ifdef DEBUG_ASIO
                std::cout << "ASIO RX>>";
                std::copy(rx_buffer_ptr, rx_buffer_ptr + bytes_transferred, std::ostream_iterator<uint8_t>(std::cout));
                std::cout << "<<ASIO RX";
#endif

                {
                    std::lock_guard<std::mutex> lg(g_pcap[0].pcap_mutex);
                    std::copy(rx_buffer_ptr, rx_buffer_ptr + bytes_transferred, g_pcap[0].tx_buffer.data() + g_tx_packet_header_length);
                    int isize = static_cast<int>(g_tx_packet_header_length + bytes_transferred);
                    int r = 0;
                    do
                    {
                        r = pcap_inject(g_pcap[0].pcap, g_pcap[0].tx_buffer.data(), isize);
                    } while (r < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));

                    if (r <= 0)
                    {
                        std::cout << "Trouble injecting packet: " << r << " / " << isize << " : " << pcap_geterr(g_pcap[0].pcap) << "\n";
                    }

                    if (r > 0 && r != isize)
                    {
                        std::cout << "Incomplete packet sent: " << r << " / " << isize << "\n";
                    }
                }

                update_stats(g_pcap[0], 0, bytes_transferred);

                send_ack();
            }
        }

        g_asio.socket->async_receive_from(
                    boost::asio::buffer(g_asio.rx_buffer),
                    g_asio.rx_endpoint, g_asio.rx_callback);
    }
}

static void asio_tx_callback(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    //put it back in the pool
    if (g_asio.tx_buffer_in_transit)
    {
        std::lock_guard<std::mutex> lg(g_asio.tx_buffer_mutex);
        g_asio.tx_buffer_pool.push_back(std::move(g_asio.tx_buffer_in_transit));

        g_asio.tx_buffer_in_transit.reset();

        //send the next one
        send_asio_packet_locked();
    }
}

static void send_asio_packet_locked()
{
    if (!g_asio.tx_buffer_queue.empty() && !g_asio.tx_buffer_in_transit)
    {
        //std::cout << "sending\n";
        g_asio.tx_buffer_in_transit = std::move(g_asio.tx_buffer_queue.front());

#ifdef DEBUG_ASIO
        std::cout << "ASIO TX>>";
        std::copy(g_asio.tx_buffer_in_transit->begin(), g_asio.tx_buffer_in_transit->end(), std::ostream_iterator<uint8_t>(std::cout));
        std::cout << "<<ASIO TX";
#endif

        g_asio.tx_buffer_queue.pop_front();
        g_asio.socket->async_send_to(boost::asio::buffer(*g_asio.tx_buffer_in_transit), g_asio.tx_endpoint, g_asio.tx_callback);
    }
}

static void send_asio_packet()
{
    if (!g_asio.tx_buffer_in_transit)
    {
        std::lock_guard<std::mutex> lg(g_asio.tx_buffer_mutex);
        send_asio_packet_locked();
    }
}

static bool prepare_socket(uint16_t tx_port, uint16_t rx_port)
{
    g_asio.thread = std::thread([&g_asio]()
    {
        while (!g_exit)
        {
            g_asio.io_service.run();
            g_asio.io_service.reset();
        }
    });

    g_asio.tx_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), tx_port);
    g_asio.rx_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), rx_port);

    g_asio.socket.reset(new boost::asio::ip::udp::socket(g_asio.io_service));
    g_asio.socket->open(boost::asio::ip::udp::v4());
    g_asio.socket->set_option(boost::asio::ip::udp::socket::reuse_address(true));
    g_asio.socket->set_option(boost::asio::socket_base::receive_buffer_size(MAX_USER_PACKET_SIZE + 200));
    g_asio.socket->set_option(boost::asio::socket_base::send_buffer_size(MAX_USER_PACKET_SIZE + 200));
    g_asio.socket->bind(g_asio.rx_endpoint);

    g_asio.tx_callback = boost::bind(&asio_tx_callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred);
    g_asio.rx_callback = boost::bind(&asio_rx_callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred);

    g_asio.socket->async_receive_from(
                boost::asio::buffer(g_asio.rx_buffer),
                g_asio.rx_endpoint, g_asio.rx_callback);

    return true;
}

static bool process_rx_packet(PCAP& pcap)
{
    struct pcap_pkthdr* pcap_packet_header = nullptr;

    uint8_t payload_buffer[MAX_PACKET_SIZE];
    uint8_t* payload = payload_buffer;

    while (true)
    {
        {
            std::lock_guard<std::mutex> lg(pcap.pcap_mutex);
            int retval = pcap_next_ex(pcap.pcap, &pcap_packet_header, (const u_char**)&payload);
            if (retval < 0)
            {
                std::cout << "Socket broken: " << pcap_geterr(pcap.pcap) << "\n";
                return false;
            }
            if (retval != 1)
            {
                //no more packets
                break;
            }
        }

        size_t header_len = (payload[2] + (payload[3] << 8));
        if (pcap_packet_header->len < (header_len + pcap._80211_header_length))
        {
            std::cout << "packet too small\n";
            return true;
        }

        size_t bytes = pcap_packet_header->len - (header_len + pcap._80211_header_length);

        ieee80211_radiotap_iterator rti;
        if (ieee80211_radiotap_iterator_init(&rti, (struct ieee80211_radiotap_header *)payload, pcap_packet_header->len) < 0)
        {
            std::cout << "iterator null\n";
            return true;
        }

        int n = 0;
        Penumbra_Radiotap_Header prh;
        while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0)
        {

            switch (rti.this_arg_index)
            {
            case IEEE80211_RADIOTAP_RATE:
                prh.rate = (*rti.this_arg);
                break;

            case IEEE80211_RADIOTAP_CHANNEL:
                prh.channel = (*((uint16_t *)rti.this_arg));
                prh.channel_flags = (*((uint16_t *)(rti.this_arg + 2)));
                break;

            case IEEE80211_RADIOTAP_ANTENNA:
                prh.antenna = (*rti.this_arg) + 1;
                break;

            case IEEE80211_RADIOTAP_FLAGS:
                prh.radiotap_flags = *rti.this_arg;
                break;
            }
        }
        payload += header_len + pcap._80211_header_length;

        if (prh.radiotap_flags & IEEE80211_RADIOTAP_F_FCS)
        {
            bytes -= 4;
        }

        bool checksum_correct = (prh.radiotap_flags & 0x40) == 0;

        //    block_num = seq_nr / param_retransmission_block_size;//if retr_block_size would be limited to powers of two, this could be replaced by a logical AND operation

        //printf("rec %x bytes %d crc %d\n", seq_nr, bytes, checksum_correct);

#ifdef DEBUG_PCAP
        std::cout << "PCAP RX " << pcap.interface << ">>";
        std::copy(payload, payload + bytes, std::ostream_iterator<uint8_t>(std::cout));
        std::cout << "<<PCAP RX";
#endif

        {
            std::lock_guard<std::mutex> lg(g_asio.tx_buffer_mutex);
            Buffer buffer;
            if (g_asio.tx_buffer_pool.empty())
            {
                buffer = std::make_shared<Buffer::element_type>(bytes + 1);
            }
            else
            {
                buffer = std::move(g_asio.tx_buffer_pool.back());
                g_asio.tx_buffer_pool.pop_back();
                buffer->resize(bytes + 1);
            }

            buffer->front() = MARKER_DATA;
            std::copy(payload, payload + bytes, buffer->begin() + 1);
            g_asio.tx_buffer_queue.push_back(std::move(buffer));

            send_asio_packet_locked();
        }

        update_stats(pcap, bytes, 0);
    }

    return true;
}

// Define the function to be called when ctrl-c (SIGINT) signal is sent to process
static void signal_handler(int signum)
{
    if (g_exit)
    {
        std::cout << "Forcing an exit due to signal " << signum;
        abort();
    }
    g_exit = true;
    std::cout << "Exitting due to signal " << signum;
}

int main(int argc, char const* argv[])
{
    signal(SIGINT, signal_handler); // Trap basic signals (exit cleanly)
    signal(SIGKILL, signal_handler);
    signal(SIGUSR1, signal_handler);
//    signal(SIGQUIT, signal_handler);
//    signal(SIGABRT, signal_handler);
//    signal(SIGSTOP, signal_handler);

    namespace po = boost::program_options;

    po::options_description opt("Options");
    opt.add_options()
        ("help,h", "produce help message")
        ("interface,i", po::value<std::vector<std::string>>()->multitoken()->required(), "wlan interface in monitor mode. Use several for diversity. First one is used for transmitting.")
        ("packet,p", po::value<size_t>()->default_value(MAX_USER_PACKET_SIZE), "packet size")
        ("id", po::value<uint8_t>()->required(), "local station id")
        ("port", po::value<uint16_t>()->default_value(DEFAULT_PORT), "port to read data received from rfcom. Use port+1 to send data");

    po::variables_map vm;
    try
    {
        po::store(po::command_line_parser(argc, argv).options(opt).run(), vm);
        po::notify(vm);
    }
    catch (...)
    {
        std::cout << "(c)2015 leflambeur. Based on befinitiv wifibroadcast.\n";
        std::cout << "Usage: " << argv[0] << " [options]\n";
        std::cout << opt << "\n";
        return 0;
    }

    if (vm.count("help"))
    {
        std::cout << "(c)2015 leflambeur. Based on befinitiv wifibroadcast.\n";
        std::cout << "Usage: " << argv[0] << " [options]\n";
        std::cout << opt << "\n";
        return 0;
    }

    g_max_packet_size = vm["packet"].empty() ? MAX_USER_PACKET_SIZE : vm["packet"].as<size_t>();
    if (g_max_packet_size > MAX_USER_PACKET_SIZE)
    {
        std::cout << "Packet size is too big. Max is " << MAX_USER_PACKET_SIZE << "\n";
        return 1;
    }

    g_local_id = vm["id"].as<uint8_t>();

    uint16_t rx_port = vm["port"].empty() ? DEFAULT_PORT : vm["port"].as<uint16_t>();
    uint16_t tx_port = rx_port + 1;

    std::cout << "\n\nLocal id: " << g_local_id << "\n";
    std::cout << "Max packet size: " << g_max_packet_size << "\n";
    std::cout << "RX Port: " << rx_port << " TX Port: " << tx_port << "\n";

    IEEE_HEADER[SRC_MAC_LASTBYTE] = g_local_id;
    IEEE_HEADER[DST_MAC_LASTBYTE] = g_local_id;

    prepare_radiotap_header(g_rate_hz);

    char pcap_error[PCAP_ERRBUF_SIZE] = {0};

    std::vector<std::string> interfaces = vm["interface"].as<std::vector<std::string>>();
    for (const auto& interface: interfaces)
    {
        PCAP& pcap = g_pcap[g_interface_count++];
        pcap.interface = interface;

        std::cout << "\n\nInterface: " << interface << ", Local id: " << g_local_id << "\n";

        pcap.pcap = pcap_create(interface.c_str(), pcap_error);
        if (pcap.pcap == nullptr)
        {
            std::cout << "Unable to open interface " << interface << " in pcap: " << pcap_error << "\n";
            return (1);
        }
        if (pcap_set_snaplen(pcap.pcap, 1800) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_snaplen\n";
            return 1;
        }
        if (pcap_set_promisc(pcap.pcap, 1) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_promisc\n";
            return 1;
        }
        if (pcap_set_rfmon(pcap.pcap, 1) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_rfmon\n";
            return 1;
        }
        if (pcap_set_timeout(pcap.pcap, -1) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_timeout\n";
            return 1;
        }
        if (pcap_set_immediate_mode(pcap.pcap, 0) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_immediate_mode\n";
            return 1;
        }
        if (pcap_set_buffer_size(pcap.pcap, 16000000) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_set_buffer_size\n";
            return 1;
        }
        if (pcap_activate(pcap.pcap) < 0)
        {
            std::cout << "Error setting " << interface << " pcap_activate\n";
            return 1;
        }
        if (pcap_setnonblock(pcap.pcap, 1, pcap_error) < 0)
        {
            std::cout << "Error setting " << interface << " to nonblocking mode: " << pcap_error << "\n";
            return 1;
        }
        if (pcap_setdirection(pcap.pcap, PCAP_D_IN) < 0)
        {
            std::cout << "Error setting " << interface << " capture direction: " << pcap_geterr(pcap.pcap);
            return 1;
        }

        prepare_tx_packet_header(pcap.tx_buffer.data());

        if (!prepare_filter(pcap))
        {
            return 1;
        }
    }

    g_tx_packet_header_length = RADIOTAP_HEADER.size() + sizeof(IEEE_HEADER);
    std::cout << "Radiocap header size: " << RADIOTAP_HEADER.size() << ", IEEE header size: " << sizeof(IEEE_HEADER) << "\n";

    //asio data will be received directly in the pcap tx buffer, just after the headers. This avoids a memcpy
    //g_asio.rx_buffer_ptr = g_pcap[0].tx_buffer.data() + g_tx_packet_header_length;

    if (!prepare_socket(rx_port, tx_port))
    {
        return 1;
    }

    std::cout << "Starting main loop\n";
    while (!g_exit)
    {
        fd_set readset;
        struct timeval to;

        to.tv_sec = 0;
        to.tv_usec = 1e3;

        FD_ZERO(&readset);
        for (size_t i = 0; i < g_interface_count; ++i)
        {
            FD_SET(g_pcap[i].rx_selectable_fd, &readset);
        }

        int n = select(30, &readset, NULL, NULL, &to);
        for (size_t i = 0; i < g_interface_count; ++i)
        {
            if (n == 0)
            {
                break;
            }

            if (FD_ISSET(g_pcap[i].rx_selectable_fd, &readset))
            {
                process_rx_packet(g_pcap[i]);
            }
        }
    }

    g_asio.io_service.stop();

    if (g_asio.thread.joinable())
    {
        g_asio.thread.join();
    }

    return 0;
}

max_stars_repo_name: jeanleflambeur/wifibidicast

max_issues_repo_name: jeanleflambeur/wifibidicast

max_forks_repo_name: jeanleflambeur/wifibidicast


text:
#include <libfreenect/libfreenect.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <pthread.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

#include "serialport.h"

using namespace cv;
using namespace std;

class myMutex {
public:
    myMutex() {
        pthread_mutex_init( &m_mutex, NULL );
    }
    void lock() {
        pthread_mutex_lock( &m_mutex );
    }
    void unlock() {
        pthread_mutex_unlock( &m_mutex );
    }
private:
    pthread_mutex_t m_mutex;
};

class MyFreenectDevice : public Freenect::FreenectDevice {
public:
    MyFreenectDevice(freenect_context *_ctx, int _index)
            : Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_DEPTH_11BIT),
              m_buffer_rgb(FREENECT_VIDEO_RGB), m_gamma(2048), m_new_rgb_frame(false),
              m_new_depth_frame(false), depthMat(Size(640,480),CV_16UC1),
              rgbMat(Size(640,480), CV_8UC3, Scalar(0)),
              ownMat(Size(640,480),CV_8UC3,Scalar(0)) {

        for( unsigned int i = 0 ; i < 2048 ; i++) {
            float v = i/2048.0;
            v = std::pow(v, 3)* 6;
            m_gamma[i] = v*6*256;
        }
    }

    // Do not call directly even in child
    void VideoCallback(void* _rgb, uint32_t timestamp) {
//       std::cout << "RGB callback" << std::endl;
        m_rgb_mutex.lock();
        uint8_t* rgb = static_cast<uint8_t*>(_rgb);
        rgbMat.data = rgb;
        m_new_rgb_frame = true;
        m_rgb_mutex.unlock();
    };

    // Do not call directly even in child
    void DepthCallback(void* _depth, uint32_t timestamp) {
        std::cout << "Depth callback" << std::endl;
        m_depth_mutex.lock();
        uint16_t* depth = static_cast<uint16_t*>(_depth);
        depthMat.data = (uchar*) depth;
        m_new_depth_frame = true;
        m_depth_mutex.unlock();
    }

    bool getVideo(Mat& output) {
        m_rgb_mutex.lock();
        if(m_new_rgb_frame) {
            cv::cvtColor(rgbMat, output, CV_RGB2BGR);
            m_new_rgb_frame = false;
            m_rgb_mutex.unlock();
            return true;
        } else {
            m_rgb_mutex.unlock();
            return false;
        }
    }

    bool getDepth(Mat& output) {
        m_depth_mutex.lock();
        if(m_new_depth_frame) {
            depthMat.copyTo(output);
            m_new_depth_frame = false;
            m_depth_mutex.unlock();
            return true;
        } else {
            m_depth_mutex.unlock();
            return false;
        }
    }
private:
    std::vector<uint8_t> m_buffer_depth;
    std::vector<uint8_t> m_buffer_rgb;
    std::vector<uint16_t> m_gamma;
    Mat depthMat;
    Mat rgbMat;
    Mat ownMat;
    myMutex m_rgb_mutex;
    myMutex m_depth_mutex;
    bool m_new_rgb_frame;
    bool m_new_depth_frame;
};

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#define sleep(n) Sleep(1000 * (n))
#else
#include <unistd.h>
#endif

using namespace std;

void readHandler( boost::array<char,SerialPort::k_readBufferSize> const& buffer, size_t bytesTransferred) {
    std::vector<uint8_t > data;
    std::copy(buffer.begin(), buffer.begin()+bytesTransferred, std::back_inserter(data));
    for(auto item: data){
        printf("%X \t",item);
    }

    printf("\n");
}

int main(int argc, char **argv) {
    bool die(false);
    string filename("snapshot");
    string suffix(".png");
    int i_snap(0),iter(0);

    Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));

    // The next two lines must be changed as Freenect::Freenect
    // isn't a template but the method createDevice:
    // Freenect::Freenect<MyFreenectDevice> freenect;
    // MyFreenectDevice& device = freenect.createDevice(0);
    // by these two lines:

    Freenect::Freenect freenect;
    MyFreenectDevice& device = freenect.createDevice<MyFreenectDevice>(0);

    namedWindow("rgb",CV_WINDOW_AUTOSIZE);
    device.startVideo();

    boost::asio::io_service ioSrv;

    auto send_light  = Send_Light(15);
    serialPort.Write(send_light);
    sleep(1);
    while(!die){
        cv::imshow("rgb", rgbMat);
        auto temp = Send_digital();
        serialPort.Write(temp);
        for(auto item:temp){
            printf("%X \t",item);
        }
        printf("\n");
        device.getVideo(rgbMat);
        char k = cvWaitKey(1000);
        if(iter >= 10) break;
        iter++;
    }

    device.stopVideo();
    return 0;
}


text:
// Methods for converting YAML into XmlRpcValues for the parameter server
// Author: Max Schwarz <max.schwarz@ais.uni-bonn.de>

#include "yaml_params.h"
#include "launch_config.h"
#include "substitution.h"
#include "substitution_python.h"

#include <boost/algorithm/string/predicate.hpp>

namespace rosmon
{
namespace launch
{

namespace
{
	class XmlRpcValueCreator : public XmlRpc::XmlRpcValue
	{
	public:
		static XmlRpcValueCreator createArray(const std::vector<XmlRpcValue>& values)
		{
			XmlRpcValueCreator ret;
			ret._type = TypeArray;
			ret._value.asArray = new ValueArray(values);

			return ret;
		}

		static XmlRpcValueCreator createStruct(const std::map<std::string, XmlRpcValue>& members)
		{
			XmlRpcValueCreator ret;
			ret._type = TypeStruct;
			ret._value.asStruct = new std::map<std::string, XmlRpcValue>(members);
			return ret;
		}
	};
}

XmlRpc::XmlRpcValue yamlToXmlRpc(const ParseContext& ctx, const YAML::Node& n)
{
	if(n.Type() != YAML::NodeType::Scalar)
	{
		switch(n.Type())
		{
			case YAML::NodeType::Map:
			{
				std::map<std::string, XmlRpc::XmlRpcValue> members;
				for(YAML::const_iterator it = n.begin(); it != n.end(); ++it)
				{
					members[it->first.as<std::string>()] = yamlToXmlRpc(ctx, it->second);
				}
				return XmlRpcValueCreator::createStruct(members);
			}
			case YAML::NodeType::Sequence:
			{
				std::vector<XmlRpc::XmlRpcValue> values;
				for(YAML::const_iterator it = n.begin(); it != n.end(); ++it)
				{
					values.push_back(yamlToXmlRpc(ctx, *it));
				}
				return XmlRpcValueCreator::createArray(values);
			}
			default:
				throw ctx.error("Invalid YAML node type");
		}
	}

	// Scalars are tricky, as XmlRpcValue is strongly typed. So we need to
	// figure out the data type...

	// Check if a YAML tag is present
	if(n.Tag() == "tag:yaml.org,2002:int")
		return XmlRpc::XmlRpcValue(n.as<int>());
	if(n.Tag() == "tag:yaml.org,2002:float")
		return XmlRpc::XmlRpcValue(n.as<double>());
	if(n.Tag() == "tag:yaml.org,2002:bool")
		return XmlRpc::XmlRpcValue(n.as<bool>());
	if(n.Tag() == "tag:yaml.org,2002:str")
		return XmlRpc::XmlRpcValue(n.as<std::string>());
	if(n.Tag() == "tag:yaml.org,2002:binary")
	{
		auto binary = n.as<YAML::Binary>();

		// XmlRpc API is stupid here and expects a mutable void*, so to keep
		// things clean we do a copy.
		std::vector<unsigned char> copy(binary.data(), binary.data()+binary.size());

		return XmlRpc::XmlRpcValue(copy.data(), copy.size());
	}

	// rosparam supports !!degrees and !!radians...
	if(n.Tag() == "!degrees")
	{
		try
		{
			return XmlRpc::XmlRpcValue(evaluateROSParamPython(n.as<std::string>()) * M_PI / 180.0);
		}
		catch(SubstitutionException& e)
		{
			throw ctx.error("{}", e.what());
		}
	}
	if(n.Tag() == "!radians")
	{
		try
		{
			return XmlRpc::XmlRpcValue(evaluateROSParamPython(n.as<std::string>()));
		}
		catch(SubstitutionException& e)
		{
			throw ctx.error("{}", e.what());
		}
	}

	// If we have a "non-specific" tag '!', this means that the YAML scalar
	// is non-plain, i.e. of type seq, map, or str. Since seq and map are
	// handled above, we assume str in this case.
	if(n.Tag() == "!")
		return XmlRpc::XmlRpcValue(n.as<std::string>());

	// Otherwise, we simply have to try things one by one...
	try { return XmlRpc::XmlRpcValue(n.as<bool>()); }
	catch(YAML::Exception&) {}

	try { return XmlRpc::XmlRpcValue(n.as<int>()); }
	catch(YAML::Exception&) {}

	try { return XmlRpc::XmlRpcValue(n.as<double>()); }
	catch(YAML::Exception&) {}

	try
	{
		std::string str = n.as<std::string>();

		// rosparam supports deg(...) and rad(...) expressions, so we have to
		// parse them here.

		if(boost::starts_with(str, "deg(") && boost::ends_with(str, ")"))
		{
			try
			{
				return XmlRpc::XmlRpcValue(
					evaluateROSParamPython(str.substr(4, str.size() - 5)) * M_PI / 180.0
				);
			}
			catch(SubstitutionException& e)
			{
				throw ctx.error("{}", e.what());
			}
		}

		if(boost::starts_with(str, "rad(") && boost::ends_with(str, ")"))
		{
			try
			{
				return XmlRpc::XmlRpcValue(evaluateROSParamPython(str.substr(4, str.size() - 5)));
			}
			catch(SubstitutionException& e)
			{
				throw ctx.error("{}", e.what());
			}
		}

		return XmlRpc::XmlRpcValue(str);
	}
	catch(YAML::Exception&) {}

	throw ctx.error("Could not convert YAML value");
}

}
}

max_stars_repo_name: Rogerpi/rosmon

max_issues_repo_name: Rogerpi/rosmon

max_forks_repo_name: Rogerpi/rosmon


text:
#include <boost/test/unit_test.hpp>

#include <scorum/protocol/exceptions.hpp>

#include <scorum/chain/database/database.hpp>
#include <scorum/chain/schema/scorum_objects.hpp>
#include <scorum/blockchain_history/schema/operation_objects.hpp>
#include <scorum/chain/genesis/genesis_state.hpp>
#include <scorum/chain/services/account.hpp>
#include <scorum/chain/services/witness_schedule.hpp>
#include <scorum/chain/services/dynamic_global_property.hpp>

#include <scorum/blockchain_history/blockchain_history_plugin.hpp>

#include <graphene/utilities/tempdir.hpp>

#include <fc/crypto/digest.hpp>
#include <scorum/chain/database_exceptions.hpp>

#include "database_default_integration.hpp"
#include <random>

const int witnesses_count = 43;

namespace {
using namespace database_fixture;
using namespace scorum::protocol;

class witness : public database_trx_integration_fixture
{
public:
    std::vector<Actor> witnesses;
    int witness_no;
    Actor account;

    witness(int witness_no)
        : witness_no(witness_no)
    {
        initdelegate.scorumpower(asset(TEST_ACCOUNTS_INITIAL_SUPPLY.amount, SP_SYMBOL));
        initdelegate.scorum(TEST_ACCOUNTS_INITIAL_SUPPLY);

        auto gen = Genesis::create()
                       .accounts_supply(TEST_ACCOUNTS_INITIAL_SUPPLY * witnesses_count)
                       .rewards_supply(TEST_REWARD_INITIAL_SUPPLY * witnesses_count)
                       .dev_committee(initdelegate)
                       .steemit_bounty_accounts_supply(
                           asset(TEST_ACCOUNTS_INITIAL_SUPPLY.amount * witnesses_count, SP_SYMBOL))
                       .steemit_bounty_accounts(initdelegate)
                       .witnesses(initdelegate)
                       .accounts(initdelegate);

        witnesses.push_back(initdelegate);

        for (int i = 1; i < witnesses_count; ++i)
        {
            Actor witness = "witness" + std::to_string(i + 1);
            witness.scorumpower(asset(TEST_ACCOUNTS_INITIAL_SUPPLY.amount, SP_SYMBOL));
            witness.scorum(TEST_ACCOUNTS_INITIAL_SUPPLY);
            // actor(initdelegate).give_sp(witness, 1e8);

            witnesses.push_back(witness);
            gen.accounts(witnesses.back());
            gen.witnesses(witnesses.back());
            gen.steemit_bounty_accounts(witnesses.back());
        }

        account = witnesses[witness_no];

        open_database(gen.generate());

        auto& wso = db.obtain_service<dbs_witness_schedule>().get();
        db.modify(wso, [](witness_schedule_object& o) { o.num_scheduled_witnesses = 21; });
    }

    virtual void open_database_impl(const genesis_state_type& genesis) override
    {
        database_integration_fixture::open_database_impl(genesis);
    }
};

class fork_db_fixture
{
public:
    fork_db_fixture()
        : distr(1, 42)
    {
        // std::default_random_engine

        for (int i = 0; i < witnesses_count; ++i)
            w.push_back(std::make_shared<witness>(i));
    }

    void vote(std::shared_ptr<witness> who, std::shared_ptr<witness> whom, std::shared_ptr<witness> sign_with)
    {
        account_witness_vote_operation op;
        op.account = who->account.name;
        op.witness = whom->account.name;
        op.approve = true;

        sign_with->push_operation(op, sign_with->account.private_key, false);
    }

    signed_block gen_block(std::shared_ptr<witness> wit, int slot_no)
    {
        return wit->db.generate_block(wit->db.get_slot_time(slot_no), wit->account.name, wit->account.private_key,
                                      database::skip_nothing);
    }

    void push(std::shared_ptr<witness> wit, signed_block& block)
    {
        wit->db.push_block(block, database::skip_nothing);
    }

    const fc::array<account_name_type, 21>& get_schedule(std::shared_ptr<witness> wit) const
    {
        auto& wso = wit->db.obtain_service<dbs_witness_schedule>().get();
        return wso.current_shuffled_witnesses;
    }

public:
    std::vector<std::shared_ptr<witness>> w;
    std::default_random_engine eng;
    std::uniform_int_distribution<> distr;
};

BOOST_FIXTURE_TEST_SUITE(fork_tests, fork_db_fixture)

BOOST_AUTO_TEST_CASE(should_throw_unlinkable_block_exception)
{
    auto& wso = w[0]->db.obtain_service<dbs_witness_schedule>().get();
    int i = 0;
    for (const auto& w : wso.current_shuffled_witnesses)
        BOOST_TEST_MESSAGE(++i << ": " << w);

    // starting from w[1] because we cannot select slot '0' directly.
    auto block0 = gen_block(w[1], 1);
    push(w[0], block0);
    push(w[2], block0);
    push(w[3], block0);
    push(w[4], block0);

    auto block1 = gen_block(w[2], 1);
    push(w[0], block1);
    push(w[1], block1);
    // push(w[3], block1);
    push(w[4], block1);

    auto block2 = gen_block(w[3], 2); // since w[3] skipped 'block1', 'block2' goes into fork db for each witness. since
    // we do not pushing block into main db, we do not increment dpo.current_aslot
    push(w[0], block2);
    push(w[1], block2);
    push(w[2], block2);
    push(w[4], block2);

    auto block3 = gen_block(w[4], 2);
    push(w[0], block3);
    push(w[1], block3);
    push(w[2], block3);

    BOOST_REQUIRE_THROW(push(w[3], block3), unlinkable_block_exception);
    push(w[3], block0); // syncing
    push(w[3], block1);
    push(w[3], block3);
}

BOOST_AUTO_TEST_CASE(circulating_capital_mismatch)
{
    auto& wso = w[0]->db.obtain_service<dbs_witness_schedule>().get();
    int i = 0;
    for (const auto& w : wso.current_shuffled_witnesses)
        BOOST_TEST_MESSAGE(++i << ": " << w);

    // starting from w[1] because we cannot select slot '0' directly.
    auto block0 = gen_block(w[1], 1);
    push(w[0], block0);
    push(w[2], block0);
    push(w[3], block0);
    push(w[4], block0);

    auto block1 = gen_block(w[2], 1);
    push(w[0], block1);
    push(w[1], block1);
    // push(w[3], block1);
    push(w[4], block1);

    auto block2 = gen_block(w[3], 2); // since w[3] skipped 'block1', 'block2' goes into fork db for each witness. since
    // we do not pushing block into main db, we do not increment dpo.current_aslot
    push(w[0], block2);
    push(w[1], block2);
    push(w[2], block2);
    push(w[4], block2);

    auto block3 = gen_block(w[4], 2);
    push(w[0], block3);
    push(w[1], block3);
    push(w[2], block3);

    BOOST_REQUIRE_THROW(push(w[3], block3), unlinkable_block_exception);
    push(w[3], block0); // syncing
    push(w[3], block1);
    push(w[3], block3);

    const auto& w3_account_service = w[3]->db.account_service();
    const auto& w2_acc_from_w3_db = w3_account_service.get_account(w[2]->account.name);

    const auto& w2_account_service = w[2]->db.account_service();
    const auto& w2_acc_from_w2_db = w2_account_service.get_account(w[2]->account.name);

    BOOST_REQUIRE_EQUAL(w2_acc_from_w2_db.scorumpower, w2_acc_from_w3_db.scorumpower);
}

BOOST_AUTO_TEST_SUITE_END()
}

max_stars_repo_name: scorum/scorum

max_issues_repo_name: Scorum/Scorum

max_forks_repo_name: Scorum/Scorum


text:
#include "../src/ForceFields/GayBerneFF.h"
#include "../src/ForceFields/ForceFieldManager.h"
#include "../src/Simulation/StandardSimulation.h"
#include "../src/Moves/MoveManager.h"
#include "../src/Moves/TranslateMove.h"
#include "../src/Particles/Particle.h"

#include "../src/Worlds/World.h"
#include "../src/Worlds/WorldManager.h"
#include "../src/Constraints/Constraint.h"
#include "TestAccumulator.h"
#include "json/json.h"
#include "gtest/gtest.h"
#include <fstream>

#ifdef MULTI_WALKER
#include <boost/mpi.hpp>
using namespace boost;
#endif

using namespace SAPHRON;

// Verified against OpenMD 2.4.
TEST(GayBerneFF, DefaultBehavior)
{
	double rcut = 55.0;
	GayBerneFF ff(16.27, 16.27, 3.254, 3.254, 418.0, 10.0, 1.0, 0.20, {rcut}, 1.0, 2.0);

	Particle s1({0.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, "L1");
	Particle s2({0.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, "L1");
	s1.AddNeighbor(&s2);
	s2.AddNeighbor(&s1);

	s2.SetPosition({16.6855, 0, 0});
	auto NB = ff.Evaluate(s1, s2, s1.GetPosition() - s2.GetPosition(), 0);
	ASSERT_NEAR(NB.energy, -2823.5, 1e-1);

	s2.SetPosition({0, 0, 32.5468});
	NB = ff.Evaluate(s1, s2, s1.GetPosition() - s2.GetPosition(), 0);
	ASSERT_NEAR(NB.energy, -0.1129, 1e-4);
}

// Tests conservation of energy in a system with GB
// particles and no skin thickness. (rcut = nlist).
TEST(GayBerneFF, NoSkinConservation)
{
	#ifdef MULTI_WALKER
	mpi::environment env;
	mpi::communicator comm;
	#endif

	// Load file (assumes we are in build folder).
	std::ifstream t("../test/gb_no_skin.json");
	std::stringstream buffer;
	buffer << t.rdbuf();

	// Read JSON.
	Json::Reader reader;
	Json::Value root;
	ASSERT_TRUE(reader.parse(buffer, root));

	// Build world.
	WorldManager wm;
	World* w;
	ASSERT_NO_THROW(w = World::Build(root["worlds"][0], root["blueprints"]));
	ASSERT_NE(nullptr, w);
	wm.AddWorld(w);

	ASSERT_EQ(338, w->GetParticleCount());
	ASSERT_EQ(5.0, w->GetNeighborRadius());
	ASSERT_EQ(0.0, w->GetSkinThickness());

	// Gay Berne interaction.
	ForceFieldManager ffm;
	GayBerneFF ff(1.0, 1.0, 3.0, 3.0, 1.0, 1.0, 5.0, 1.0, {5.0}, 2.0, 1.0);
	ffm.AddNonBondedForceField("GB", "GB", ff);

	// Get constraints.
	std::vector<Constraint*> constraints;
	ASSERT_NO_THROW(Constraint::BuildConstraints(root["forcefields"]["constraints"], &ffm, &wm, constraints));

	// Get moves.
	MoveManager mm;
	MoveList moves;
	ASSERT_NO_THROW(Move::BuildMoves(root["moves"], &mm, &wm, moves));

	// Initialize simulation.
	StandardSimulation sim(&wm, &ffm, &mm);

	sim.Run(100);

	// Conservation of energy and pressure.
	auto H = ffm.EvaluateEnergy(*w);
	ASSERT_NEAR(H.energy.total(), w->GetEnergy().total(), 1e-10);

	delete w;
	for(auto& m : mm)
		delete m;

	for(auto& c : constraints)
		delete c;
}

max_stars_repo_name: hsidky/LNTMC

max_issues_repo_name: hsidky/LNT-MC

max_forks_repo_name: hsidky/LNT-MC


text:
//  (C) Copyright Gennadiy Rozental 2001.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : defines runtime parameters setup error
// ***************************************************************************

#ifndef BOOST_TEST_UTILS_RUNTIME_INIT_ERROR_HPP
#define BOOST_TEST_UTILS_RUNTIME_INIT_ERROR_HPP

// Boost.Test Runtime parameters
#include <boost/test/utils/runtime/fwd.hpp>

// Boost.Test
#include <boost/test/utils/string_cast.hpp>

// Boost.Test
#include <boost/config.hpp>

// STL
#include <exception>
#include <vector>

#include <boost/test/detail/suppress_warnings.hpp>

namespace boost {
namespace runtime {

// ************************************************************************** //
// **************             runtime::param_error             ************** //
// ************************************************************************** //

class BOOST_SYMBOL_VISIBLE param_error : public std::exception {
public:
  ~param_error() BOOST_NOEXCEPT_OR_NOTHROW {}

  virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW {
    return msg.c_str();
  }

  cstring param_name;
  std::string msg;

protected:
  explicit param_error(cstring param_name_) : param_name(param_name_) {}
};

//____________________________________________________________________________//

class BOOST_SYMBOL_VISIBLE init_error : public param_error {
protected:
  explicit init_error(cstring param_name) : param_error(param_name) {}
  ~init_error() BOOST_NOEXCEPT_OR_NOTHROW {}
};

class BOOST_SYMBOL_VISIBLE input_error : public param_error {
protected:
  explicit input_error(cstring param_name) : param_error(param_name) {}
  ~input_error() BOOST_NOEXCEPT_OR_NOTHROW {}
};

//____________________________________________________________________________//

template <typename Derived, typename Base>
class BOOST_SYMBOL_VISIBLE specific_param_error : public Base {
protected:
  explicit specific_param_error(cstring param_name) : Base(param_name) {}
  ~specific_param_error() BOOST_NOEXCEPT_OR_NOTHROW {}

public:
  //____________________________________________________________________________//

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) &&                              \
    !defined(BOOST_NO_CXX11_REF_QUALIFIERS)

  Derived operator<<(char const *val) && {
    this->msg.append(val);

    return static_cast<Derived &&>(*this);
  }

  //____________________________________________________________________________//

  template <typename T> Derived operator<<(T const &val) && {
    this->msg.append(unit_test::utils::string_cast(val));

    return static_cast<Derived &&>(*this);
  }

  //____________________________________________________________________________//

#else

  Derived const &operator<<(char const *val) const {
    const_cast<specific_param_error<Derived, Base> &>(*this).msg.append(val);

    return static_cast<Derived const &>(*this);
  }

  //____________________________________________________________________________//

  template <typename T> Derived const &operator<<(T const &val) const {
    const_cast<specific_param_error<Derived, Base> &>(*this).msg.append(
        unit_test::utils::string_cast(val));

    return static_cast<Derived const &>(*this);
  }

  //____________________________________________________________________________//

#endif
};

// ************************************************************************** //
// **************           specific exception types           ************** //
// ************************************************************************** //

#define SPECIFIC_EX_TYPE(type, base)                                           \
  class BOOST_SYMBOL_VISIBLE type : public specific_param_error<type, base> {  \
  public:                                                                      \
    explicit type(cstring param_name = cstring())                              \
        : specific_param_error<type, base>(param_name) {}                      \
  } /**/

SPECIFIC_EX_TYPE(invalid_cla_id, init_error);
SPECIFIC_EX_TYPE(duplicate_param, init_error);
SPECIFIC_EX_TYPE(conflicting_param, init_error);
SPECIFIC_EX_TYPE(unknown_param, init_error);
SPECIFIC_EX_TYPE(access_to_missing_argument, init_error);
SPECIFIC_EX_TYPE(arg_type_mismatch, init_error);
SPECIFIC_EX_TYPE(invalid_param_spec, init_error);

SPECIFIC_EX_TYPE(format_error, input_error);
SPECIFIC_EX_TYPE(duplicate_arg, input_error);
SPECIFIC_EX_TYPE(missing_req_arg, input_error);

#undef SPECIFIC_EX_TYPE

class BOOST_SYMBOL_VISIBLE ambiguous_param
    : public specific_param_error<ambiguous_param, input_error> {
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  explicit ambiguous_param(std::vector<cstring> &&amb_candidates)
      : specific_param_error<ambiguous_param, input_error>(""),
        m_amb_candidates(std::move(amb_candidates)) {}
#else
  explicit ambiguous_param(std::vector<cstring> const &amb_candidates)
      : specific_param_error<ambiguous_param, input_error>(""),
        m_amb_candidates(amb_candidates) {}
#endif
  ~ambiguous_param() BOOST_NOEXCEPT_OR_NOTHROW {}

  std::vector<cstring> m_amb_candidates;
};

class BOOST_SYMBOL_VISIBLE unrecognized_param
    : public specific_param_error<unrecognized_param, input_error> {
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  explicit unrecognized_param(std::vector<cstring> &&type_candidates)
      : specific_param_error<unrecognized_param, input_error>(""),
        m_typo_candidates(std::move(type_candidates)) {}
#else
  explicit unrecognized_param(std::vector<cstring> const &type_candidates)
      : specific_param_error<unrecognized_param, input_error>(""),
        m_typo_candidates(type_candidates) {}
#endif
  ~unrecognized_param() BOOST_NOEXCEPT_OR_NOTHROW {}

  std::vector<cstring> m_typo_candidates;
};

} // namespace runtime
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_UTILS_RUNTIME_INIT_ERROR_HPP

ext: hpp

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
//  (c) Copyright 2008 Samuel Debionne.
//
//  Distributed under the MIT Software License. (See accompanying file
//  license.txt) or copy at http://www.opensource.org/licenses/mit-license.php)
//
//  See http://code.google.com/p/fsc-sdk/ for the library home page.
//
//	$Revision: $
//	$History: $

/// \file work_thread.hpp
/// The main loop (apart from the GUI one)

#if !defined(__WORKER_THREAD_HPP__)
#define __WORKER_THREAD_HPP__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <boost/array.hpp>

#include <cockpit.hpp>
#include <win/event.hpp>
//#include <iocards/usb_expansion_card.hpp>
//#include <fsx/sim_connect.hpp>
#include <fsx/dispatch_proc.hpp>

#define WORK_PRECONDITION(x) _ASSERT((x))

//struct context
//{
//    context(fsx::sim_connect& _sc, iocards::usb_expansion_card& _hid, basic_cockpit& _cockpit)
//        : sc_(_sc), hid_(_hid), cockpit_(_cockpit) {}
//
//    fsx::sim_connect& sc_;
//    iocards::usb_expansion_card& hid_;
//    basic_cockpit& cockpit_;
//};

/// A callable object that implements the main loop
class work
{
public:
    enum event {EVENT_SIMCONNECT, EVENT_HID, EVENT_EXIT};

    work(
        basic_cockpit& _ckpt,
        win::event_t _simconn_event,
        win::event_t _hid_event,
        win::event_t _exit_event) :
        ckpt_(_ckpt)
    {
        WORK_PRECONDITION((_simconn_event.get() != INVALID_HANDLE_VALUE));
        WORK_PRECONDITION((_hid_event.get() != INVALID_HANDLE_VALUE));
        WORK_PRECONDITION((_exit_event.get() != INVALID_HANDLE_VALUE));

        events_[EVENT_SIMCONNECT] = _simconn_event.get();
	    events_[EVENT_HID] = _hid_event.get();
        events_[EVENT_EXIT] = _exit_event.get();
    }

    void operator()()
    {
        bool exit = false;
        while (!exit)
        {
            DWORD EvtId = ::WaitForMultipleObjects(events_.size(), events_.c_array(), FALSE, INFINITE);

            switch (EvtId)
            {
            case WAIT_OBJECT_0 + EVENT_SIMCONNECT:
                ckpt_.sim().call_dispatch(dispatch_proc, &exit);
                break;

            case WAIT_ABANDONED_0 + EVENT_HID:
            case WAIT_TIMEOUT:
                ckpt_.hw().cancel_io();
                break;

            case WAIT_OBJECT_0 + EVENT_HID:
                //LDBG_ << std::setbase(std::ios_base::hex)
                //    << (int) ckpt_.hid_.input_buffer[0] << " "
                //    << (int) input_buffer[1] << " "
                //    << (int) input_buffer[2] << " "
                //    << (int) input_buffer[3] << " "
                //    << (int) input_buffer[4] << " "
                //    << (int) input_buffer[5] << " "
                //    << (int) input_buffer[6] << " "
                //    << (int) input_buffer[7] << " "
                //    << (int) input_buffer[8];
                {
                DWORD nb_bytes_transferred = ckpt_.hw().overlapped_result();

                //TODO: Parse HID buffer...
                //boost::dynamic_bitset<> bitset(res.second * 8);
                //hid_to_event_mapping bitset

                // Initiate a new read
                DWORD nb_bytes_read = ckpt_.hw().read();

                //hr = sc.transmit_client_event(SIMCONNECT_OBJECT_ID_USER, EVENT_MIXTURE_SET, input_buffer[2] * 0x40, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
                }
                break;

            case WAIT_OBJECT_0 + EVENT_EXIT:
                exit = true;
                break;

            default :
                LERR_ << "unexpected event: " << EvtId;
            }
        }
    }

private:
    boost::array<HANDLE, 3> events_;
     basic_cockpit& ckpt_;
};

#endif //__WORKER_THREAD_HPP__

max_stars_repo_name: gbucknell/fsc-sdk

max_issues_repo_name: gbucknell/fsc-sdk

max_forks_repo_name: gbucknell/fsc-sdk


text:
/* Copyright (c) 2010-2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdarg.h>
#include <execinfo.h>
#include <signal.h>
#include <stdexcept>

#include <boost/lexical_cast.hpp>

#include "Logger.h"
#include "ShortMacros.h"
#include "ThreadId.h"
#include "Util.h"

namespace RAMCloud {

Logger* Logger::sharedLogger = NULL;

/**
 * Friendly names for each #LogLevel value.
 * Keep this in sync with the LogLevel enum.
 */
static const char* logLevelNames[] = {"(none)", "ERROR", "WARNING",
                                      "NOTICE", "DEBUG"};

static_assert(unsafeArrayLength(logLevelNames) == NUM_LOG_LEVELS,
              "logLevelNames size does not match NUM_LOG_LEVELS");
/**
 * Friendly names for each #LogModule value.
 * Keep this in sync with the LogModule enum.
 */
static const char* logModuleNames[] = {"default", "transport"};

static_assert(unsafeArrayLength(logModuleNames) == NUM_LOG_MODULES,
              "logModuleNames size does not match NUM_LOG_MODULES");

/**
 * Create a new debug logger; messages will go to stderr by default.
 * \param[in] level
 *      Messages for all modules at least as important as \a level will be
 *      logged.
 */
Logger::Logger(LogLevel level)
    : stream(NULL)
    , mutex()
    , collapseMap()
    , collapseIntervalMs(DEFAULT_COLLAPSE_INTERVAL)
    , maxCollapseMapSize(DEFAULT_COLLAPSE_MAP_LIMIT)
    , nextCleanTime({0, 0})
    // Collapsing log messages is usually more trouble than it is worth.
    // It causes log messages to show up out of order and has created more
    // confusion than it has save.
    // The default below is now to run the system without log collapsing
    // unless enableCollapsing() is called first.
    , testingBufferSize(0)
{
    setLogLevels(level);
}

/**
 * Destructor for debug logs.
 */
Logger::~Logger()
{
    Lock lock(mutex);
    if (stream != NULL)
        fclose(stream);
}

/**
 * Return the singleton shared instance that is normally used for logging.
 */
Logger&
Logger::get()
{
    if (sharedLogger == NULL) {
        sharedLogger = new Logger();
    }
    return *sharedLogger;
}

/**
 * Arrange for future log messages to go to a particular file.
 * \param path
 *      The pathname for the log file, which may or may not exist already.
 * \param truncate
 *      True means the log file should be truncated if it already exists;
 *      false means an existing log file is retained, and new messages are
 *      appended.
 *
 */
void
Logger::setLogFile(const char* path, bool truncate)
{
    Lock lock(mutex);
    FILE* f = fopen(path, truncate ? "w" : "a");
    if (f == NULL) {
        throw Exception(HERE,
                        format("couldn't open log file '%s'", path),
                        errno);
    }
    if (stream != NULL)
        fclose(stream);
    stream = f;
}

/**
 * Set the log level for a particular module.
 * \param[in] module
 *      The module whose level to set.
 * \param[in] level
 *      Messages for \a module at least as important as \a level will be
 *      logged.
 */
void
Logger::setLogLevel(LogModule module, LogLevel level)
{
    Lock lock(mutex);
    logLevels[module] = level;
}

/**
 * Set the log level for a particular module.
 * \param[in] module
 *      The module whose level to set.
 * \param[in] level
 *      Messages for \a module at least as important as \a level will be
 *      logged. This will be clamped to a valid LogLevel if it is out of range.
 */
void
Logger::setLogLevel(LogModule module, int level)
{
    // No lock needed: doesn't access Logger object.
    if (level < 0)
        level = 0;
    else if (level >= NUM_LOG_LEVELS)
        level = NUM_LOG_LEVELS - 1;
    setLogLevel(module, static_cast<LogLevel>(level));
}

/**
 * Set the log level for a particular module.
 * \param[in] module
 *      The module whose level to set.  Given as a string from #logModuleNames.
 * \param[in] level
 *      Messages for \a module at least as important as \a level will be
 *      logged. This will be clamped to a valid LogLevel if it is out of range.
 *      Given as a string from #logLevelNames or as a decimal number indicating
 *      that level's index in the array.
 */
void
Logger::setLogLevel(string module, string level)
{
    // No lock needed: doesn't access Logger object.
    int moduleIndex = 0;
    for (; moduleIndex < NUM_LOG_MODULES; ++moduleIndex) {
        if (module == logModuleNames[moduleIndex])
            break;
    }
    if (moduleIndex == NUM_LOG_MODULES) {
        LOG(WARNING, "Ignoring bad log module name: %s", module.c_str());
        return;
    }
    int moduleLevel;
    try {
        moduleLevel = boost::lexical_cast<int>(level);
    } catch (boost::bad_lexical_cast& e) {
        for (moduleLevel = static_cast<int>(ERROR);
             moduleLevel < NUM_LOG_LEVELS;
             ++moduleLevel)
        {
            if (level == logLevelNames[moduleLevel])
                break;
        }
        if (moduleLevel == NUM_LOG_LEVELS) {
            LOG(WARNING, "Ignoring bad log module level: %s", level.c_str());
            return;
        }
    }
    setLogLevel(static_cast<LogModule>(moduleIndex), moduleLevel);
}

/**
 * Change the log level by a relative amount for a particular module.
 * \param[in] module
 *      The module whose level to change.
 * \param[in] delta
 *      The amount (positive or negative) by which to change the log level
 *      of \a module. The resulting level will be clamped to a valid LogLevel
 *      if it is out of range.
 */
void
Logger::changeLogLevel(LogModule module, int delta)
{
    Lock lock(mutex);
    int level = static_cast<int>(logLevels[module]);
    setLogLevel(module, level + delta);
}

/**
 * Set the log level for all modules.
 * \param[in] level
 *      Messages for the modules at least as important as \a level will be
 *      logged.
 */
void
Logger::setLogLevels(LogLevel level)
{
    // No lock needed: doesn't access Logger object.
    for (int i = 0; i < NUM_LOG_MODULES; i++) {
        LogModule module = static_cast<LogModule>(i);
        setLogLevel(module, level);
    }
}
/**
 * Set the log level for all modules.
 * \param[in] level
 *      Messages for all modules at least as important as \a level will be
 *      logged. This will be clamped to a valid LogLevel if it is out of range.
 */
void
Logger::setLogLevels(int level)
{
    // No lock needed: doesn't access Logger object.
    if (level < 0)
        level = 0;
    else if (level >= NUM_LOG_LEVELS)
        level = NUM_LOG_LEVELS - 1;
    setLogLevels(static_cast<LogLevel>(level));
}
/**
 * Set the log level for all modules.
 * \param[in] level
 *      Messages for all modules at least as important as \a level will be
 *      logged. This will be clamped to a valid LogLevel if it is out of range.
 */
void
Logger::setLogLevels(string level)
{
    // No lock needed: doesn't access Logger object.
    int moduleLevel;
    try {
        moduleLevel = boost::lexical_cast<int>(level);
    } catch (boost::bad_lexical_cast& e) {
        for (moduleLevel = static_cast<int>(ERROR);
             moduleLevel < NUM_LOG_LEVELS;
             ++moduleLevel)
        {
            if (level == logLevelNames[moduleLevel])
                break;
        }
        if (moduleLevel == NUM_LOG_LEVELS) {
            LOG(WARNING, "Ignoring bad log module level: %s", level.c_str());
            return;
        }
    }
    setLogLevels(moduleLevel);
}

/**
 * Change the log level by a relative amount for all modules.
 * \param[in] delta
 *      The amount (positive or negative) by which to change the log level
 *      of the modules. The resulting level will be clamped to a valid LogLevel
 *      if it is out of range.
 */
void
Logger::changeLogLevels(int delta)
{
    // No lock needed: doesn't access Logger object.
    for (int i = 0; i < NUM_LOG_MODULES; i++) {
        LogModule module = static_cast<LogModule>(i);
        changeLogLevel(module, delta);
    }
}

/**
 * Log a backtrace for the system administrator.
 * This version doesn't provide C++ name demangling so it can be helpful
 * to run the output of the backtrace through c++filt.
 * \param[in] module
 *      The module to which the message pertains.
 * \param[in] level
 *      See #LOG.
 * \param[in] where
 *      The result of #HERE.
 */
void
Logger::logBacktrace(LogModule module, LogLevel level,
                     const CodeLocation& where)
{
    // No lock needed: doesn't access Logger object.
    const int maxFrames = 128;
    void* retAddrs[maxFrames];
    int frames = backtrace(retAddrs, maxFrames);
    char** symbols = backtrace_symbols(retAddrs, frames);
    if (symbols == NULL) {
        // If the malloc failed we might be able to get the backtrace out
        // to stderr still.
        backtrace_symbols_fd(retAddrs, frames, 2);
        return;
    }

    logMessage(false, module, level, where, "Backtrace:\n");
    for (int i = 0; i < frames; ++i)
        logMessage(false, module, level, where, "%s\n", symbols[i]);

    free(symbols);
}

/**
 * Log a message for the system administrator.
 * \param[in] collapse
 *      Collapse log messages when set.
 * \param[in] module
 *      The module to which the message pertains.
 * \param[in] level
 *      See #LOG.
 * \param[in] where
 *      The result of #HERE.
 * \param[in] fmt
 *      See #LOG except the string should end with a newline character.
 * \param[in] ...
 *      See #LOG.
 */
void
Logger::logMessage(bool collapse, LogModule module, LogLevel level,
                   const CodeLocation& where,
                   const char* fmt, ...)
{
    Lock lock(mutex);

    static int pid = getpid();
    va_list ap;
    struct timespec now;
    clock_gettime(CLOCK_REALTIME, &now);

    // Check for possibility of collapsing before the message is generated at
    // all.
    SkipInfo* skip = NULL;
    if (collapse) {
        auto messageId = std::make_pair(where.file, where.line);
        CollapseMap::iterator iter = collapseMap.find(messageId);
        if (iter != collapseMap.end()) {
            // We have printed this message before; if it was recently,
            // don't print the current message, but keep track of the fact
            // that we skipped it.
            skip = &iter->second;
            if (Util::timespecLess(now, skip->nextPrintTime)) {
                skip->skipCount++;
                return;
            }

            // We've printed this message before, but it was a while ago,
            // so print the message again.
        } else {
            skip = &collapseMap[messageId];
        }
    }

    // Compute the body of the log message except for the initial timestamp
    // (i.e. process the original format string, and add location/process/thread
    // info).
    string message = format("%s:%d in %s %s %s[%d:%lu]: ",
            where.relativeFile().c_str(), where.line,
            where.qualifiedFunction().c_str(), logModuleNames[module],
            logLevelNames[level], pid, ThreadId::get());
    char buffer[2000];
    va_start(ap, fmt);
    uint32_t bufferSize = testingBufferSize ? testingBufferSize
            : downCast<uint32_t>(sizeof(buffer));
    uint32_t needed = vsnprintf(buffer, bufferSize, fmt, ap);
    va_end(ap);
    message += buffer;
    if (needed >= bufferSize) {
        // Couldn't quite fit the whole message in our fixed-size buffer.
        // Just truncate the message.
        snprintf(buffer, bufferSize, "... (%d chars truncated)\n",
                (needed + 1 - bufferSize));
        message += buffer;
    }

    if (!collapse) {
        printMessage(now, message.c_str(), 0);
        return;
    }

    // If we reach this point of control, then we are collapsing but this is
    // the first time we have seen this CodeLocation, or this entry was
    // previously purged.
    //
    // Make a new collapseMap entry so we won't print this message again for a
    // while.
    skip->message = message;
    skip->nextPrintTime = Util::timespecAdd(now,
            {collapseIntervalMs/1000,
            (collapseIntervalMs%1000)*1000000});

    // Print previously-deferred messages, if needed.
    if (Util::timespecLessEqual(nextCleanTime, now)) {
        cleanCollapseMap(now);
    }
    if (Util::timespecLess(skip->nextPrintTime, nextCleanTime)) {
        nextCleanTime = skip->nextPrintTime;
    }

    // Print the current message.
    printMessage(now, message.c_str(), skip->skipCount);
    skip->skipCount = 0;

    // If collapseMap gets too large, just delete an entry at random.
    if (collapseMap.size() > maxCollapseMapSize) {
        collapseMap.erase(collapseMap.begin());
    }
}

/**
 * This method is called to print delayed log messages. If a bunch of
 * duplicates for the message were suppressed, but no new copies of that
 * message are logged, we eventually want to print out information about
 * the suppressed duplicates. This method does that (and it also removes
 * old entries from \c collapseMap). The caller must hold the Logger lock.
 *
 * \param now
 *      The current time: information will be printed about any suppressed
 *      duplicates with \c nextPrintTime less than or equal to this, or
 *      such entries will be removed from collapseMap if there are no
 *      suppressed duplicates.
 */
void
Logger::cleanCollapseMap(struct timespec now)
{
    nextCleanTime = Util::timespecAdd(now, {1000, 0});
    CollapseMap::iterator iter = collapseMap.begin();
    while (iter != collapseMap.end()) {
        auto messageId = &iter->first;
        SkipInfo* skip = &iter->second;
        if (Util::timespecLessEqual(skip->nextPrintTime, now)) {
            // This entry has been around for a while: if there were
            // suppress messages then print one; otherwise delete the
            // entry.
            if (skip->skipCount == 0) {
                // This entry is old and there haven't been any suppressed
                // log messages for it; just delete the entry.
                iter++;
                collapseMap.erase(*messageId);
                continue;
            }

            // This entry contains suppressed log messages, but it's been
            // a long time since we printed the last one; print another one.

            printMessage(skip->nextPrintTime, skip->message.c_str(),
                    skip->skipCount-1);
            skip->skipCount = 0;
            skip->nextPrintTime = Util::timespecAdd(now,
                    {collapseIntervalMs/1000,
                    (collapseIntervalMs%1000)*1000000});
        }
        if (Util::timespecLess(skip->nextPrintTime, nextCleanTime)) {
            nextCleanTime = skip->nextPrintTime;
        }
        iter++;
    }
}

/**
 * Return the I/O stream to use for log output.
 */
FILE*
Logger::getStream()
{
    if (stream != NULL)
        return stream;
    return stderr;
}

/**
 * Utility method that actually prints messages; eliminates duplicated code.
 * The caller must hold the Logger lock.
 *
 * \param t
 *      Time to be printed in the message.
 * \param message
 *      Main body of the message (everything but the timestamp).
 * \param skipCount
 *      If nonzero, additional message is printed before the main one,
 *      indicating that duplicate messages were suppressed.
 */
void
Logger::printMessage(struct timespec t, const char* message, int skipCount)
{
    FILE* f = getStream();
    if (skipCount > 0) {
        fprintf(f, "%010lu.%09lu (%d duplicates of the following message "
                "were suppressed)\n", t.tv_sec, t.tv_nsec, skipCount);
    }
    fprintf(f, "%010lu.%09lu %s", t.tv_sec, t.tv_nsec, message);
    fflush(f);
}

/**
 * Restore a logger to its default initialized state. Used primarily by tests.
 */
void
Logger::reset()
{
    if (stream != NULL)
        fclose(stream);
    stream = NULL;
    collapseMap.clear();
    collapseIntervalMs = DEFAULT_COLLAPSE_INTERVAL;
    maxCollapseMapSize = DEFAULT_COLLAPSE_MAP_LIMIT;
    testingBufferSize = 0;
}

/**
 * This replaces the default __assert_fail function, which is invoked by the
 * assert macro when there are errors. This function differs from the default
 * __assert_fail function in that it dumps its output to the RAMCloud log file.
 *
 * \param assertion
 *      Textual description of the assertion that failed.
 * \param file
 *      Name of the source file containing the assertion.
 * \param line
 *      Line number of the line containing the assertion, within \a file.
 * \param function
 *      Textual description of the function containing the assertion.
 */
void
Logger::assertionError(const char *assertion, const char *file,
                       unsigned int line, const char *function)
{
    Lock lock(mutex);
    struct timespec now;
    clock_gettime(CLOCK_REALTIME, &now);

    // Compute the body of the log message except for the initial timestamp
    char buffer[strlen(assertion) + 500];
    snprintf(buffer, sizeof(buffer),
            "%s:%d in %s %s %s[%d:%lu]: Assertion `%s' failed.\n",
            file, line, function,
            logModuleNames[RAMCLOUD_CURRENT_LOG_MODULE],
            logLevelNames[ERROR], getpid(), ThreadId::get(), assertion);
    printMessage(now, buffer, 0);
}

/**
 * Signal handler which logs a backtrace and exits.
 *
 * \param signal
 *      Signal number which caused the handler to be invoked.
 * \param info
 *      Details about the cause of the signal. Used to find the
 *      faulting address for segfaults.
 * \param ucontext
 *      CPU context at the time the signal occurred.
 */
static void
criticalErrorHandler(int signal, siginfo_t* info, void* ucontext)
{
    ucontext_t* uc = static_cast<ucontext_t*>(ucontext);
    void* callerAddress =
        reinterpret_cast<void*>(uc->uc_mcontext.gregs[REG_RIP]);

    LOG(ERROR, "Signal %d (%s) at address %p from %p",
        signal, strsignal(signal), info->si_addr,
        callerAddress);

    const int maxFrames = 128;
    void* retAddrs[maxFrames];
    int frames = backtrace(retAddrs, maxFrames);

    // Overwrite sigaction with caller's address.
    retAddrs[1] = callerAddress;

    char** symbols = backtrace_symbols(retAddrs, frames);
    if (symbols == NULL) {
        // If the malloc failed we might be able to get the backtrace out
        // to stderr still.
        backtrace_symbols_fd(retAddrs, frames, 2);
        return;
    }

    LOG(ERROR, "Backtrace:");
    for (int i = 1; i < frames; ++i)
        LOG(ERROR, "%s\n", symbols[i]);

    free(symbols);

    // use abort, rather than exit, to dump core/trap in gdb
    abort();
}

/**
 * Logs a backtrace and exits. For use with std::set_terminate().
 */
static void
terminateHandler()
{
    BACKTRACE(ERROR);

    // use abort, rather than exit, to dump core/trap in gdb
    abort();
}

/**
 * Install handlers for SIGSEGV and std::terminate which log backtraces to
 * the process log file before exiting. This function currently ignores all
 * the thread-safety issues that signals introduce. Since the handlers are
 * only invoked in fatal cases its probably not a big deal.
 */
void
Logger::installCrashBacktraceHandlers()
{
    struct sigaction signalAction;
    signalAction.sa_sigaction = criticalErrorHandler;
    signalAction.sa_flags = SA_RESTART | SA_SIGINFO;

    if (sigaction(SIGSEGV, &signalAction, NULL) != 0)
        LOG(ERROR, "Couldn't set signal handler for SIGSEGV, oh well");

    std::set_terminate(terminateHandler);
}

} // end RAMCloud

/**
 * This replaces the default __assert_fail function, which is invoked by the
 * assert macro when there are errors. This function differs from the default
 * __assert_fail function in that it dumps its output to the RAMCloud log file.
 *
 * \param assertion
 *      Textual description of the assertion that failed.
 * \param file
 *      Name of the source file containing the assertion.
 * \param line
 *      Line number of the line containing the assertion, within \a file.
 * \param function
 *      Textual description of the function containing the assertion.
 */
void
__assert_fail(const char *assertion, const char *file, unsigned int line,
        const char *function)
{
    RAMCloud::Logger::get().assertionError(assertion, file, line, function);
    abort();
}

ext: cc

max_stars_repo_name: jcarreira/ramcloud

max_issues_repo_name: jcarreira/ramcloud

max_forks_repo_name: jcarreira/ramcloud