<commit_before>/*
 * GetFileMessage.hpp
 *
 *  Created on: 27.04.2016
 *      Author: Marc Hartung
 */

#ifndef INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_
#define INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_

#include <fstream>
#include <algorithm>

#include "AbstractMessage.hpp"
#include "../AdditionalTypes.hpp"
#include "../network_impl/SimNetworkFunctions.hpp"

namespace NetOff
{
    class GetFileMessage : public AbstractMessage<InitialClientMessageSpecifyer>
    {
     public:
        GetFileMessage(const int & simId, const std::string & file)
                : AbstractMessage<InitialClientMessageSpecifyer>(InitialClientMessageSpecifyer::GET_FILE),
                  _data(nullptr),
                  _dataSize(0),
                  _req(nullptr),
                  _simId(nullptr),
                  _path(nullptr)
        {
            std::cout << "size: " << _dataSize << "\n";
            _dataSize = sizeof(InitialClientMessageSpecifyer) + sizeof(int) + getStringDataSize(file);
            _data = std::shared_ptr<char>(new char[_dataSize]);
            _req = reinterpret_cast<InitialClientMessageSpecifyer*>(_data.get());
            char * p = saveShiftIntegralInData(InitialClientMessageSpecifyer::GET_FILE, _data.get());
            _simId = reinterpret_cast<int*>(p);
            p = saveShiftIntegralInData<int>(simId, p);
            _path = p;
            saveStringInData(file,_path);
        }

        GetFileMessage(std::shared_ptr<char> & data)
                : AbstractMessage<InitialClientMessageSpecifyer>(InitialClientMessageSpecifyer::GET_FILE),
                  _data(data),
                  _dataSize(0),
                  _req(nullptr),
                  _simId(nullptr),
                  _path(nullptr)
        {
            _req = reinterpret_cast<InitialClientMessageSpecifyer*>(_data.get());
            char * p = shift<InitialClientMessageSpecifyer>(_data.get());
            _simId = reinterpret_cast<int*>(p);
            p = shift<int>(p);
            _path = p;
        }

        GetFileMessage(const GetFileMessage& rhs) = delete;
        GetFileMessage& operator=(const GetFileMessage& rhs) = delete;

        ~GetFileMessage()
        {
            // Do not delete pointer members since they point to memory locations managed by smart pointers.
        }

        int getSimId() const
        {
            return *_simId;
        }

        std::string getFilePath() const
        {
            return createStringFromData(_path);
        }

        char * data() override
        {
            return _data.get();
        }

        const char * data() const override
        {
            return _data.get();
        }

        size_t dataSize() const override
        {
            return _dataSize;
        }

     private:
        std::shared_ptr<char> _data;
        size_t _dataSize;
        InitialClientMessageSpecifyer * _req;
        int * _simId;
        char * _path;
    };

    class GetFileSuccessMessage : public AbstractMessage<InitialServerMessageSpecifyer>
    {
     public:
        GetFileSuccessMessage(const int & simId, const std::string & file)
            : AbstractMessage<InitialServerMessageSpecifyer>(InitialServerMessageSpecifyer::SUCCESS_GET_FILE),
              _data(nullptr),
              _dataSize(0),
              _req(nullptr),
              _simId(nullptr),
              _fileStart(nullptr)
        {
            std::ifstream fileStream;
            std::streampos startPos, endPos;
            fileStream.open(file.c_str(), std::ios::binary);
            startPos = fileStream.tellg();
            fileStream.seekg(0,std::ios::end);
            endPos = fileStream.tellg();

            _dataSize = sizeof(InitialServerMessageSpecifyer) + sizeof(int) + endPos - startPos;
            _data = std::shared_ptr<char>(new char[_dataSize]);
            _req = reinterpret_cast<InitialServerMessageSpecifyer*>(_data.get());
            char * p = saveShiftIntegralInData(InitialServerMessageSpecifyer::SUCCESS_GET_FILE,_data.get());
            _simId = reinterpret_cast<int*>(p);
            p = saveShiftIntegralInData(simId,p);
            _fileStart = p;
            fileStream.seekg(0,std::ios::beg);
            size_t count = sizeof(InitialServerMessageSpecifyer) + sizeof(int);
            size_t blockLength = 512, curReadLength = 1;
            while(fileStream.good() && curReadLength > 0)
            {
                curReadLength = std::min(blockLength, _dataSize - count);
                fileStream.read(p, curReadLength);
                p += curReadLength;
                count += curReadLength;
            }
            fileStream.close();
            if(count != _dataSize)// || endPos != fileStream.tellg())
                throw std::runtime_error("GetFileSuccessMessage: Error during file read.");
        }

        GetFileSuccessMessage(const size_t numBytes, std::shared_ptr<char> & data, const std::string & file)
        : AbstractMessage<InitialServerMessageSpecifyer>(InitialServerMessageSpecifyer::SUCCESS_GET_FILE),
          _data(data),
          _dataSize(numBytes),
          _req(nullptr),
          _simId(nullptr),
          _fileStart(nullptr)
        {
            _req = reinterpret_cast<InitialServerMessageSpecifyer*>(_data.get());
            char * p = _data.get();
            p = shift<InitialServerMessageSpecifyer>(p);
            _simId = reinterpret_cast<int*>(p);
            p = shift<int>(p);

            size_t curReadLength = 1, count = sizeof(InitialServerMessageSpecifyer) + sizeof(int), blockLength = 512;
            std::ofstream fileStream;
            fileStream.open(file.c_str(), std::ios::binary);
            while(fileStream.good() && curReadLength > 0)
            {
                curReadLength = std::min(blockLength, _dataSize - count);
                fileStream.write(p, curReadLength);
                p += curReadLength;
                count += curReadLength;
            }
            fileStream.close();
        }

        GetFileSuccessMessage(const GetFileSuccessMessage& rhs) = delete;
        GetFileSuccessMessage& operator=(const GetFileSuccessMessage& rhs) = delete;

        ~GetFileSuccessMessage()
        {
            // Do not delete pointer members since they point to memory locations managed by smart pointers.
        }

        char * data() override
        {
            return _data.get();
        }

        std::shared_ptr<char> & shared()
        {
            return _data;
        }

        const char * data() const override
        {
            return _data.get();
        }

        size_t dataSize() const override
        {
            return _dataSize;
        }

     private:
        std::shared_ptr<char> _data;
        size_t _dataSize;

        InitialServerMessageSpecifyer * _req;
        int * _simId;
        char * _fileStart;
    };

}

#endif /* INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_ */
<commit_msg>When using make shared to create arrays we need to make sure, that delete[] is called<commit_after>/*
 * GetFileMessage.hpp
 *
 *  Created on: 27.04.2016
 *      Author: Marc Hartung
 */

#ifndef INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_
#define INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_

#include "AbstractMessage.hpp"
#include "AdditionalTypes.hpp"
#include "network_impl/SimNetworkFunctions.hpp"

#include <algorithm>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

namespace NetOff
{
    class GetFileMessage : public AbstractMessage<InitialClientMessageSpecifyer>
    {
     public:
        GetFileMessage(const int & simId, const std::string & file)
                : AbstractMessage<InitialClientMessageSpecifyer>(InitialClientMessageSpecifyer::GET_FILE),
                  _data(nullptr),
                  _dataSize(0),
                  _req(nullptr),
                  _simId(nullptr),
                  _path(nullptr)
        {
            std::cout << "size: " << _dataSize << "\n";
            _dataSize = sizeof(InitialClientMessageSpecifyer) + sizeof(int) + getStringDataSize(file);
            _data = std::shared_ptr<char>(new char[_dataSize], std::default_delete<char[]>());
            _req = reinterpret_cast<InitialClientMessageSpecifyer*>(_data.get());
            char * p = saveShiftIntegralInData(InitialClientMessageSpecifyer::GET_FILE, _data.get());
            _simId = reinterpret_cast<int*>(p);
            p = saveShiftIntegralInData<int>(simId, p);
            _path = p;
            saveStringInData(file, _path);
        }

        GetFileMessage(std::shared_ptr<char> & data)
                : AbstractMessage<InitialClientMessageSpecifyer>(InitialClientMessageSpecifyer::GET_FILE),
                  _data(data),
                  _dataSize(0),
                  _req(nullptr),
                  _simId(nullptr),
                  _path(nullptr)
        {
            _req = reinterpret_cast<InitialClientMessageSpecifyer*>(_data.get());
            char * p = shift<InitialClientMessageSpecifyer>(_data.get());
            _simId = reinterpret_cast<int*>(p);
            p = shift<int>(p);
            _path = p;
        }

        GetFileMessage(const GetFileMessage& rhs) = delete;

        GetFileMessage& operator=(const GetFileMessage& rhs) = delete;

        ~GetFileMessage()
        {
            // Do not delete pointer members since they point to memory locations managed by smart pointers.
        }

        int getSimId() const
        {
            return *_simId;
        }

        std::string getFilePath() const
        {
            return createStringFromData(_path);
        }

        char * data() override
        {
            return _data.get();
        }

        const char * data() const override
        {
            return _data.get();
        }

        size_t dataSize() const override
        {
            return _dataSize;
        }

     private:
        std::shared_ptr<char> _data;
        size_t _dataSize;
        InitialClientMessageSpecifyer * _req;
        int * _simId;
        char * _path;
    };

    class GetFileSuccessMessage : public AbstractMessage<InitialServerMessageSpecifyer>
    {
     public:
        GetFileSuccessMessage(const int & simId, const std::string & file)
                : AbstractMessage<InitialServerMessageSpecifyer>(InitialServerMessageSpecifyer::SUCCESS_GET_FILE),
                  _data(nullptr),
                  _dataSize(0),
                  _req(nullptr),
                  _simId(nullptr),
                  _fileStart(nullptr)
        {
            std::ifstream fileStream;
            std::streampos startPos, endPos;
            fileStream.open(file.c_str(), std::ios::binary);
            startPos = fileStream.tellg();
            fileStream.seekg(0, std::ios::end);
            endPos = fileStream.tellg();

            _dataSize = sizeof(InitialServerMessageSpecifyer) + sizeof(int) + endPos - startPos;
            _data = std::shared_ptr<char>(new char[_dataSize], std::default_delete<char[]>());
            _req = reinterpret_cast<InitialServerMessageSpecifyer*>(_data.get());
            char * p = saveShiftIntegralInData(InitialServerMessageSpecifyer::SUCCESS_GET_FILE, _data.get());
            _simId = reinterpret_cast<int*>(p);
            p = saveShiftIntegralInData(simId, p);
            _fileStart = p;
            fileStream.seekg(0, std::ios::beg);
            size_t count = sizeof(InitialServerMessageSpecifyer) + sizeof(int);
            size_t blockLength = 512, curReadLength = 1;
            while (fileStream.good() && curReadLength > 0)
            {
                curReadLength = std::min(blockLength, _dataSize - count);
                fileStream.read(p, curReadLength);
                p += curReadLength;
                count += curReadLength;
            }
            fileStream.close();
            if (count != _dataSize)  // || endPos != fileStream.tellg())
                throw std::runtime_error("GetFileSuccessMessage: Error during file read.");
        }

        GetFileSuccessMessage(const size_t numBytes, std::shared_ptr<char> & data, const std::string & file)
                : AbstractMessage<InitialServerMessageSpecifyer>(InitialServerMessageSpecifyer::SUCCESS_GET_FILE),
                  _data(data),
                  _dataSize(numBytes),
                  _req(nullptr),
                  _simId(nullptr),
                  _fileStart(nullptr)
        {
            _req = reinterpret_cast<InitialServerMessageSpecifyer*>(_data.get());
            char * p = _data.get();
            p = shift<InitialServerMessageSpecifyer>(p);
            _simId = reinterpret_cast<int*>(p);
            p = shift<int>(p);

            size_t curReadLength = 1, count = sizeof(InitialServerMessageSpecifyer) + sizeof(int), blockLength = 512;
            std::ofstream fileStream;
            fileStream.open(file.c_str(), std::ios::binary);
            while (fileStream.good() && curReadLength > 0)
            {
                curReadLength = std::min(blockLength, _dataSize - count);
                fileStream.write(p, curReadLength);
                p += curReadLength;
                count += curReadLength;
            }
            fileStream.close();
        }

        GetFileSuccessMessage(const GetFileSuccessMessage& rhs) = delete;

        GetFileSuccessMessage& operator=(const GetFileSuccessMessage& rhs) = delete;

        ~GetFileSuccessMessage()
        {
            // Do not delete pointer members since they point to memory locations managed by smart pointers.
        }

        char * data() override
        {
            return _data.get();
        }

        std::shared_ptr<char> & shared()
        {
            return _data;
        }

        const char * data() const override
        {
            return _data.get();
        }

        size_t dataSize() const override
        {
            return _dataSize;
        }

     private:
        std::shared_ptr<char> _data;
        size_t _dataSize;

        InitialServerMessageSpecifyer * _req;
        int * _simId;
        char * _fileStart;
    };

}

#endif /* INCLUDE_MESSAGES_GETFILEMESSAGE_HPP_ */
<|endoftext|>


<commit_before>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_TYPE_TRAITS_HPP
#define MPPP_DETAIL_TYPE_TRAITS_HPP

#include <type_traits>

namespace mppp
{

inline namespace detail
{

// A bunch of useful utilities from C++14/C++17.

// http://en.cppreference.com/w/cpp/types/void_t
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using void_t = std::void_t<Ts...>;

#else

template <typename... Ts>
struct make_void {
    typedef void type;
};

template <typename... Ts>
using void_t = typename make_void<Ts...>::type;

#endif

// http://en.cppreference.com/w/cpp/experimental/is_detected
template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

// http://en.cppreference.com/w/cpp/experimental/nonesuch
struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const &) = delete;
    void operator=(nonesuch const &) = delete;
};

template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;

template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;

// http://en.cppreference.com/w/cpp/types/conjunction
// http://en.cppreference.com/w/cpp/types/disjunction
// http://en.cppreference.com/w/cpp/types/negation
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using conjunction = std::conjunction<Ts...>;

template <typename... Ts>
using disjunction = std::disjunction<Ts...>;

template <typename T>
using negation = std::negation<T>;

#else

template <class...>
struct conjunction : std::true_type {
};

template <class B1>
struct conjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<B1::value != false, conjunction<Bn...>, B1>::type {
};

template <class...>
struct disjunction : std::false_type {
};

template <class B1>
struct disjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct disjunction<B1, Bn...> : std::conditional<B1::value != false, B1, disjunction<Bn...>>::type {
};

template <class B>
struct negation : std::integral_constant<bool, !B::value> {
};

#endif

// Some handy aliases.
template <typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

// Small helpers, like C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template <typename T>
using make_unsigned = typename std::make_unsigned<T>::type;
}
}

#endif
<commit_msg>Add another type trait as implementation detail.<commit_after>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_TYPE_TRAITS_HPP
#define MPPP_DETAIL_TYPE_TRAITS_HPP

#include <type_traits>

namespace mppp
{

inline namespace detail
{

// A bunch of useful utilities from C++14/C++17.

// http://en.cppreference.com/w/cpp/types/void_t
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using void_t = std::void_t<Ts...>;

#else

template <typename... Ts>
struct make_void {
    typedef void type;
};

template <typename... Ts>
using void_t = typename make_void<Ts...>::type;

#endif

// http://en.cppreference.com/w/cpp/experimental/is_detected
template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

// http://en.cppreference.com/w/cpp/experimental/nonesuch
struct nonesuch {
    nonesuch() = delete;
    ~nonesuch() = delete;
    nonesuch(nonesuch const &) = delete;
    void operator=(nonesuch const &) = delete;
};

template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;

template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;

// http://en.cppreference.com/w/cpp/types/conjunction
// http://en.cppreference.com/w/cpp/types/disjunction
// http://en.cppreference.com/w/cpp/types/negation
#if MPPP_CPLUSPLUS >= 201703L

template <typename... Ts>
using conjunction = std::conjunction<Ts...>;

template <typename... Ts>
using disjunction = std::disjunction<Ts...>;

template <typename T>
using negation = std::negation<T>;

#else

template <class...>
struct conjunction : std::true_type {
};

template <class B1>
struct conjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<B1::value != false, conjunction<Bn...>, B1>::type {
};

template <class...>
struct disjunction : std::false_type {
};

template <class B1>
struct disjunction<B1> : B1 {
};

template <class B1, class... Bn>
struct disjunction<B1, Bn...> : std::conditional<B1::value != false, B1, disjunction<Bn...>>::type {
};

template <class B>
struct negation : std::integral_constant<bool, !B::value> {
};

#endif

// Some handy aliases.
template <typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

// Small helpers, like C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;

template <typename T>
using make_unsigned = typename std::make_unsigned<T>::type;

// Detect non-const non-volatile rvalue references.
template <typename T>
using is_ncvrvr
    = conjunction<std::is_rvalue_reference<T>, negation<std::is_const<typename std::remove_reference<T>::type>>,
                  negation<std::is_volatile<typename std::remove_reference<T>::type>>>;
}
}

#endif
<|endoftext|>


<commit_before>/** \file include/mpi_dispatcher/mpi_skel.hpp
** \brief Declares mpi_skel - a structure to simplify master-slave calculations
*/

#ifndef __INCLUDE_MPISKEL_H
#define __INCLUDE_MPISKEL_H

#include <boost/mpi.hpp>
#include <boost/local_function.hpp>
#include <boost/scoped_ptr.hpp>

//#include <type_traits>
#include "mpi_dispatcher.hpp"

namespace pMPI {

template <typename PartType>
struct ComputeWrap {
    PartType *x;
    int complexity;
    ComputeWrap(PartType &y, int complexity = 1):x(&y),complexity(complexity){};
    void run(){x->compute();};
    ComputeWrap(){};
};

template <typename PartType>
struct PrepareWrap {
    PartType *x;
    int complexity;
    PrepareWrap(PartType &y, int complexity = 1):x(&y),complexity(complexity){};
    void run(){x->prepare();};
    PrepareWrap(){};
};

template <typename WrapType>
struct mpi_skel {
    std::vector<WrapType> parts;
    std::map<pMPI::JobId, pMPI::WorkerId> run(const boost::mpi::communicator& comm, bool VerboseOutput = true);
};

/// Master-slave task schedule, associates jobs with workers and executes mpi_dispatcher to run the simulation
template <typename WrapType>
std::map<pMPI::JobId, pMPI::WorkerId> mpi_skel<WrapType>::run(const boost::mpi::communicator& comm, bool VerboseOutput)
{
    int rank = comm.rank();
    int comm_size = comm.size();
    comm.barrier();
    if (rank==0) { std::cout << "Calculating " << parts.size() << " jobs using " << comm_size << " procs." << std::endl; };

    size_t ROOT = 0;
    boost::scoped_ptr<pMPI::MPIMaster> disp;

    if (comm.rank() == ROOT) {
        // prepare one Master on a root process for distributing parts.size() jobs
        std::vector<pMPI::JobId> job_order(parts.size());
        for (size_t i=0; i<job_order.size(); i++) job_order[i] = i;
        int BOOST_LOCAL_FUNCTION_TPL(bind this_, std::size_t l, std::size_t r) {
            return (this_->parts[l].complexity > this_->parts[r].complexity); } BOOST_LOCAL_FUNCTION_NAME_TPL(comp1)
        std::sort(job_order.begin(), job_order.end(), comp1);
        disp.reset(new pMPI::MPIMaster(comm,job_order,true));
    };

    comm.barrier();

    // Start calculating data
    for (pMPI::MPIWorker worker(comm,ROOT);!worker.is_finished();) {
        if (rank == ROOT) disp->order();
        worker.receive_order();
        if (worker.is_working()) { // for a specific worker
            JobId p = worker.current_job();
            if (VerboseOutput) std::cout << "["<<p+1<<"/"<<parts.size()<< "] P" << comm.rank()
                                         << " : part " << p << " [" << parts[p].complexity << "] run;" << std::endl;
            parts[p].run();
            worker.report_job_done();
        };
        if (rank == ROOT) disp->check_workers(); // check if there are free workers
    };
    // at this moment all communication is finished
    //comm.barrier();
    MPI_Barrier(MPI_COMM_WORLD);
    // Now spread the information, who did what.
	if (VerboseOutput && rank==ROOT) std::cout << "done." << std::endl;
    comm.barrier();
    std::map<pMPI::JobId, pMPI::WorkerId> job_map;
    if (rank == ROOT) {
        job_map = disp -> DispatchMap;
        std::vector<pMPI::JobId> jobs(job_map.size());
        std::vector<pMPI::WorkerId> workers(job_map.size());

        std::map<pMPI::JobId, pMPI::WorkerId>::const_iterator it = job_map.begin();
        for (int i=0; i<workers.size(); i++) {
            jobs[i] = it->first;
            workers[i] = it->second;
            ++it;
        }
        boost::mpi::broadcast(comm, jobs, ROOT);
        boost::mpi::broadcast(comm, workers, ROOT);
    }
    else {
        std::vector<pMPI::JobId> jobs(parts.size());
        boost::mpi::broadcast(comm, jobs, ROOT);
        std::vector<pMPI::WorkerId> workers(parts.size());
        boost::mpi::broadcast(comm, workers, ROOT);
        for (size_t i=0; i<jobs.size(); i++) job_map[jobs[i]] = workers[i];
    }
    return job_map;
}

}; // end of namespace MPI

#endif
<commit_msg>Add missing vector header include for boost serialization<commit_after>/** \file include/mpi_dispatcher/mpi_skel.hpp
** \brief Declares mpi_skel - a structure to simplify master-slave calculations
*/

#ifndef __INCLUDE_MPISKEL_H
#define __INCLUDE_MPISKEL_H

#include <boost/mpi.hpp>
#include <boost/local_function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/serialization/vector.hpp>

//#include <type_traits>
#include "mpi_dispatcher.hpp"

namespace pMPI {

template <typename PartType>
struct ComputeWrap {
    PartType *x;
    int complexity;
    ComputeWrap(PartType &y, int complexity = 1):x(&y),complexity(complexity){};
    void run(){x->compute();};
    ComputeWrap(){};
};

template <typename PartType>
struct PrepareWrap {
    PartType *x;
    int complexity;
    PrepareWrap(PartType &y, int complexity = 1):x(&y),complexity(complexity){};
    void run(){x->prepare();};
    PrepareWrap(){};
};

template <typename WrapType>
struct mpi_skel {
    std::vector<WrapType> parts;
    std::map<pMPI::JobId, pMPI::WorkerId> run(const boost::mpi::communicator& comm, bool VerboseOutput = true);
};

/// Master-slave task schedule, associates jobs with workers and executes mpi_dispatcher to run the simulation
template <typename WrapType>
std::map<pMPI::JobId, pMPI::WorkerId> mpi_skel<WrapType>::run(const boost::mpi::communicator& comm, bool VerboseOutput)
{
    int rank = comm.rank();
    int comm_size = comm.size();
    comm.barrier();
    if (rank==0) { std::cout << "Calculating " << parts.size() << " jobs using " << comm_size << " procs." << std::endl; };

    size_t ROOT = 0;
    boost::scoped_ptr<pMPI::MPIMaster> disp;

    if (comm.rank() == ROOT) {
        // prepare one Master on a root process for distributing parts.size() jobs
        std::vector<pMPI::JobId> job_order(parts.size());
        for (size_t i=0; i<job_order.size(); i++) job_order[i] = i;
        int BOOST_LOCAL_FUNCTION_TPL(bind this_, std::size_t l, std::size_t r) {
            return (this_->parts[l].complexity > this_->parts[r].complexity); } BOOST_LOCAL_FUNCTION_NAME_TPL(comp1)
        std::sort(job_order.begin(), job_order.end(), comp1);
        disp.reset(new pMPI::MPIMaster(comm,job_order,true));
    };

    comm.barrier();

    // Start calculating data
    for (pMPI::MPIWorker worker(comm,ROOT);!worker.is_finished();) {
        if (rank == ROOT) disp->order();
        worker.receive_order();
        if (worker.is_working()) { // for a specific worker
            JobId p = worker.current_job();
            if (VerboseOutput) std::cout << "["<<p+1<<"/"<<parts.size()<< "] P" << comm.rank()
                                         << " : part " << p << " [" << parts[p].complexity << "] run;" << std::endl;
            parts[p].run();
            worker.report_job_done();
        };
        if (rank == ROOT) disp->check_workers(); // check if there are free workers
    };
    // at this moment all communication is finished
    //comm.barrier();
    MPI_Barrier(MPI_COMM_WORLD);
    // Now spread the information, who did what.
	if (VerboseOutput && rank==ROOT) std::cout << "done." << std::endl;
    comm.barrier();
    std::map<pMPI::JobId, pMPI::WorkerId> job_map;
    if (rank == ROOT) {
        job_map = disp -> DispatchMap;
        std::vector<pMPI::JobId> jobs(job_map.size());
        std::vector<pMPI::WorkerId> workers(job_map.size());

        std::map<pMPI::JobId, pMPI::WorkerId>::const_iterator it = job_map.begin();
        for (int i=0; i<workers.size(); i++) {
            jobs[i] = it->first;
            workers[i] = it->second;
            ++it;
        }
        boost::mpi::broadcast(comm, jobs, ROOT);
        boost::mpi::broadcast(comm, workers, ROOT);
    }
    else {
        std::vector<pMPI::JobId> jobs(parts.size());
        boost::mpi::broadcast(comm, jobs, ROOT);
        std::vector<pMPI::WorkerId> workers(parts.size());
        boost::mpi::broadcast(comm, workers, ROOT);
        for (size_t i=0; i<jobs.size(); i++) job_map[jobs[i]] = workers[i];
    }
    return job_map;
}

}; // end of namespace MPI

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *   Email: russ@q12.org   Web: www.q12.org                              *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include "ode/ode.h"
#include "ode/odemath.h"
#include "ode/matrix.h"

#define _I(i,j) I[(i)*4+(j)]

// return 1 if ok, 0 if bad

static int checkMass (dMass *m)
{
  if (m->mass <= 0) {
    dDEBUGMSG ("mass must be > 0");
    return 0;
  }
  if (!dIsPositiveDefinite (m->I,3)) {
    dDEBUGMSG ("inertia must be positive definite");
    return 0;
  }

  // verify that the center of mass position is consistent with the mass
  // and inertia matrix. this is done by checking that the inertia around
  // the center of mass is also positive definite. from the comment in
  // dMassTranslate(), if the body is translated so that its center of mass
  // is at the point of reference, then the new inertia is:
  //   I + mass*crossmat(c)^2
  // note that requiring this to be positive definite is exactly equivalent
  // to requiring that the spatial inertia matrix
  //   [ mass*eye(3,3)   M*crossmat(c)^T ]
  //   [ M*crossmat(c)   I               ]
  // is positive definite, given that I is PD and mass>0. see the theorem
  // about partitioned PD matrices for proof.

  dMatrix3 I2,chat;
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  dMULTIPLY0_333 (I2,chat,chat);
  for (int i=0; i<12; i++) I2[i] = m->I[i] + m->mass*I2[i];
  if (!dIsPositiveDefinite (I2,3)) {
    dDEBUGMSG ("center of mass inconsistent with mass parameters");
    return 0;
  }
  return 1;
}

void dMassSetZero (dMass *m)
{
  dAASSERT (m);
  m->mass = REAL(0.0);
  dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
  dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
}

void dMassSetParameters (dMass *m, dReal themass,
			 dReal cgx, dReal cgy, dReal cgz,
			 dReal I11, dReal I22, dReal I33,
			 dReal I12, dReal I13, dReal I23)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = themass;
  m->c[0] = cgx;
  m->c[1] = cgy;
  m->c[2] = cgz;
  m->_I(0,0) = I11;
  m->_I(1,1) = I22;
  m->_I(2,2) = I33;
  m->_I(0,1) = I12;
  m->_I(0,2) = I13;
  m->_I(1,2) = I23;
  m->_I(1,0) = I12;
  m->_I(2,0) = I13;
  m->_I(2,1) = I23;
  checkMass (m);
}

void dMassSetSphere (dMass *m, dReal density, dReal radius)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = (4.0/3.0) * M_PI * radius*radius*radius * density;
  dReal II = 0.4 * m->mass * radius*radius;
  m->_I(0,0) = II;
  m->_I(1,1) = II;
  m->_I(2,2) = II;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinder (dMass *m, dReal density, int direction,
			     dReal a, dReal b)
{
  dReal M1,M2,Ia,Ib;
  dAASSERT (m);
  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
  dMassSetZero (m);
  M1 = M_PI*a*a*b*density;		// cylinder mass
  M2 = (4.0/3.0)*M_PI*a*a*a*density;	// total cap mass
  m->mass = M1+M2;
  Ia = M1*(0.25*a*a + (1.0/12.0)*b*b) + M2*(0.4*a*a + 0.5*b*b);
  Ib = (M1*0.5 + M2*0.4)*a*a;
  m->_I(0,0) = Ia;
  m->_I(1,1) = Ia;
  m->_I(2,2) = Ia;
  m->_I(direction-1,direction-1) = Ib;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetBox (dMass *m, dReal density,
		  dReal lx, dReal ly, dReal lz)
{
  dAASSERT (m);
  dMassSetZero (m);
  dReal M = lx*ly*lz*density;
  m->mass = M;
  m->_I(0,0) = M/12.0 * (ly*ly + lz*lz);
  m->_I(1,1) = M/12.0 * (lx*lx + lz*lz);
  m->_I(2,2) = M/12.0 * (lx*lx + ly*ly);

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdjust (dMass *m, dReal newmass)
{
  dAASSERT (m);
  dReal scale = newmass / m->mass;
  m->mass = newmass;
  for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
{
  // if the body is translated by `a' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
  //
  // where c is the existing center of mass and I is the old inertia.

  int i,j;
  dMatrix3 ahat,chat,t1,t2;
  dReal a[3];

  dAASSERT (m);

  // adjust inertia matrix
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  a[0] = x + m->c[0];
  a[1] = y + m->c[1];
  a[2] = z + m->c[2];
  dSetZero (ahat,12);
  dCROSSMAT (ahat,a,4,+,-);
  dMULTIPLY0_333 (t1,ahat,ahat);
  dMULTIPLY0_333 (t2,chat,chat);
  for (i=0; i<3; i++) for (j=0; j<3; j++)
    m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // adjust center of mass
  m->c[0] += x;
  m->c[1] += y;
  m->c[2] += z;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassRotate (dMass *m, const dMatrix3 R)
{
  // if the body is rotated by `R' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   R * I * R'
  //
  // where I is the old inertia.

  dMatrix3 t1;
  dReal t2[3];

  dAASSERT (m);

  // rotate inertia matrix
  dMULTIPLY2_333 (t1,m->I,R);
  dMULTIPLY0_333 (m->I,R,t1);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // rotate center of mass
  dMULTIPLY0_331 (t2,R,m->c);
  m->c[0] = t2[0];
  m->c[1] = t2[1];
  m->c[2] = t2[2];

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdd (dMass *a, dMass *b)
{
  int i;
  dAASSERT (a && b);
  dReal denom = dRecip (a->mass + b->mass);
  for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
  a->mass += b->mass;
  for (i=0; i<12; i++) a->I[i] += b->I[i];
}
<commit_msg>small fix<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *   Email: russ@q12.org   Web: www.q12.org                              *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include "ode/ode.h"
#include "ode/odemath.h"
#include "ode/matrix.h"

#define _I(i,j) I[(i)*4+(j)]

// return 1 if ok, 0 if bad

static int checkMass (dMass *m)
{
  if (m->mass <= 0) {
    dDEBUGMSG ("mass must be > 0");
    return 0;
  }
  if (!dIsPositiveDefinite (m->I,3)) {
    dDEBUGMSG ("inertia must be positive definite");
    return 0;
  }

  // verify that the center of mass position is consistent with the mass
  // and inertia matrix. this is done by checking that the inertia around
  // the center of mass is also positive definite. from the comment in
  // dMassTranslate(), if the body is translated so that its center of mass
  // is at the point of reference, then the new inertia is:
  //   I + mass*crossmat(c)^2
  // note that requiring this to be positive definite is exactly equivalent
  // to requiring that the spatial inertia matrix
  //   [ mass*eye(3,3)   M*crossmat(c)^T ]
  //   [ M*crossmat(c)   I               ]
  // is positive definite, given that I is PD and mass>0. see the theorem
  // about partitioned PD matrices for proof.

  dMatrix3 I2,chat;
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  dMULTIPLY0_333 (I2,chat,chat);
  for (int i=0; i<12; i++) I2[i] = m->I[i] + m->mass*I2[i];
  if (!dIsPositiveDefinite (I2,3)) {
    dDEBUGMSG ("center of mass inconsistent with mass parameters");
    return 0;
  }
  return 1;
}

void dMassSetZero (dMass *m)
{
  dAASSERT (m);
  m->mass = REAL(0.0);
  dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
  dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
}

void dMassSetParameters (dMass *m, dReal themass,
			 dReal cgx, dReal cgy, dReal cgz,
			 dReal I11, dReal I22, dReal I33,
			 dReal I12, dReal I13, dReal I23)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = themass;
  m->c[0] = cgx;
  m->c[1] = cgy;
  m->c[2] = cgz;
  m->_I(0,0) = I11;
  m->_I(1,1) = I22;
  m->_I(2,2) = I33;
  m->_I(0,1) = I12;
  m->_I(0,2) = I13;
  m->_I(1,2) = I23;
  m->_I(1,0) = I12;
  m->_I(2,0) = I13;
  m->_I(2,1) = I23;
  checkMass (m);
}

void dMassSetSphere (dMass *m, dReal density, dReal radius)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = (4.0/3.0) * M_PI * radius*radius*radius * density;
  dReal II = 0.4 * m->mass * radius*radius;
  m->_I(0,0) = II;
  m->_I(1,1) = II;
  m->_I(2,2) = II;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinder (dMass *m, dReal density, int direction,
			     dReal a, dReal b)
{
  dReal M1,M2,Ia,Ib;
  dAASSERT (m);
  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
  dMassSetZero (m);
  M1 = M_PI*a*a*b*density;		// cylinder mass
  M2 = (4.0/3.0)*M_PI*a*a*a*density;	// total cap mass
  m->mass = M1+M2;
  Ia = M1*(0.25*a*a + (1.0/12.0)*b*b) + M2*(0.4*a*a + 0.5*b*b);
  Ib = (M1*0.5 + M2*0.4)*a*a;
  m->_I(0,0) = Ia;
  m->_I(1,1) = Ia;
  m->_I(2,2) = Ia;
  m->_I(direction-1,direction-1) = Ib;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetBox (dMass *m, dReal density,
		  dReal lx, dReal ly, dReal lz)
{
  dAASSERT (m);
  dMassSetZero (m);
  dReal M = lx*ly*lz*density;
  m->mass = M;
  m->_I(0,0) = M/12.0 * (ly*ly + lz*lz);
  m->_I(1,1) = M/12.0 * (lx*lx + lz*lz);
  m->_I(2,2) = M/12.0 * (lx*lx + ly*ly);

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdjust (dMass *m, dReal newmass)
{
  dAASSERT (m);
  dReal scale = newmass / m->mass;
  m->mass = newmass;
  for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
{
  // if the body is translated by `a' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
  //
  // where c is the existing center of mass and I is the old inertia.

  int i,j;
  dMatrix3 ahat,chat,t1,t2;
  dReal a[3];

  dAASSERT (m);

  // adjust inertia matrix
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  a[0] = x + m->c[0];
  a[1] = y + m->c[1];
  a[2] = z + m->c[2];
  dSetZero (ahat,12);
  dCROSSMAT (ahat,a,4,+,-);
  dMULTIPLY0_333 (t1,ahat,ahat);
  dMULTIPLY0_333 (t2,chat,chat);
  for (i=0; i<3; i++) for (j=0; j<3; j++)
    m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // adjust center of mass
  m->c[0] += x;
  m->c[1] += y;
  m->c[2] += z;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassRotate (dMass *m, const dMatrix3 R)
{
  // if the body is rotated by `R' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   R * I * R'
  //
  // where I is the old inertia.

  dMatrix3 t1;
  dReal t2[3];

  dAASSERT (m);

  // rotate inertia matrix
  dMULTIPLY2_333 (t1,m->I,R);
  dMULTIPLY0_333 (m->I,R,t1);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // rotate center of mass
  dMULTIPLY0_331 (t2,R,m->c);
  m->c[0] = t2[0];
  m->c[1] = t2[1];
  m->c[2] = t2[2];

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdd (dMass *a, const dMass *b)
{
  int i;
  dAASSERT (a && b);
  dReal denom = dRecip (a->mass + b->mass);
  for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
  a->mass += b->mass;
  for (i=0; i<12; i++) a->I[i] += b->I[i];
}
<|endoftext|>


<commit_before>#include "HelloWorld5Module.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>
#include "NFComm/NFCore/NFIComponent.h"
#include "NFCTestComponent.h"

bool HelloWorld5Module::Init()
{
    //ʼ
    std::cout << "Hello, world5, Init" << std::endl;

    return true;
}

bool HelloWorld5Module::AfterInit()
{
    //ʼ
    std::cout << "Hello, world5, AfterInit, ThreadID: " << std::this_thread::get_id() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////

	//int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent, HelloWorld5Module>(this, &HelloWorld5Module::OnSyncEvent);
	int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent>(this, &HelloWorld5Module::OnSyncEvent);

	for (int i = 0; i < 20; ++i)
	{
		m_pEventProcessModule->SendActorMsg(nActorID, 555, NFIDENTID(), boost::lexical_cast<std::string>(i));
	}

    std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////

    return true;
}

int HelloWorld5Module::OnSyncEvent(const NFIDENTID& self, const int nActorID, const int event, const std::string& arg)
{
    //¼ص
    std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

    return 0;
}

bool HelloWorld5Module::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world5, Execute" << std::endl;

    return true;
}

bool HelloWorld5Module::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world5, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld5Module::Shut()
{
    //ʼ
    std::cout << "Hello, world5, Shut" << std::endl;

    return true;
}
<commit_msg>modified actor tutorial for new actor model<commit_after>#include "HelloWorld5Module.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>
#include "NFComm/NFCore/NFIComponent.h"
#include "NFCTestComponent.h"

bool HelloWorld5Module::Init()
{
    //ʼ
    std::cout << "Hello, world5, Init" << std::endl;

    return true;
}

bool HelloWorld5Module::AfterInit()
{
    //ʼ
    std::cout << "Hello, world5, AfterInit, ThreadID: " << std::this_thread::get_id() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////
	for (int i = 0; i < 50000; ++i)
	{
		int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent>(this, &HelloWorld5Module::OnSyncEvent);
		m_pEventProcessModule->SendActorMsg(nActorID, 555, NFIDENTID(), boost::lexical_cast<std::string>(i));
	}

    std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

    return true;
}

int HelloWorld5Module::OnSyncEvent(const NFIDENTID& self, const int nActorID, const int event, const std::string& arg)
{
    //¼ص
    std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

    return 0;
}

bool HelloWorld5Module::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world5, Execute" << std::endl;

    return true;
}

bool HelloWorld5Module::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world5, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld5Module::Shut()
{
    //ʼ
    std::cout << "Hello, world5, Shut" << std::endl;

    return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>

using namespace std;

int main(void)
{
	int a, b;
	cin >> a >> b;

	if (b == 0)
		throw runtime_error("divisor is 0");

	cout << static_cast<double>(a) / b << endl;

	return 0;
}
<commit_msg>Update ex5_24.cpp<commit_after>#include <iostream>
#include <stdexcept>

//
//  When a zero entered, the code below would crash with feedback as :
//  "Unhandled exception at 0x75834598 in just_for_cpp.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0054F9F4."
//
//  Tested on Windows 8.1 + Vs 2013
//

int main(void)
{
    int i, j;
    std::cin >> i >> j;
    if (j == 0)
        throw std::runtime_error("divisor is 0");
    std::cout << i / j << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#ifndef REQL_REQL_SOCKET_HPP_
#define REQL_REQL_SOCKET_HPP_

#include <atomic>
#include <cerrno>
#include <memory>
#include <thread>

#ifdef __MINGW32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#endif

namespace _ReQL {

template <class socket_e, class str_t>
int connect(const str_t &addr, const str_t &port) {
  struct addrinfo hints;
  struct addrinfo *result, *rp;

  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0;
  hints.ai_protocol = IPPROTO_TCP;

  if (getaddrinfo(addr.c_str(), port.c_str(), &hints, &result) != 0) {
    throw socket_e("");  // TODO
  }

  int sock = -1;

  for (rp = result; rp != nullptr; rp = rp->ai_next) {
    sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

    if (sock == -1) continue;

    if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;

    ::close(sock);
  }

  freeaddrinfo(result);

  if (rp) {
    return sock;
  }

  throw socket_e("");  // TODO
}

template <class socket_e>
class Socket_t {
public:
  Socket_t() : p_sock(-1) {}

  template <class str_t>
  Socket_t(const str_t &addr, const str_t &port) :
    p_sock(connect<socket_e, str_t>(addr, port)) {}

  ~Socket_t() {
    close();
  }

  bool isOpen() const {
    return p_sock.load() >= 0;
  }

  void close() {
    int sock = p_sock.exchange(-1);
    if (sock >= 0) {
      ::close(sock);
    }
  }

  ImmutableString read() {
    int sock = load();
    wait_read();
    ssize_t size = 0;
    socklen_t opt_len = sizeof(ssize_t);
    auto sts = getsockopt(sock, SOL_SOCKET, SO_NREAD, &size, &opt_len);
    if (sts < 0) {
      switch (errno) {
        case EBADF:
        case EFAULT:
        case EINVAL:
        case ENOBUFS:
        case ENOMEM:
        case ENOPROTOOPT:
        case ENOTSOCK: {
          throw socket_e("");  // TODO
        }
        default: {
          throw socket_e("");  // TODO
        }
      }
      throw std::exception();
    }
    std::unique_ptr<char> buffer(new char[static_cast<size_t>(size)]);
    size = recvfrom(sock, buffer.get(), static_cast<size_t>(size), 0, nullptr, nullptr);
    if (size < 0) {
      throw socket_e("");  // TODO
    }
    return ImmutableString(buffer.get(), static_cast<size_t>(size));
  }

  void write(const ImmutableString &out) {
    int sock = load();
    wait_write();
    send(sock, out.c_str(), out.size(), 0);
  }

private:
  bool poll(bool read, bool write) {
    int sock = load();
    timeval to = {0, 0};
    fd_set set;
    FD_ZERO(&set);
    FD_SET(sock, &set);
    auto sts = ::select(sock + 1,
                        read ? &set : nullptr,
                        write ? &set : nullptr,
                        &set, &to);
    if (sts == EAGAIN) return false;
    if (sts >= sock) return true;
  }

  void wait_read() {
    while (!poll(true, false)) {
      std::this_thread::yield();
    }
  }

  void wait_write() {
    while (!poll(false, true)) {
      std::this_thread::yield();
    }
  }

  int load() {
    int sock = p_sock.load();
    if (sock < 0) {
      throw socket_e("");  // TODO
    }
    return sock;
  }

  std::atomic<int> p_sock;
};

}  // namespace _ReQL

#endif  // REQL_REQL_SOCKET_HPP_
<commit_msg>Template socket on errors.<commit_after>/*
Copyright 2015 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#ifndef REQL_REQL_SOCKET_HPP_
#define REQL_REQL_SOCKET_HPP_

#include <atomic>
#include <cerrno>
#include <memory>
#include <thread>

#ifdef __MINGW32__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#endif

namespace _ReQL {

template <class addr_t, class port_t, class socket_e>
int connect(const addr_t &addr, const port_t &port) {
  struct addrinfo hints;
  struct addrinfo *result, *rp;

  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0;
  hints.ai_protocol = IPPROTO_TCP;

  int sts = 0;

  if ((sts = getaddrinfo(addr.c_str(), port.c_str(), &hints, &result)) != 0) {
    throw socket_e(gai_strerror(sts));
  }

  int sock = -1;

  for (rp = result; rp != nullptr; rp = rp->ai_next) {
    sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

    if (sock == -1) continue;

    if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;

    ::close(sock);
  }

  freeaddrinfo(result);

  if (rp) {
    return sock;
  }

  throw socket_e("");  // TODO
}

template <class socket_e>
class Socket_t {
public:
  Socket_t() : p_sock(-1) {}

  template <class addr_t, class port_t>
  Socket_t(const addr_t &addr, const port_t &port) :
    p_sock(connect<addr_t, port_t, socket_e>(addr, port)) {}

  ~Socket_t() {
    close();
  }

  bool isOpen() const {
    return p_sock.load() >= 0;
  }

  void close() {
    int sock = p_sock.exchange(-1);
    if (sock >= 0) {
      ::close(sock);
    }
  }

  ImmutableString read() {
    int sock = load();
    wait_read();
    ssize_t size = 0;
    socklen_t opt_len = sizeof(ssize_t);
    auto sts = getsockopt(sock, SOL_SOCKET, SO_NREAD, &size, &opt_len);
    if (sts < 0) {
      switch (errno) {
        case EBADF:
        case EFAULT:
        case EINVAL:
        case ENOBUFS:
        case ENOMEM:
        case ENOPROTOOPT:
        case ENOTSOCK: {
          throw socket_e("");  // TODO
        }
        default: {
          throw socket_e("");  // TODO
        }
      }
      throw std::exception();
    }
    std::unique_ptr<char> buffer(new char[static_cast<size_t>(size)]);
    size = recvfrom(sock, buffer.get(), static_cast<size_t>(size), MSG_WAITALL, nullptr, nullptr);
    if (size == 0) {
      throw socket_e("");  // TODO
    } else if (size < 0) {
      switch (errno) {
        case EAGAIN: {
          return ImmutableString();
        }
        case EBADF:
        case ECONNRESET:
        case EFAULT:
        case EINTR:
        case EINVAL:
        case ENOBUFS:
        case ENOTCONN:
        case ENOTSOCK:
        case EOPNOTSUPP:
        case ETIMEDOUT: {
          throw socket_e("");  // TODO
        }
        default: {
          throw socket_e("");  // TODO
        }
      }
      throw std::exception();
    }
    return ImmutableString(buffer.get(), static_cast<size_t>(size));
  }

  void write(const ImmutableString &out) {
    int sock = load();
    wait_write();
    send(sock, out.c_str(), out.size(), 0);
  }

private:
  bool poll(bool read = true) {
    int sock = load();
    timeval to = {0, 0};
    fd_set set;
    FD_ZERO(&set);
    FD_SET(sock, &set);
    auto sts = ::select(sock + 1,
                        read ? &set : nullptr,
                        read ? nullptr : &set,
                        &set, &to);
    if (sts == 0) {
      return false;
    } else if (sts < 0) {
      switch (errno) {
        case EAGAIN:
        case EBADF:
        case EINTR:
        case EINVAL:{
          throw socket_e("");  // TODO
        }
        default: {
          throw socket_e("");  // TODO
        }
      }
      throw std::exception();
    }
    return true;
  }

  void wait_read() {
    while (!poll()) {
      std::this_thread::yield();
    }
  }

  void wait_write() {
    while (!poll(false)) {
      std::this_thread::yield();
    }
  }

  int load() {
    int sock = p_sock.load();
    if (sock < 0) {
      throw socket_e("");  // TODO
    }
    return sock;
  }

  std::atomic<int> p_sock;
};

}  // namespace _ReQL

#endif  // REQL_REQL_SOCKET_HPP_
<|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2018-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Chapter.h"

#include "database/SqliteTools.h"
#include "database/SqliteQuery.h"
#include "Media.h"

namespace medialibrary
{

const std::string Chapter::Table::Name = "Chapter";
const std::string Chapter::Table::PrimaryKeyColumn = "id_chapter";
int64_t Chapter::* const Chapter::Table::PrimaryKey = &Chapter::m_id;

void Chapter::createTable( sqlite::Connection* dbConn )
{
    return sqlite::Tools::executeRequest( dbConn,
                                          schema( Table::Name, Settings::DbModelVersion ) );
}

std::string Chapter::schema( const std::string& tableName, uint32_t )
{
    UNUSED_IN_RELEASE( tableName );

    assert( tableName == Table::Name );
    return "CREATE TABLE " + Table::Name +
    "("
        + Table::PrimaryKeyColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
        "offset INTEGER NOT NULL,"
        "duration INTEGER NOT NULL,"
        "name TEXT,"
        "media_id INTEGER,"
        "FOREIGN KEY(media_id) REFERENCES " +
            Media::Table::Name + "(" + Media::Table::PrimaryKeyColumn + ")"
            " ON DELETE CASCADE"
    ")";
}

bool Chapter::checkDbModel( MediaLibraryPtr ml )
{
    return sqlite::Tools::checkTableSchema( ml->getConn(),
                                       schema( Table::Name, Settings::DbModelVersion ),
                                       Table::Name );
}

std::shared_ptr<Chapter> Chapter::create( MediaLibraryPtr ml, int64_t offset,
                                          int64_t duration, std::string name,
                                          int64_t mediaId )
{
    static const std::string req = "INSERT INTO " + Table::Name +
            "(offset, duration, name, media_id) VALUES(?, ?, ?, ?)";
    auto self = std::make_shared<Chapter>( ml, offset, duration,
                                           std::move( name ) );
    if ( insert( ml, self, req, offset, duration, self->m_name, mediaId ) == false )
        return nullptr;
    return self;
}

Query<IChapter> Chapter::fromMedia( MediaLibraryPtr ml, int64_t mediaId,
                                    const QueryParameters* params )
{
    std::string req = "FROM " + Table::Name + " WHERE media_id = ?";
    std::string orderBy = "ORDER BY ";
    auto desc = params != nullptr ? params->desc : false;
    auto sort = params != nullptr ? params->sort : SortingCriteria::Default;

    switch ( sort )
    {
        case SortingCriteria::Alpha:
            orderBy += "name";
            break;
        case SortingCriteria::Duration:
            orderBy += "duration";
            desc = !desc;
            break;
        default:
            LOG_WARN( "Unsupported sorting criteria ",
                      static_cast<std::underlying_type<SortingCriteria>::type>( sort ),
                      " falling back to default (by offset)" );
            /* fall-through */
        case SortingCriteria::Default:
            orderBy += "offset";
            break;
    }
    if ( desc == true )
        orderBy += " DESC";

    return make_query<Chapter, IChapter>( ml, "*", req, orderBy, mediaId );
}

Chapter::Chapter( MediaLibraryPtr ml, sqlite::Row& row )
    : m_ml( ml )
    , m_id( row.extract<decltype(m_id)>() )
    , m_offset( row.extract<decltype(m_offset)>() )
    , m_duration( row.extract<decltype(m_offset)>() )
    , m_name( row.extract<decltype(m_name)>() )
{
    // Simply check that the media_id row is present, until we eventually store it
    assert( row.extract<int64_t>() );
    assert( row.hasRemainingColumns() == false );
}

Chapter::Chapter( MediaLibraryPtr ml, int64_t offset, int64_t duration,
                  std::string name )
    : m_ml( ml )
    , m_id( 0 )
    , m_offset( offset )
    , m_duration( duration )
    , m_name( std::move( name ) )
{
}

const std::string& Chapter::name() const
{
    return m_name;
}

int64_t Chapter::offset() const
{
    return m_offset;
}

int64_t Chapter::duration() const
{
    return m_duration;
}

}
<commit_msg>Chapter: Remove useless return<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2018-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Chapter.h"

#include "database/SqliteTools.h"
#include "database/SqliteQuery.h"
#include "Media.h"

namespace medialibrary
{

const std::string Chapter::Table::Name = "Chapter";
const std::string Chapter::Table::PrimaryKeyColumn = "id_chapter";
int64_t Chapter::* const Chapter::Table::PrimaryKey = &Chapter::m_id;

void Chapter::createTable( sqlite::Connection* dbConn )
{
    sqlite::Tools::executeRequest( dbConn, schema( Table::Name,
                                                   Settings::DbModelVersion ) );
}

std::string Chapter::schema( const std::string& tableName, uint32_t )
{
    UNUSED_IN_RELEASE( tableName );

    assert( tableName == Table::Name );
    return "CREATE TABLE " + Table::Name +
    "("
        + Table::PrimaryKeyColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
        "offset INTEGER NOT NULL,"
        "duration INTEGER NOT NULL,"
        "name TEXT,"
        "media_id INTEGER,"
        "FOREIGN KEY(media_id) REFERENCES " +
            Media::Table::Name + "(" + Media::Table::PrimaryKeyColumn + ")"
            " ON DELETE CASCADE"
    ")";
}

bool Chapter::checkDbModel( MediaLibraryPtr ml )
{
    return sqlite::Tools::checkTableSchema( ml->getConn(),
                                       schema( Table::Name, Settings::DbModelVersion ),
                                       Table::Name );
}

std::shared_ptr<Chapter> Chapter::create( MediaLibraryPtr ml, int64_t offset,
                                          int64_t duration, std::string name,
                                          int64_t mediaId )
{
    static const std::string req = "INSERT INTO " + Table::Name +
            "(offset, duration, name, media_id) VALUES(?, ?, ?, ?)";
    auto self = std::make_shared<Chapter>( ml, offset, duration,
                                           std::move( name ) );
    if ( insert( ml, self, req, offset, duration, self->m_name, mediaId ) == false )
        return nullptr;
    return self;
}

Query<IChapter> Chapter::fromMedia( MediaLibraryPtr ml, int64_t mediaId,
                                    const QueryParameters* params )
{
    std::string req = "FROM " + Table::Name + " WHERE media_id = ?";
    std::string orderBy = "ORDER BY ";
    auto desc = params != nullptr ? params->desc : false;
    auto sort = params != nullptr ? params->sort : SortingCriteria::Default;

    switch ( sort )
    {
        case SortingCriteria::Alpha:
            orderBy += "name";
            break;
        case SortingCriteria::Duration:
            orderBy += "duration";
            desc = !desc;
            break;
        default:
            LOG_WARN( "Unsupported sorting criteria ",
                      static_cast<std::underlying_type<SortingCriteria>::type>( sort ),
                      " falling back to default (by offset)" );
            /* fall-through */
        case SortingCriteria::Default:
            orderBy += "offset";
            break;
    }
    if ( desc == true )
        orderBy += " DESC";

    return make_query<Chapter, IChapter>( ml, "*", req, orderBy, mediaId );
}

Chapter::Chapter( MediaLibraryPtr ml, sqlite::Row& row )
    : m_ml( ml )
    , m_id( row.extract<decltype(m_id)>() )
    , m_offset( row.extract<decltype(m_offset)>() )
    , m_duration( row.extract<decltype(m_offset)>() )
    , m_name( row.extract<decltype(m_name)>() )
{
    // Simply check that the media_id row is present, until we eventually store it
    assert( row.extract<int64_t>() );
    assert( row.hasRemainingColumns() == false );
}

Chapter::Chapter( MediaLibraryPtr ml, int64_t offset, int64_t duration,
                  std::string name )
    : m_ml( ml )
    , m_id( 0 )
    , m_offset( offset )
    , m_duration( duration )
    , m_name( std::move( name ) )
{
}

const std::string& Chapter::name() const
{
    return m_name;
}

int64_t Chapter::offset() const
{
    return m_offset;
}

int64_t Chapter::duration() const
{
    return m_duration;
}

}
<|endoftext|>


<commit_before>/** \brief Utility for displaying various bits of info about a collection of MARC records.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015-2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <map>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "FileUtil.h"
#include "MARC.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << ::progname << " [--verbose] marc_data\n";
    std::exit(EXIT_FAILURE);
}

void ProcessRecords(const bool verbose, MARC::Reader * const marc_reader) {
    std::string raw_record;
    unsigned record_count(0), max_record_length(0), max_local_block_count(0), oversized_record_count(0),
        max_subfield_count(0), cumulative_field_count(0);
    std::unordered_set<std::string> control_numbers;
    std::map<MARC::Record::RecordType, unsigned> record_types_and_counts;

    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        cumulative_field_count += record.getNumberOfFields();

        if (unlikely(record.getNumberOfFields() == 0))
            logger->error("record #" + std::to_string(record_count) + " has zero fields!");
        const std::string &control_number(record.getControlNumber());

        if (control_numbers.find(control_number) != control_numbers.end())
            logger->warning("found at least one duplicate control number: " + control_number);
        control_numbers.insert(control_number);

        const MARC::Record::RecordType record_type(record.getRecordType());
        ++record_types_and_counts[record_type];
        if (verbose and record_type == MARC::Record::RecordType::UNKNOWN)
            std::cerr << "Unknown record type '" << record.getLeader()[6] << "' for PPN " << control_number
                      << ".\n";

        const unsigned record_length(record.size());
        if (record_length > max_record_length)
            max_record_length = record_length;
        if (record_length >= 100000)
            ++oversized_record_count;

        for (const auto &field : record) {
            if (field.isControlField())
                continue;

            const MARC::Subfields subfields(field.getContents());
            const size_t subfield_count(subfields.size());
            if (unlikely(subfield_count > max_subfield_count))
                max_subfield_count = subfield_count;
        }

        std::vector<std::pair<MARC::Record::const_iterator, MARC::Record::const_iterator>> local_block_boundaries;
        const size_t local_block_count(record.findAllLocalDataBlocks(&local_block_boundaries));
        if (local_block_count > max_local_block_count)
            max_local_block_count = local_block_count;
        for (const auto local_block_boundary : local_block_boundaries) {
            std::vector<MARC::Record::const_iterator> fields;
            if (record.findFieldsInLocalBlock("001", "??", local_block_boundary, &fields) != 1)
                logger->error("Every local data block has to have exactly one 001 field. (Record: "
                              + record.getControlNumber() + ", Local data block: "
                              + std::to_string(local_block_boundary.first - record.begin()) + " - "
                              + std::to_string(local_block_boundary.second - record.begin()));
        }
    }

    std::cout << "Data set contains " << record_count << " MARC record(s).\n";
    std::cout << "Largest record contains " << max_record_length << " bytes.\n";
    std::cout << "The record with the largest number of \"local\" blocks has " << max_local_block_count
              << " local blocks.\n";
    std::cout << "Counted " << record_types_and_counts[MARC::Record::RecordType::BIBLIOGRAPHIC]
              << " bibliographic record(s), " << record_types_and_counts[MARC::Record::RecordType::AUTHORITY]
              << " classification record(s), " << record_types_and_counts[MARC::Record::RecordType::CLASSIFICATION]
              << " authority record(s), and " << record_types_and_counts[MARC::Record::RecordType::UNKNOWN]
              << " record(s) of unknown record type.\n";
    std::cout << "Found " << oversized_record_count << " oversized records.\n";
    std::cout << "The field with the most subfields has " << max_subfield_count << " subfield(s).\n";
    std::cout << "The average no. of fields per record is "
              << (static_cast<double>(cumulative_field_count) / record_count) << ".\n";
    std::cout << "The average record size in bytes is "
              << (static_cast<double>(FileUtil::GetFileSize(marc_reader->getPath())) / record_count) << ".\n";
}

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 2)
        Usage();

    const bool verbose(std::strcmp(argv[1], "--verbose") == 0);
    if (verbose)
        --argc, ++argv;

    if (argc != 2)
        Usage();

    std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(argv[1]));

    try {
        ProcessRecords(verbose, marc_reader.get());
    } catch (const std::exception &e) {
        logger->error("Caught exception: " + std::string(e.what()));
    }
}
<commit_msg>Got rid of a magic constant.<commit_after>/** \brief Utility for displaying various bits of info about a collection of MARC records.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015-2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <map>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "FileUtil.h"
#include "MARC.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << ::progname << " [--verbose] marc_data\n";
    std::exit(EXIT_FAILURE);
}

void ProcessRecords(const bool verbose, MARC::Reader * const marc_reader) {
    std::string raw_record;
    unsigned record_count(0), max_record_length(0), max_local_block_count(0), oversized_record_count(0),
        max_subfield_count(0), cumulative_field_count(0);
    std::unordered_set<std::string> control_numbers;
    std::map<MARC::Record::RecordType, unsigned> record_types_and_counts;

    while (const MARC::Record record = marc_reader->read()) {
        ++record_count;
        cumulative_field_count += record.getNumberOfFields();

        if (unlikely(record.getNumberOfFields() == 0))
            logger->error("record #" + std::to_string(record_count) + " has zero fields!");
        const std::string &control_number(record.getControlNumber());

        if (control_numbers.find(control_number) != control_numbers.end())
            logger->warning("found at least one duplicate control number: " + control_number);
        control_numbers.insert(control_number);

        const MARC::Record::RecordType record_type(record.getRecordType());
        ++record_types_and_counts[record_type];
        if (verbose and record_type == MARC::Record::RecordType::UNKNOWN)
            std::cerr << "Unknown record type '" << record.getLeader()[6] << "' for PPN " << control_number
                      << ".\n";

        const unsigned record_length(record.size());
        if (record_length > max_record_length)
            max_record_length = record_length;
        if (record_length > MARC::Record::MAX_RECORD_LENGTH)
            ++oversized_record_count;

        for (const auto &field : record) {
            if (field.isControlField())
                continue;

            const MARC::Subfields subfields(field.getContents());
            const size_t subfield_count(subfields.size());
            if (unlikely(subfield_count > max_subfield_count))
                max_subfield_count = subfield_count;
        }

        std::vector<std::pair<MARC::Record::const_iterator, MARC::Record::const_iterator>> local_block_boundaries;
        const size_t local_block_count(record.findAllLocalDataBlocks(&local_block_boundaries));
        if (local_block_count > max_local_block_count)
            max_local_block_count = local_block_count;
        for (const auto local_block_boundary : local_block_boundaries) {
            std::vector<MARC::Record::const_iterator> fields;
            if (record.findFieldsInLocalBlock("001", "??", local_block_boundary, &fields) != 1)
                logger->error("Every local data block has to have exactly one 001 field. (Record: "
                              + record.getControlNumber() + ", Local data block: "
                              + std::to_string(local_block_boundary.first - record.begin()) + " - "
                              + std::to_string(local_block_boundary.second - record.begin()));
        }
    }

    std::cout << "Data set contains " << record_count << " MARC record(s).\n";
    std::cout << "Largest record contains " << max_record_length << " bytes.\n";
    std::cout << "The record with the largest number of \"local\" blocks has " << max_local_block_count
              << " local blocks.\n";
    std::cout << "Counted " << record_types_and_counts[MARC::Record::RecordType::BIBLIOGRAPHIC]
              << " bibliographic record(s), " << record_types_and_counts[MARC::Record::RecordType::AUTHORITY]
              << " classification record(s), " << record_types_and_counts[MARC::Record::RecordType::CLASSIFICATION]
              << " authority record(s), and " << record_types_and_counts[MARC::Record::RecordType::UNKNOWN]
              << " record(s) of unknown record type.\n";
    std::cout << "Found " << oversized_record_count << " oversized records.\n";
    std::cout << "The field with the most subfields has " << max_subfield_count << " subfield(s).\n";
    std::cout << "The average no. of fields per record is "
              << (static_cast<double>(cumulative_field_count) / record_count) << ".\n";
    std::cout << "The average record size in bytes is "
              << (static_cast<double>(FileUtil::GetFileSize(marc_reader->getPath())) / record_count) << ".\n";
}

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 2)
        Usage();

    const bool verbose(std::strcmp(argv[1], "--verbose") == 0);
    if (verbose)
        --argc, ++argv;

    if (argc != 2)
        Usage();

    std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(argv[1]));

    try {
        ProcessRecords(verbose, marc_reader.get());
    } catch (const std::exception &e) {
        logger->error("Caught exception: " + std::string(e.what()));
    }
}
<|endoftext|>


<commit_before>#include <cassert>
#include <iostream>
#include <string>
#include <memory>
#include <vector>

using namespace std;

template <typename T> class object {

public:
  object() = delete;

  object(T* p) : px{p} {
    assert(px != nullptr);
  }

  T& ref() noexcept {
    return *px;
  }

  T& ref() const noexcept {
    return *px;
  }

  T* get() noexcept {
    return px.get();
  }

  T* get() const noexcept {
    return px.get();
  }

private:
  shared_ptr<T> px;
};

int main() {

  //object<int> bang{ nullptr };

  object<int> o0{new int{5}};
  auto o1 = object<string>{new string{"abc"}};
  vector<object<double>> v { new double{ 0.1 }, new double { 0.2 } };

  cout << o0.ref() << endl;
  cout << o1.ref() << endl;
  for (const auto& o : v) {
    cout << o.ref() << " " << o.get() << endl;
  }

}
<commit_msg>fixup! some shared_ptr wrapper<commit_after>#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;

// fwd decl
template <typename T> class object;
template <typename T> int count_object(const object<T>&);
template <typename T> T* get_object_ptr(const object<T>&);

template <typename T> class object {
public:
  object() = delete;
  ~object() noexcept = default;

  // Not required (because destructor declaration automatically removes move
  // constructor and move assignment)
  // object(object<T>&&) = delete;
  // object(const object<T>&&) = delete;
  // object<T>& operator=(object<T>&&) = delete;

  explicit object(T* p) : px{ p } { assert(px != nullptr); }

  operator T&() const noexcept { return *px; }

  T& operator*() const noexcept { return *px; }

  T* operator->() const noexcept { return px.get(); }

  // not possible
  // T& operator.() const noexcept { return *px; }

private:
  shared_ptr<T> px;

  friend int count_object<T>(const object<T>&);
  friend T* get_object_ptr<T>(const object<T>&);
};

// auxiliary functions
template <typename T, typename... Args> object<T> make_object(Args&&... args) {
  return object<T>{ new T{ std::forward<Args>(args)... } };
}

template <typename T> int count_object(const object<T>& obj) {
  return obj.px.use_count();
}

template <typename T> T* get_object_ptr(const object<T>& obj) {
  return obj.px.get();
}

struct base {
  virtual void f() { cout << "base" << endl; }
};

struct extended : public base {
  virtual void f() override { cout << "extended" << endl; }
};

int main() {
  // runtime errors:
  // object<int> bang {nullptr};
  // object<int> bad;

  object<int> o0{ new int{ 5 } };
  cout << *o0 << endl;

  auto mo1 = make_object<int>(10);
  // will actually make a copy instead of 'move' (because a destructor was
  // declared)
  auto mo2 = std::move(mo1);
  cout << get_object_ptr(mo1) << ",count: " << count_object(mo1) << endl;
  cout << *mo1 << endl;

  auto o1 = object<string>{ new string{ "abc" } };
  cout << *o1 << endl;

  vector<object<double> > v{ make_object<double>(1.0),
                             make_object<double>(2.0) };
  cout << "{ ";
  for (const auto& o : v) {
    cout << *o << " ";
  }
  cout << "}" << endl;

  extended ext;
  base& base_ref = ext;
  base_ref.f();

  auto o2 = make_object<extended>();
  o2->f();
  extended& ref2 = o2;
  ref2.f();
  (static_cast<extended&>(o2)).f();
  // operator. can not be overriden in c++ (and operator T&() won't do it)
  // o2.f();

  // why? how to do it?
  //  object<base> o3 = make_object<extended>();
  //  o3->f();
}
<|endoftext|>