<commit_before>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef INCLUDE_OTF2XX_COMMON_HPP
#define INCLUDE_OTF2XX_COMMON_HPP

namespace otf2
{
namespace common
{

    /**
     * an enum for representing possible types within events and definitions
     */
    enum class type
    {
        none,
        uint8,
        uint16,
        uint32,
        uint64,
        int8,
        int16,
        int32,
        int64,
        Float,
        Double,
        string,
        attribute,
        location,
        region,
        group,
        metric,
        comm,
        parameter,
        rma_win,
        source_code_location,
        calling_context,
        interrupt_generator,
        io_file,
        io_handle
    };

    enum class system_tree_node_domain
    {
        machine,
        shared_memory,
        numa,
        socket,
        cache,
        core,
        pu

    };

    /**
     * an enum for representing the contants of a group definition
     */
    enum class group_type
    {
        /** a unknown type */
        unknown,
        /** locations */
        locations,
        /** regions (not used) */
        regions,
        /** metrics (not used) */
        metric,
        /**  */
        comm_locations,
        /**  */
        comm_group,
        /** special group, only contains itself */
        comm_self
    };

    enum class group_flag_type
    {
        none,
        global_members
    };

    /**
     * an enum for representing the type of a location
     */
    enum class location_type
    {
        /** unknown */
        unknown,
        /** a cpu thread */
        cpu_thread,
        /** on gpu */
        gpu,
        /** a metric - acts as recorder for metric instances */
        metric
    };

    enum class parameter_type
    {
        string,
        int64,
        uint64
    };

    enum class location_group_type
    {
        unknown,
        process
    };

    enum class role_type
    {
        unknown,
        function,
        wrapper,
        loop,
        code,
        parallel,
        sections,
        section,
        workshare,
        single,
        single_sblock,
        master,
        critical,
        critical_sblock,
        atomic,
        barrier,
        implicit_barrier,
        flush,
        ordered,
        ordered_sblock,
        task,
        task_create,
        task_wait,
        coll_one2all,
        coll_all2one,
        coll_all2all,
        coll_other,
        file_io,
        point2point,
        rma,
        data_transfer,
        artifical,
        thread_create,
        thread_wait,
        task_untied,
        allocate,
        deallocate,
        reallocate,
        file_io_metadata
    };

    enum class paradigm_type
    {
        unknown,
        user,
        compiler,
        openmp,
        mpi,
        cuda,
        measurement_system,
        pthread,
        hmpp,
        ompss,
        hardware,
        gaspi,
        upc,
        shmem,
        winthread,
        qtthread,
        acethread,
        tbbthread,
        openacc,
        opencl,
        mtapi,
        sampling,
        none
    };

    enum class paradigm_class_type
    {
        process,
        thread_fork_join,
        thread_create_wait,
        accelerator
    };

    enum class paradigm_property_type
    {
        comm_name_template,
        rma_win_name_template,
        rma_only
    };

    enum class flags_type
    {
        none,
        dynamic,
        phase
    };

    enum class collective_type
    {
        barrier,
        broadcast,
        gather,
        gatherv,
        scatter,
        scatterv,
        all_gather,
        all_gatherv,
        all_to_all,
        all_to_allv,
        all_to_allw,
        all_reduce,
        reduce,
        reduce_scatter,
        scan,
        exscan,
        reduce_scatter_block,
        create_handle,
        destroy_handle,
        allocate,
        deallocate,
        create_handle_and_allocate,
        destroy_handle_and_deallocate
    };

    enum class metric_type
    {
        other,
        papi,
        rusage,
        user
    };

    enum class metric_timing
    {
        start = 0,
        point = 1 << 4,
        last = 2 << 4,
        next = 3 << 4
    };

    /**
     * metric occurence
     */
    enum class metric_occurence
    {
        /** Metric occurs at every region enter and leave. */
        strict,
        /** Metric occurs only at a region enter and leave, but does not need to occur at every
           enter/leave. */
        sync,
        /** Metric can occur at any place i.e. it is not related to region enter and leaves. */
        async
    };

    /**
     * \brief metric scope
     *
     * Specifies the scope the values of a metric class are valid for
     */
    enum class metric_scope
    {
        /** for a location*/
        location,
        /** for a location group */
        location_group,
        /** for a system tree node */
        system_tree_node,
        /** a custom group of locations */
        group
    };

    enum class metric_value_property
    {
        accumulated = 0,
        absolute = 1,
        relative = 2
    };

    enum class base_type
    {
        binary,
        decimal
    };

    enum class metric_mode;

    template <metric_timing timing, metric_value_property property>
    class both
    {
    public:
        static const int value = static_cast<int>(timing) | static_cast<int>(property);
    };

    enum class metric_mode
    {
        accumulated_start = both<metric_timing::start, metric_value_property::accumulated>::value,
        accumulated_point = both<metric_timing::point, metric_value_property::accumulated>::value,
        accumulated_last = both<metric_timing::last, metric_value_property::accumulated>::value,
        accumulated_next = both<metric_timing::next, metric_value_property::accumulated>::value,
        absolute_point = both<metric_timing::point, metric_value_property::absolute>::value,
        absolute_last = both<metric_timing::last, metric_value_property::absolute>::value,
        absolute_next = both<metric_timing::next, metric_value_property::absolute>::value,
        relative_point = both<metric_timing::point, metric_value_property::relative>::value,
        relative_last = both<metric_timing::last, metric_value_property::relative>::value,
        relative_next = both<metric_timing::next, metric_value_property::relative>::value
    };

    enum class recorder_kind
    {
        unknown,
        abstract,
        cpu,
        gpu
    };

    /**
     * enum for representing the type of an event
     *
     * \internal
     * This is used by the \ref otf2::event::buffer to distinguish between events,
     * as they are stored as void pointers.
     */
    enum class event_type
    {
        buffer_flush,
        enter,
        leave,
        measurement,
        metric,
        mpi_collective_begin,
        mpi_collective_end,
        mpi_ireceive,
        mpi_ireceive_request,
        mpi_isend,
        mpi_isend_complete,
        mpi_receive,
        mpi_request_cancelled,
        mpi_request_test,
        mpi_send,
        parameter_int,
        parameter_string,
        parameter_unsigned_int,
        thread_acquire_lock,
        thread_fork,
        thread_join,
        thread_release_lock,
        thread_task_complete,
        thread_task_create,
        thread_task_switch,
        thread_team_begin,
        thread_team_end
    };

    enum class interrupt_generator_mode_type
    {
        time,
        count
    };

    enum class io_handle_flags
    enum class io_handle_flags_type
    {
        none,
        pre_created
    };

    enum class mapping_type_type
    {
        string,
        attribute,
        location,
        region,
        group,
        metric,
        comm,
        parameter,
        rma_win,
        source_code_location,
        calling_context,
        interrupt_generator,
        io_file,
        io_handle,
        max
    };

    enum class marker_severity_type
    {
        none,
        low,
        medium,
        high
    };

    enum class marker_scope_type
    {
        global,
        location,
        location_group,
        system_tree_node,
        group,
        comm
    };
}
}

#endif // INCLUDE_OTF2XX_COMMON_HPP
<commit_msg>Add event type enums<commit_after>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef INCLUDE_OTF2XX_COMMON_HPP
#define INCLUDE_OTF2XX_COMMON_HPP

namespace otf2
{
namespace common
{

    /**
     * an enum for representing possible types within events and definitions
     */
    enum class type
    {
        none,
        uint8,
        uint16,
        uint32,
        uint64,
        int8,
        int16,
        int32,
        int64,
        Float,
        Double,
        string,
        attribute,
        location,
        region,
        group,
        metric,
        comm,
        parameter,
        rma_win,
        source_code_location,
        calling_context,
        interrupt_generator,
        io_file,
        io_handle
    };

    enum class system_tree_node_domain
    {
        machine,
        shared_memory,
        numa,
        socket,
        cache,
        core,
        pu

    };

    /**
     * an enum for representing the contants of a group definition
     */
    enum class group_type
    {
        /** a unknown type */
        unknown,
        /** locations */
        locations,
        /** regions (not used) */
        regions,
        /** metrics (not used) */
        metric,
        /**  */
        comm_locations,
        /**  */
        comm_group,
        /** special group, only contains itself */
        comm_self
    };

    enum class group_flag_type
    {
        none,
        global_members
    };

    /**
     * an enum for representing the type of a location
     */
    enum class location_type
    {
        /** unknown */
        unknown,
        /** a cpu thread */
        cpu_thread,
        /** on gpu */
        gpu,
        /** a metric - acts as recorder for metric instances */
        metric
    };

    enum class parameter_type
    {
        string,
        int64,
        uint64
    };

    enum class location_group_type
    {
        unknown,
        process
    };

    enum class role_type
    {
        unknown,
        function,
        wrapper,
        loop,
        code,
        parallel,
        sections,
        section,
        workshare,
        single,
        single_sblock,
        master,
        critical,
        critical_sblock,
        atomic,
        barrier,
        implicit_barrier,
        flush,
        ordered,
        ordered_sblock,
        task,
        task_create,
        task_wait,
        coll_one2all,
        coll_all2one,
        coll_all2all,
        coll_other,
        file_io,
        point2point,
        rma,
        data_transfer,
        artifical,
        thread_create,
        thread_wait,
        task_untied,
        allocate,
        deallocate,
        reallocate,
        file_io_metadata
    };

    enum class paradigm_type
    {
        unknown,
        user,
        compiler,
        openmp,
        mpi,
        cuda,
        measurement_system,
        pthread,
        hmpp,
        ompss,
        hardware,
        gaspi,
        upc,
        shmem,
        winthread,
        qtthread,
        acethread,
        tbbthread,
        openacc,
        opencl,
        mtapi,
        sampling,
        none
    };

    enum class paradigm_class_type
    {
        process,
        thread_fork_join,
        thread_create_wait,
        accelerator
    };

    enum class paradigm_property_type
    {
        comm_name_template,
        rma_win_name_template,
        rma_only
    };

    enum class flags_type
    {
        none,
        dynamic,
        phase
    };

    enum class collective_type
    {
        barrier,
        broadcast,
        gather,
        gatherv,
        scatter,
        scatterv,
        all_gather,
        all_gatherv,
        all_to_all,
        all_to_allv,
        all_to_allw,
        all_reduce,
        reduce,
        reduce_scatter,
        scan,
        exscan,
        reduce_scatter_block,
        create_handle,
        destroy_handle,
        allocate,
        deallocate,
        create_handle_and_allocate,
        destroy_handle_and_deallocate
    };

    enum class metric_type
    {
        other,
        papi,
        rusage,
        user
    };

    enum class metric_timing
    {
        start = 0,
        point = 1 << 4,
        last = 2 << 4,
        next = 3 << 4
    };

    /**
     * metric occurence
     */
    enum class metric_occurence
    {
        /** Metric occurs at every region enter and leave. */
        strict,
        /** Metric occurs only at a region enter and leave, but does not need to occur at every
           enter/leave. */
        sync,
        /** Metric can occur at any place i.e. it is not related to region enter and leaves. */
        async
    };

    /**
     * \brief metric scope
     *
     * Specifies the scope the values of a metric class are valid for
     */
    enum class metric_scope
    {
        /** for a location*/
        location,
        /** for a location group */
        location_group,
        /** for a system tree node */
        system_tree_node,
        /** a custom group of locations */
        group
    };

    enum class metric_value_property
    {
        accumulated = 0,
        absolute = 1,
        relative = 2
    };

    enum class base_type
    {
        binary,
        decimal
    };

    enum class metric_mode;

    template <metric_timing timing, metric_value_property property>
    class both
    {
    public:
        static const int value = static_cast<int>(timing) | static_cast<int>(property);
    };

    enum class metric_mode
    {
        accumulated_start = both<metric_timing::start, metric_value_property::accumulated>::value,
        accumulated_point = both<metric_timing::point, metric_value_property::accumulated>::value,
        accumulated_last = both<metric_timing::last, metric_value_property::accumulated>::value,
        accumulated_next = both<metric_timing::next, metric_value_property::accumulated>::value,
        absolute_point = both<metric_timing::point, metric_value_property::absolute>::value,
        absolute_last = both<metric_timing::last, metric_value_property::absolute>::value,
        absolute_next = both<metric_timing::next, metric_value_property::absolute>::value,
        relative_point = both<metric_timing::point, metric_value_property::relative>::value,
        relative_last = both<metric_timing::last, metric_value_property::relative>::value,
        relative_next = both<metric_timing::next, metric_value_property::relative>::value
    };

    enum class recorder_kind
    {
        unknown,
        abstract,
        cpu,
        gpu
    };

    /**
     * enum for representing the type of an event
     *
     * \internal
     * This is used by the \ref otf2::event::buffer to distinguish between events,
     * as they are stored as void pointers.
     */
    enum class event_type
    {
        buffer_flush,
        enter,
        leave,
        measurement,
        metric,
        mpi_collective_begin,
        mpi_collective_end,
        mpi_ireceive,
        mpi_ireceive_request,
        mpi_isend,
        mpi_isend_complete,
        mpi_receive,
        mpi_request_cancelled,
        mpi_request_test,
        mpi_send,
        parameter_int,
        parameter_string,
        parameter_unsigned_int,
        thread_acquire_lock,
        thread_fork,
        thread_join,
        thread_release_lock,
        thread_task_complete,
        thread_task_create,
        thread_task_switch,
        thread_team_begin,
        thread_team_end
    };

    enum class interrupt_generator_mode_type
    {
        time,
        count
    };

    enum class io_paradigm_class
    {
        serial,
        parallel
    };

    enum class io_access_mode_type
    {
        read_only,
        write_only,
        read_write,
        execute_only,
        search_only
    };

    enum class io_creation_flag_type
    {
        none,
        create,
        truncate,
        directory,
        exclusive,
        no_controlling_terminal,
        no_follow,
        path,
        temporary_file,
        largefile,
        no_seek,
        unique
    };

    enum class io_status_flag_type
    {
        none,
        close_on_exec,
        append,
        non_blocking,
        async,
        sync,
        data_sync,
        avoid_caching,
        no_access_time,
        delete_on_close
    };

    enum class io_seek_option_type
    {
        from_start,
        from_current,
        from_end,
        data,
        hole
    };

    enum class io_operation_mode_type
    {
        read,
        write,
        flush
    };

    enum class io_operation_flag_type
    {
        none,
        non_blocking,
        collective
    };

    enum class io_handle_flags_type
    {
        none,
        pre_created
    };

    enum class mapping_type_type
    {
        string,
        attribute,
        location,
        region,
        group,
        metric,
        comm,
        parameter,
        rma_win,
        source_code_location,
        calling_context,
        interrupt_generator,
        io_file,
        io_handle,
        max
    };

    enum class marker_severity_type
    {
        none,
        low,
        medium,
        high
    };

    enum class marker_scope_type
    {
        global,
        location,
        location_group,
        system_tree_node,
        group,
        comm
    };
}
}

#endif // INCLUDE_OTF2XX_COMMON_HPP
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// 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)
//=======================================================================

#ifndef TAC_QUADRUPLE_H
#define TAC_QUADRUPLE_H

#include <vector>

#include "tac/Operator.hpp"
#include "tac/Argument.hpp"

namespace eddic {

class Variable;

namespace tac {

struct Quadruple {
    std::shared_ptr<Variable> result;
    tac::Argument arg1;
    tac::Argument arg2;
    tac::Operator op;

    Quadruple();
    Quadruple(std::shared_ptr<Variable> result, tac::Argument arg);
    Quadruple(std::shared_ptr<Variable> result, tac::Argument arg1, Operator op, tac::Argument arg2);
};

} //end of tac

} //end of eddic

#endif
<commit_msg>Set the args as optional<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// 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)
//=======================================================================

#ifndef TAC_QUADRUPLE_H
#define TAC_QUADRUPLE_H

#include <boost/optional.hpp>

#include <vector>

#include "tac/Operator.hpp"
#include "tac/Argument.hpp"

namespace eddic {

class Variable;

namespace tac {

struct Quadruple {
    std::shared_ptr<Variable> result;
    tac::Argument arg1;
    boost::optional<tac::Argument> arg2;
    boost::optional<tac::Operator> op;

    Quadruple();
    Quadruple(std::shared_ptr<Variable> result, tac::Argument arg);
    Quadruple(std::shared_ptr<Variable> result, tac::Argument arg1, Operator op, tac::Argument arg2);
};

} //end of tac

} //end of eddic

#endif
<|endoftext|>


<commit_before>#pragma once
#include <ostream>
#include <vector>
#include <functional>
#include <sstream>

namespace the
{

namespace log
{

class LogDetails;

std::string local_time_in_string_format();
std::ostream& operator<<( std::ostream& output, const LogDetails& details );

class LogDetails
{
  public:
    int loglevel;
    const char* file;
    int line;
};

class Logger
{
  public:
    static void drop_channels();
    static void add_channel( std::ostream& );
    static void set_loglevel( int loglevel );

    template < typename...Args >
    static void log( const LogDetails& details, Args&&...args )
    {
      Logger& logger( instance() );
      if ( details.loglevel < logger.m_loglevel )
      {
        return;
      }

      logger.to_all_channels( local_time_in_string_format() );
      logger.to_all_channels( details );
      logger.print( std::forward< Args >( args )... );
      logger.end_of_message();
    }

    Logger( const Logger& ) = delete;
    Logger& operator=( const Logger& ) = delete;

  private:
    template< typename Head, typename...Tail >
    void print( Head&& head, Tail&&...tail )
    {
      to_all_channels( head );
      print( std::forward< Tail >( tail )... );
    }

    void print() {}

    void end_of_message()
    {
      for ( auto& channel : m_channels )
      {
        channel.get() << std::endl;
      }
    }

    template < typename T >
    void to_all_channels( const T& message )
    {
      for ( auto& channel : m_channels )
      {
        channel.get() << message << " ";
      }
    }

    Logger() = default;

    static Logger& instance();

    typedef std::vector< std::reference_wrapper< std::ostream > > ChannelContainer;
    ChannelContainer m_channels;
    int m_loglevel{ 0 };
};

class AutoLogger
{
  public:
    AutoLogger( const LogDetails& details );

    template < typename...Args >
    void operator()( Args&&...args )
    {
      Logger::log( m_details, std::forward<Args>( args )... );
    }

    ~AutoLogger();

  private:
    const LogDetails m_details;
};

}

}

#if defined switch_off_thelog
  #define thelog(...) (void)
#else
  #define thelog( loglevel ) the::log::AutoLogger( { loglevel, __FILE__, __LINE__ } )
#endif

<commit_msg>remove not needed include<commit_after>#pragma once
#include <ostream>
#include <vector>
#include <functional>

namespace the
{

namespace log
{

class LogDetails;

std::string local_time_in_string_format();
std::ostream& operator<<( std::ostream& output, const LogDetails& details );

class LogDetails
{
  public:
    int loglevel;
    const char* file;
    int line;
};

class Logger
{
  public:
    static void drop_channels();
    static void add_channel( std::ostream& );
    static void set_loglevel( int loglevel );

    template < typename...Args >
    static void log( const LogDetails& details, Args&&...args )
    {
      Logger& logger( instance() );
      if ( details.loglevel < logger.m_loglevel )
      {
        return;
      }

      logger.to_all_channels( local_time_in_string_format() );
      logger.to_all_channels( details );
      logger.print( std::forward< Args >( args )... );
      logger.end_of_message();
    }

    Logger( const Logger& ) = delete;
    Logger& operator=( const Logger& ) = delete;

  private:
    template< typename Head, typename...Tail >
    void print( Head&& head, Tail&&...tail )
    {
      to_all_channels( head );
      print( std::forward< Tail >( tail )... );
    }

    void print() {}

    void end_of_message()
    {
      for ( auto& channel : m_channels )
      {
        channel.get() << std::endl;
      }
    }

    template < typename T >
    void to_all_channels( const T& message )
    {
      for ( auto& channel : m_channels )
      {
        channel.get() << message << " ";
      }
    }

    Logger() = default;

    static Logger& instance();

    typedef std::vector< std::reference_wrapper< std::ostream > > ChannelContainer;
    ChannelContainer m_channels;
    int m_loglevel{ 0 };
};

class AutoLogger
{
  public:
    AutoLogger( const LogDetails& details );

    template < typename...Args >
    void operator()( Args&&...args )
    {
      Logger::log( m_details, std::forward<Args>( args )... );
    }

    ~AutoLogger();

  private:
    const LogDetails m_details;
};

}

}

#if defined switch_off_thelog
  #define thelog(...) (void)
#else
  #define thelog( loglevel ) the::log::AutoLogger( { loglevel, __FILE__, __LINE__ } )
#endif

<|endoftext|>


<commit_before><commit_msg>interface of ParticleSet<commit_after>#ifndef V_SMC_PARTICLE_HPP
#define V_SMC_PARTICLE_HPP

#include <vector>
#include <cstddef>
#include <vDist/utilities/service.hpp>

namespace vSMC {

enum RESAMPLE_SCHEME {MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC};

template <class PartContainer>
class ParticleSet
{
    public :

    Particle (std::size_t N) :
        particle_num(N), particle_set(N), log_weight(N) {};

    inline void Resample ();
    inline double ESS ();

    inline void SetWeight    (std::size_t n, const double *weight);
    inline void MulWeight    (std::size_t n, const double *inc_weight);
    inline void SetLogWeight (std::size_t n, const double *log_weight);
    inline void AddLogWeight (std::size_t n, const double *inc_weight);

    private :

    std::size_t particle_num;
    PartContainer particle_set;
    vDist::internal::Buffer<double> log_weight;

    inline void resample_multinomial ();
    inline void resample_residual ();
    inline void resample_stratified ();
    inline void resample_systematic ();
    inline void resample_do (std::size_t n, std::size_t *rep);
};

} // namespace vSMC

#endif // V_SMC_PARTICLE_HPP
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, 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 "registrardb.hh"
#include "registrardb-internal.hh"
#include "common.hh"

#include <ctime>
#include <cstdio>
#include <vector>
#include <algorithm>

#include <sofia-sip/sip_protos.h>

using namespace std;

RegistrarDbInternal::RegistrarDbInternal(const string &preferredRoute) : RegistrarDb(preferredRoute) {
}

void RegistrarDbInternal::doBind(const url_t *ifrom, sip_contact_t *icontact, const char *iid, uint32_t iseq,
						const sip_path_t *ipath, list<string> acceptHeaders, bool usedAsRoute, int expire, int alias, int version,
						const shared_ptr<ContactUpdateListener> &listener) {
	string key = Record::defineKeyFromUrl(ifrom);
	time_t now = getCurrentTime();

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r;
	if (it == mRecords.end()) {
		r = new Record(ifrom);
		mRecords.insert(make_pair(key, r));
		LOGD("Creating AOR %s association", key.c_str());
	} else {
		LOGD("AOR %s found", key.c_str());
		r = (*it).second;
	}

	if (r->isInvalidRegister(iid, iseq)) {
		LOGD("Invalid register");
		listener->onInvalid();
		return;
	}

	r->update(icontact, ipath, expire, iid, iseq, now, alias, acceptHeaders, usedAsRoute, listener);

	mLocalRegExpire->update(*r);
	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetch(const url_t *url, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;
	if (it != mRecords.end()) {
		r = (*it).second;
		r->clean(getCurrentTime(), listener);
		if (r->isEmpty()) {
			mRecords.erase(it);
			r = NULL;
		}
	}

	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetchForGruu(const url_t *url, const string &gruu, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));
	SofiaAutoHome home;

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;

	if (it == mRecords.end()) {
		listener->onRecordFound(r);
		return;
	}

	r = (*it).second;
	r->clean(getCurrentTime(), listener);
	if (r->isEmpty()) {
		mRecords.erase(it);
		r = NULL;
		listener->onRecordFound(r);
		return;
	}

	const list<shared_ptr<ExtendedContact>> &contacts = r->getExtendedContacts();
	Record retRecord(url);
	for (const auto &contact : contacts) {
		if (!url_has_param(contact->mSipContact->m_url, "gr"))
			continue;

		char buffer[255] = {0};
		isize_t result = url_param(contact->mSipContact->m_url->url_params, "gr", buffer, sizeof(buffer) - 1);
		if (result <= 0)
			continue;

		stringstream streamGruu;
		streamGruu << "\"<" << buffer << ">\"";
		if (streamGruu.str() != gruu)
			continue;

		retRecord.pushContact(contact);
	}

	listener->onRecordFound(&retRecord);
}

void RegistrarDbInternal::doClear(const sip_t *sip, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(sip->sip_from->a_url));

	if (errorOnTooMuchContactInBind(sip->sip_contact, key, listener)) {
		listener->onError();
		return;
	}

	map<string, Record *>::iterator it = mRecords.find(key);

	if (it == mRecords.end()) {
		listener->onRecordFound(NULL);
		return;
	}

	LOGD("AOR %s found", key.c_str());
	Record *r = (*it).second;

	if (r->isInvalidRegister(sip->sip_call_id->i_id, sip->sip_cseq->cs_seq)) {
		listener->onInvalid();
		return;
	}

	mRecords.erase(it);
	mLocalRegExpire->remove(key);
	delete r;
	listener->onRecordFound(NULL);
}

void RegistrarDbInternal::doMigration() {

}

void RegistrarDbInternal::clearAll() {
	mRecords.clear();
	mLocalRegExpire->clearAll();
}

void RegistrarDbInternal::publish(const string &topic, const string &uid) {
	LOGD("Publish topic = %s, uid = %s", topic.c_str(), uid.c_str());
	RegistrarDb::notifyContactListener(topic, uid);
}
<commit_msg>fix leak in internalDb<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, 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 "registrardb.hh"
#include "registrardb-internal.hh"
#include "common.hh"

#include <ctime>
#include <cstdio>
#include <vector>
#include <algorithm>

#include <sofia-sip/sip_protos.h>

using namespace std;

RegistrarDbInternal::RegistrarDbInternal(const string &preferredRoute) : RegistrarDb(preferredRoute) {
}

void RegistrarDbInternal::doBind(const url_t *ifrom, sip_contact_t *icontact, const char *iid, uint32_t iseq,
						const sip_path_t *ipath, list<string> acceptHeaders, bool usedAsRoute, int expire, int alias, int version,
						const shared_ptr<ContactUpdateListener> &listener) {
	string key = Record::defineKeyFromUrl(ifrom);
	time_t now = getCurrentTime();

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r;
	if (it == mRecords.end()) {
		r = new Record(ifrom);
		mRecords.insert(make_pair(key, r));
		LOGD("Creating AOR %s association", key.c_str());
	} else {
		LOGD("AOR %s found", key.c_str());
		r = (*it).second;
	}

	if (r->isInvalidRegister(iid, iseq)) {
		LOGD("Invalid register");
		listener->onInvalid();
		return;
	}

	r->update(icontact, ipath, expire, iid, iseq, now, alias, acceptHeaders, usedAsRoute, listener);

	mLocalRegExpire->update(*r);
	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetch(const url_t *url, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;
	if (it != mRecords.end()) {
		r = (*it).second;
		r->clean(getCurrentTime(), listener);
		if (r->isEmpty()) {
			mRecords.erase(it);
			delete r;
			r = NULL;
		}
	}

	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetchForGruu(const url_t *url, const string &gruu, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));
	SofiaAutoHome home;

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;

	if (it == mRecords.end()) {
		listener->onRecordFound(r);
		return;
	}

	r = (*it).second;
	r->clean(getCurrentTime(), listener);
	if (r->isEmpty()) {
		mRecords.erase(it);
		delete r;
		r = NULL;
		listener->onRecordFound(r);
		return;
	}

	const list<shared_ptr<ExtendedContact>> &contacts = r->getExtendedContacts();
	Record retRecord(url);
	for (const auto &contact : contacts) {
		if (!url_has_param(contact->mSipContact->m_url, "gr"))
			continue;

		char buffer[255] = {0};
		isize_t result = url_param(contact->mSipContact->m_url->url_params, "gr", buffer, sizeof(buffer) - 1);
		if (result <= 0)
			continue;

		stringstream streamGruu;
		streamGruu << "\"<" << buffer << ">\"";
		if (streamGruu.str() != gruu)
			continue;

		retRecord.pushContact(contact);
	}

	listener->onRecordFound(&retRecord);
}

void RegistrarDbInternal::doClear(const sip_t *sip, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(sip->sip_from->a_url));

	if (errorOnTooMuchContactInBind(sip->sip_contact, key, listener)) {
		listener->onError();
		return;
	}

	map<string, Record *>::iterator it = mRecords.find(key);

	if (it == mRecords.end()) {
		listener->onRecordFound(NULL);
		return;
	}

	LOGD("AOR %s found", key.c_str());
	Record *r = (*it).second;

	if (r->isInvalidRegister(sip->sip_call_id->i_id, sip->sip_cseq->cs_seq)) {
		listener->onInvalid();
		return;
	}

	mRecords.erase(it);
	mLocalRegExpire->remove(key);
	delete r;
	listener->onRecordFound(NULL);
}

void RegistrarDbInternal::doMigration() {

}

void RegistrarDbInternal::clearAll() {
	mRecords.clear();
	mLocalRegExpire->clearAll();
}

void RegistrarDbInternal::publish(const string &topic, const string &uid) {
	LOGD("Publish topic = %s, uid = %s", topic.c_str(), uid.c_str());
	RegistrarDb::notifyContactListener(topic, uid);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// (C) Andy Thomason 2016
//
// Vookoo: Vulkan semaphore. Wraps VkSemaphore
//

#ifndef VKU_SEMAPHORE_INCLUDED
#define VKU_SEMAPHORE_INCLUDED

namespace vku {

class semaphore : public resource<VkSemaphore, semaphore> {
public:
  /// semaphore that does not own its pointer
  semaphore(VkSemaphore value = VK_NULL_HANDLE, VkDevice dev = VK_NULL_HANDLE) : resource(value, dev) {
  }

  /// semaphore that does own (and creates) its pointer
  semaphore(VkDevice dev) : resource(dev) {
  }

  VkSemaphore create(VkDevice dev) {
    VkSemaphoreCreateInfo info = {};
    info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    info.flags = VK_FENCE_CREATE_SIGNALED_BIT;

    VkSemaphore res = VK_NULL_HANDLE;
    VkResult err = vkCreateSemaphore(dev, &info, nullptr, &res);
    if (err) throw error(err, __FILE__, __LINE__);
    return res;
  }

  void destroy() {
    vkDestroySemaphore(dev(), get(), nullptr);
  }
};

} // vku

#endif
<commit_msg>fix semaphore creation<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// (C) Andy Thomason 2016
//
// Vookoo: Vulkan semaphore. Wraps VkSemaphore
//

#ifndef VKU_SEMAPHORE_INCLUDED
#define VKU_SEMAPHORE_INCLUDED

namespace vku {

class semaphore : public resource<VkSemaphore, semaphore> {
public:
  /// semaphore that does not own its pointer
  semaphore(VkSemaphore value = VK_NULL_HANDLE, VkDevice dev = VK_NULL_HANDLE) : resource(value, dev) {
  }

  /// semaphore that does own (and creates) its pointer
  semaphore(VkDevice dev) : resource(dev) {
    VkSemaphoreCreateInfo info = {};
    info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    info.flags = VK_FENCE_CREATE_SIGNALED_BIT;

    VkSemaphore res = VK_NULL_HANDLE;
    VkResult err = vkCreateSemaphore(dev, &info, nullptr, &res);
    if (err) throw error(err, __FILE__, __LINE__);
    set(res, true);
  }

  void destroy() {
    vkDestroySemaphore(dev(), get(), nullptr);
  }
};

} // vku

#endif
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, 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 "registrardb.hh"
#include "registrardb-internal.hh"
#include "common.hh"

#include <ctime>
#include <cstdio>
#include <vector>
#include <algorithm>

#include <sofia-sip/sip_protos.h>

using namespace std;

RegistrarDbInternal::RegistrarDbInternal(const string &preferredRoute) : RegistrarDb(preferredRoute) {
}

void RegistrarDbInternal::doBind(const url_t *ifrom, sip_contact_t *icontact, const char *iid, uint32_t iseq,
						const sip_path_t *ipath, list<string> acceptHeaders, bool usedAsRoute, int expire, int alias, int version,
						const shared_ptr<ContactUpdateListener> &listener) {
	string key = Record::defineKeyFromUrl(ifrom);
	time_t now = getCurrentTime();

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r;
	if (it == mRecords.end()) {
		r = new Record(ifrom);
		mRecords.insert(make_pair(key, r));
		LOGD("Creating AOR %s association", key.c_str());
	} else {
		LOGD("AOR %s found", key.c_str());
		r = (*it).second;
	}

	if (r->isInvalidRegister(iid, iseq)) {
		LOGD("Invalid register");
		listener->onInvalid();
		return;
	}

	r->update(icontact, ipath, expire, iid, iseq, now, alias, acceptHeaders, usedAsRoute, listener);

	mLocalRegExpire->update(*r);
	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetch(const url_t *url, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;
	if (it != mRecords.end()) {
		r = (*it).second;
		r->clean(getCurrentTime(), listener);
		if (r->isEmpty()) {
			mRecords.erase(it);
			r = NULL;
		}
	}

	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetchForGruu(const url_t *url, const string &gruu, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));
	SofiaAutoHome home;

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;

	if (it == mRecords.end()) {
		listener->onRecordFound(r);
		return;
	}

	r = (*it).second;
	r->clean(getCurrentTime(), listener);
	if (r->isEmpty()) {
		mRecords.erase(it);
		r = NULL;
		listener->onRecordFound(r);
		return;
	}

	const list<shared_ptr<ExtendedContact>> &contacts = r->getExtendedContacts();
	Record retRecord(url);
	for (const auto &contact : contacts) {
		if (!url_has_param(contact->mSipContact->m_url, "gr"))
			continue;

		char buffer[255] = {0};
		isize_t result = url_param(contact->mSipContact->m_url->url_params, "gr", buffer, sizeof(buffer) - 1);
		if (result <= 0)
			continue;

		stringstream streamGruu;
		streamGruu << "\"<" << buffer << ">\"";
		if (streamGruu.str() != gruu)
			continue;

		retRecord.pushContact(contact);
	}

	listener->onRecordFound(&retRecord);
}

void RegistrarDbInternal::doClear(const sip_t *sip, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(sip->sip_from->a_url));

	if (errorOnTooMuchContactInBind(sip->sip_contact, key, listener)) {
		listener->onError();
		return;
	}

	map<string, Record *>::iterator it = mRecords.find(key);

	if (it == mRecords.end()) {
		listener->onRecordFound(NULL);
		return;
	}

	LOGD("AOR %s found", key.c_str());
	Record *r = (*it).second;

	if (r->isInvalidRegister(sip->sip_call_id->i_id, sip->sip_cseq->cs_seq)) {
		listener->onInvalid();
		return;
	}

	mRecords.erase(it);
	mLocalRegExpire->remove(key);
	listener->onRecordFound(NULL);
}

void RegistrarDbInternal::doMigration() {

}

void RegistrarDbInternal::clearAll() {
	mRecords.clear();
	mLocalRegExpire->clearAll();
}

void RegistrarDbInternal::publish(const string &topic, const string &uid) {
	LOGD("Publish topic = %s, uid = %s", topic.c_str(), uid.c_str());
	RegistrarDb::notifyContactListener(topic, uid);
}
<commit_msg>Fix memory leak.<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, 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 "registrardb.hh"
#include "registrardb-internal.hh"
#include "common.hh"

#include <ctime>
#include <cstdio>
#include <vector>
#include <algorithm>

#include <sofia-sip/sip_protos.h>

using namespace std;

RegistrarDbInternal::RegistrarDbInternal(const string &preferredRoute) : RegistrarDb(preferredRoute) {
}

void RegistrarDbInternal::doBind(const url_t *ifrom, sip_contact_t *icontact, const char *iid, uint32_t iseq,
						const sip_path_t *ipath, list<string> acceptHeaders, bool usedAsRoute, int expire, int alias, int version,
						const shared_ptr<ContactUpdateListener> &listener) {
	string key = Record::defineKeyFromUrl(ifrom);
	time_t now = getCurrentTime();

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r;
	if (it == mRecords.end()) {
		r = new Record(ifrom);
		mRecords.insert(make_pair(key, r));
		LOGD("Creating AOR %s association", key.c_str());
	} else {
		LOGD("AOR %s found", key.c_str());
		r = (*it).second;
	}

	if (r->isInvalidRegister(iid, iseq)) {
		LOGD("Invalid register");
		listener->onInvalid();
		return;
	}

	r->update(icontact, ipath, expire, iid, iseq, now, alias, acceptHeaders, usedAsRoute, listener);

	mLocalRegExpire->update(*r);
	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetch(const url_t *url, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;
	if (it != mRecords.end()) {
		r = (*it).second;
		r->clean(getCurrentTime(), listener);
		if (r->isEmpty()) {
			mRecords.erase(it);
			r = NULL;
		}
	}

	listener->onRecordFound(r);
}

void RegistrarDbInternal::doFetchForGruu(const url_t *url, const string &gruu, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(url));
	SofiaAutoHome home;

	map<string, Record *>::iterator it = mRecords.find(key);
	Record *r = NULL;

	if (it == mRecords.end()) {
		listener->onRecordFound(r);
		return;
	}

	r = (*it).second;
	r->clean(getCurrentTime(), listener);
	if (r->isEmpty()) {
		mRecords.erase(it);
		r = NULL;
		listener->onRecordFound(r);
		return;
	}

	const list<shared_ptr<ExtendedContact>> &contacts = r->getExtendedContacts();
	Record retRecord(url);
	for (const auto &contact : contacts) {
		if (!url_has_param(contact->mSipContact->m_url, "gr"))
			continue;

		char buffer[255] = {0};
		isize_t result = url_param(contact->mSipContact->m_url->url_params, "gr", buffer, sizeof(buffer) - 1);
		if (result <= 0)
			continue;

		stringstream streamGruu;
		streamGruu << "\"<" << buffer << ">\"";
		if (streamGruu.str() != gruu)
			continue;

		retRecord.pushContact(contact);
	}

	listener->onRecordFound(&retRecord);
}

void RegistrarDbInternal::doClear(const sip_t *sip, const shared_ptr<ContactUpdateListener> &listener) {
	string key(Record::defineKeyFromUrl(sip->sip_from->a_url));

	if (errorOnTooMuchContactInBind(sip->sip_contact, key, listener)) {
		listener->onError();
		return;
	}

	map<string, Record *>::iterator it = mRecords.find(key);

	if (it == mRecords.end()) {
		listener->onRecordFound(NULL);
		return;
	}

	LOGD("AOR %s found", key.c_str());
	Record *r = (*it).second;

	if (r->isInvalidRegister(sip->sip_call_id->i_id, sip->sip_cseq->cs_seq)) {
		listener->onInvalid();
		return;
	}

	mRecords.erase(it);
	mLocalRegExpire->remove(key);
	delete r;
	listener->onRecordFound(NULL);
}

void RegistrarDbInternal::doMigration() {

}

void RegistrarDbInternal::clearAll() {
	mRecords.clear();
	mLocalRegExpire->clearAll();
}

void RegistrarDbInternal::publish(const string &topic, const string &uid) {
	LOGD("Publish topic = %s, uid = %s", topic.c_str(), uid.c_str());
	RegistrarDb::notifyContactListener(topic, uid);
}
<|endoftext|>


<commit_before>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef __RESEMBLA_REGRESSION_HPP__
#define __RESEMBLA_REGRESSION_HPP__

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <fstream>

#include "resembla_interface.hpp"
#include "regression/extractor/feature_extractor.hpp"
#include "reranker.hpp"

namespace resembla {

template<typename ScoreFunction>
class ResemblaRegression: public ResemblaInterface
{
public:
    ResemblaRegression(size_t max_candidate,
            std::shared_ptr<FeatureExtractor> feature_extractor, std::shared_ptr<ScoreFunction> score_func,
            std::string corpus_path = "", size_t feature_col = 2):
        max_candidate(max_candidate), preprocess(feature_extractor), score_func(score_func),
        reranker(), preprocess_corpus(!corpus_path.empty())
    {
        if(preprocess_corpus){
            loadCorpusFeatures(corpus_path, feature_col);
        }
    }

    void append(const std::string name, const std::shared_ptr<ResemblaInterface> resembla, bool is_primary = true)
    {
        resemblas[name] = resembla;
        if(is_primary && primary_resembla_name.empty()){
            primary_resembla_name = name;
        }
    }

    std::vector<output_type> find(const string_type& input, double threshold = 0.0, size_t max_response = 0)
    {
        std::vector<string_type> candidate_texts;
        std::unordered_map<string_type, StringFeatureMap> candidate_features;

        // primary resembla
        for(const auto& r: resemblas[primary_resembla_name]->find(input, threshold / 2.0, max_candidate * 2)){
            candidate_texts.push_back(r.text);
            candidate_features[r.text] = preprocess_corpus ? corpus_features[r.text] : (*preprocess)(r.text);
            candidate_features[r.text][primary_resembla_name] = Feature::toText(r.score);
        }

        // other resemblas
        for(const auto& p: resemblas){
            if(p.first == primary_resembla_name){
                continue;
            }
            for(auto r: p.second->eval(input, candidate_texts, threshold / 2.0, max_candidate * 2)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(const auto& c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(input, (*preprocess)(input));

        // rerank by its own metric
        std::vector<ResemblaInterface::output_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func, threshold, max_response)){
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

    std::vector<output_type> eval(const string_type& query, const std::vector<string_type>& targets, double threshold = 0.0, size_t max_response = 0)
    {
        std::unordered_map<string_type, StringFeatureMap> candidate_features;
        for(const auto& t: targets){
            candidate_features[t] = preprocess_corpus ? corpus_features[t] : (*preprocess)(t);
        }

        for(const auto& p: resemblas){
            for(const auto& r: p.second->eval(query, targets, threshold / 2.0, max_response * 2)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(const auto& c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(query, (*preprocess)(query));

        // rerank by its own metric
        std::vector<ResemblaInterface::output_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func, threshold, max_response)){
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

protected:
    using WorkData = std::pair<string_type, typename FeatureExtractor::output_type>;

    std::unordered_map<std::string, std::shared_ptr<ResemblaInterface>> resemblas;
    std::string primary_resembla_name;
    const size_t max_candidate;

    const std::shared_ptr<FeatureExtractor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    const bool preprocess_corpus;
    std::unordered_map<string_type, typename FeatureExtractor::output_type> corpus_features;

    void loadCorpusFeatures(const std::string& corpus_path, size_t features_col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(features_col - 1 < columns.size()){
                corpus_features[cast_string<string_type>(columns[0])] = (*preprocess)(columns[0], columns[features_col - 1]);
            }
        }
    }
};

}
#endif
<commit_msg>reduce redundant code in resembla_regression<commit_after>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef __RESEMBLA_REGRESSION_HPP__
#define __RESEMBLA_REGRESSION_HPP__

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <fstream>

#include "resembla_interface.hpp"
#include "regression/extractor/feature_extractor.hpp"
#include "reranker.hpp"

namespace resembla {

template<typename ScoreFunction>
class ResemblaRegression: public ResemblaInterface
{
public:
    ResemblaRegression(size_t max_candidate,
            std::shared_ptr<FeatureExtractor> feature_extractor, std::shared_ptr<ScoreFunction> score_func,
            std::string corpus_path = "", size_t feature_col = 2):
        max_candidate(max_candidate), preprocess(feature_extractor), score_func(score_func),
        reranker(), preprocess_corpus(!corpus_path.empty())
    {
        if(preprocess_corpus){
            loadCorpusFeatures(corpus_path, feature_col);
        }
    }

    void append(const std::string name, const std::shared_ptr<ResemblaInterface> resembla, bool is_primary = true)
    {
        resemblas[name] = resembla;
        if(is_primary && primary_resembla_name.empty()){
            primary_resembla_name = name;
        }
    }

    std::vector<output_type> find(const string_type& query, double threshold = 0.0, size_t max_response = 0)
    {
        std::vector<string_type> candidate_texts;
        std::unordered_map<string_type, StringFeatureMap> candidate_features;

        // primary resembla
        for(const auto& r: resemblas[primary_resembla_name]->find(query, threshold / 2.0, max_candidate * 2)){
            candidate_texts.push_back(r.text);
            candidate_features[r.text] = preprocess_corpus ? corpus_features[r.text] : (*preprocess)(r.text);
            candidate_features[r.text][primary_resembla_name] = Feature::toText(r.score);
        }

        // other resemblas
        for(const auto& p: resemblas){
            if(p.first == primary_resembla_name){
                continue;
            }
            for(auto r: p.second->eval(query, candidate_texts, threshold / 2.0, max_candidate * 2)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        return eval(query, candidate_features, threshold, max_response);
    }

    std::vector<output_type> eval(const string_type& query, const std::vector<string_type>& targets, double threshold = 0.0, size_t max_response = 0)
    {
        std::unordered_map<string_type, StringFeatureMap> candidate_features;
        for(const auto& t: targets){
            candidate_features[t] = preprocess_corpus ? corpus_features[t] : (*preprocess)(t);
        }

        for(const auto& p: resemblas){
            for(const auto& r: p.second->eval(query, targets, threshold / 2.0, max_response * 2)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        return eval(query, candidate_features, threshold, max_response);
    }

protected:
    std::vector<output_type> eval(const string_type& query, const std::unordered_map<string_type, StringFeatureMap>& candidate_features,
            double threshold, size_t max_response)
    {
        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(const auto& c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(query, (*preprocess)(query));

        // rerank by its own metric
        std::vector<ResemblaInterface::output_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func, threshold, max_response)){
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

    using WorkData = std::pair<string_type, typename FeatureExtractor::output_type>;

    std::unordered_map<std::string, std::shared_ptr<ResemblaInterface>> resemblas;
    std::string primary_resembla_name;
    const size_t max_candidate;

    const std::shared_ptr<FeatureExtractor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    const bool preprocess_corpus;
    std::unordered_map<string_type, typename FeatureExtractor::output_type> corpus_features;

    void loadCorpusFeatures(const std::string& corpus_path, size_t features_col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(features_col - 1 < columns.size()){
                corpus_features[cast_string<string_type>(columns[0])] = (*preprocess)(columns[0], columns[features_col - 1]);
            }
        }
    }
};

}
#endif
<|endoftext|>


<commit_before>#ifndef WIGWAG_SIGNAL_HPP
#define WIGWAG_SIGNAL_HPP

// Copyright (c) 2016, Dmitry Koplyarov <koplyarov.da@gmail.com>
//
// Permission to use, copy, modify, and/or 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 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR 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 <wigwag/detail/creation_storage_adapter.hpp>
#include <wigwag/detail/policies_concepts.hpp>
#include <wigwag/detail/policy_picker.hpp>
#include <wigwag/detail/signal_impl.hpp>
#include <wigwag/policies.hpp>
#include <wigwag/signal_connector.hpp>

namespace wigwag
{

#include <wigwag/detail/disable_warnings.hpp>

	namespace detail
	{
		using signal_policies_config = policies_config<
				policies_config_entry<exception_handling::policy_concept, wigwag::exception_handling::default_>,
				policies_config_entry<threading::policy_concept, wigwag::threading::default_>,
				policies_config_entry<state_populating::policy_concept, wigwag::state_populating::default_>,
				policies_config_entry<life_assurance::policy_concept, wigwag::life_assurance::default_>,
				policies_config_entry<creation::policy_concept, wigwag::creation::default_>,
				policies_config_entry<ref_counter::policy_concept, wigwag::ref_counter::default_>
			>;

		template < typename T_ >
		struct signature_getter
		{ using type = T_; };
	}

	template <
			typename Signature_,
			typename... Policies_
		>
	class signal;

	template <
			typename RetType_,
			typename... ArgTypes_,
			typename... Policies_
		>
	class signal<RetType_(ArgTypes_...), Policies_...>
	{
		using signature = typename detail::signature_getter<RetType_(ArgTypes_...)>::type;

		template < template <typename> class PolicyConcept_ >
		using policy = typename detail::policy_picker<PolicyConcept_, detail::signal_policies_config, Policies_...>::type;

		using exception_handling_policy = policy<detail::exception_handling::policy_concept>;
		using threading_policy = policy<detail::threading::policy_concept>;
		using state_populating_policy = policy<detail::state_populating::policy_concept>;
		using life_assurance_policy = policy<detail::life_assurance::policy_concept>;
		using creation_policy = policy<detail::creation::policy_concept>;
		using ref_counter_policy = policy<detail::ref_counter::policy_concept>;

	public:
		using handler_type = std::function<signature>;

	private:
		using impl_type = detail::signal_impl<signature, exception_handling_policy, threading_policy, state_populating_policy, life_assurance_policy, ref_counter_policy>;
		using impl_type_with_attr = detail::signal_with_attributes_impl<signature, exception_handling_policy, threading_policy, state_populating_policy, life_assurance_policy, ref_counter_policy>;
		using impl_type_ptr = detail::intrusive_ptr<impl_type>;

		using storage = typename creation_policy::template storage<impl_type_ptr, impl_type>;

	private:
		detail::creation_storage_adapter<storage>		_impl;

	public:
		template < typename... Args_ >
		signal(signal_attributes attributes, Args_&&... args)
		{
			if (attributes == signal_attributes::none)
				_impl.template create<impl_type>(std::forward<Args_>(args)...);
			else
				_impl.template create<impl_type_with_attr>(attributes, std::forward<Args_>(args)...);
		}

		template < typename Arg0_, typename... Args_ >
		signal(Arg0_&& arg0, Args_&&... args)
		{ _impl.template create<impl_type>(std::forward<Arg0_>(arg0), std::forward<Args_>(args)...); }

		template < bool has_default_ctor = std::is_constructible<impl_type>::value, typename = typename std::enable_if<has_default_ctor>::type >
		signal()
		{ _impl.template create<impl_type>(); }

		~signal()
		{
			if (_impl)
			{
				_impl->get_lock_primitive().lock_nonrecursive();
				auto sg = detail::at_scope_exit([&] { _impl->get_lock_primitive().unlock_nonrecursive(); } );

				_impl->finalize_nodes();
			}
		}

		signal(const signal&) = delete;
		signal& operator = (const signal&) = delete;

		auto lock_primitive() const -> decltype(_impl->get_lock_primitive().get_primitive())
		{ return _impl->get_lock_primitive().get_primitive(); }

		signal_connector<signature> connector() const
		{ return signal_connector<signature>(_impl.get_ptr()); }

		template < typename HandlerFunc_ >
		token connect(HandlerFunc_ handler, handler_attributes attributes = handler_attributes::none) const
		{ return _impl->connect(std::move(handler), attributes); }

		template < typename HandlerFunc_ >
		token connect(std::shared_ptr<task_executor> worker, HandlerFunc_ handler, handler_attributes attributes = handler_attributes::none) const
		{ return _impl->connect(std::move(worker), std::move(handler), attributes); }

		void operator() (ArgTypes_... args) const
		{
			if (_impl)
				_impl->invoke(args...);
		}
	};

#include <wigwag/detail/enable_warnings.hpp>

}

#endif
<commit_msg>Removed RetType_ from signal specialization template arguments<commit_after>#ifndef WIGWAG_SIGNAL_HPP
#define WIGWAG_SIGNAL_HPP

// Copyright (c) 2016, Dmitry Koplyarov <koplyarov.da@gmail.com>
//
// Permission to use, copy, modify, and/or 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 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR 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 <wigwag/detail/creation_storage_adapter.hpp>
#include <wigwag/detail/policies_concepts.hpp>
#include <wigwag/detail/policy_picker.hpp>
#include <wigwag/detail/signal_impl.hpp>
#include <wigwag/policies.hpp>
#include <wigwag/signal_connector.hpp>

namespace wigwag
{

#include <wigwag/detail/disable_warnings.hpp>

	namespace detail
	{
		using signal_policies_config = policies_config<
				policies_config_entry<exception_handling::policy_concept, wigwag::exception_handling::default_>,
				policies_config_entry<threading::policy_concept, wigwag::threading::default_>,
				policies_config_entry<state_populating::policy_concept, wigwag::state_populating::default_>,
				policies_config_entry<life_assurance::policy_concept, wigwag::life_assurance::default_>,
				policies_config_entry<creation::policy_concept, wigwag::creation::default_>,
				policies_config_entry<ref_counter::policy_concept, wigwag::ref_counter::default_>
			>;

		template < typename T_ >
		struct signature_getter
		{ using type = T_; };
	}

	template <
			typename Signature_,
			typename... Policies_
		>
	class signal;

	template <
			typename... ArgTypes_,
			typename... Policies_
		>
	class signal<void(ArgTypes_...), Policies_...>
	{
	public:
		using signature = typename detail::signature_getter<void(ArgTypes_...)>::type;

	private:
		template < template <typename> class PolicyConcept_ >
		using policy = typename detail::policy_picker<PolicyConcept_, detail::signal_policies_config, Policies_...>::type;

		using exception_handling_policy = policy<detail::exception_handling::policy_concept>;
		using threading_policy = policy<detail::threading::policy_concept>;
		using state_populating_policy = policy<detail::state_populating::policy_concept>;
		using life_assurance_policy = policy<detail::life_assurance::policy_concept>;
		using creation_policy = policy<detail::creation::policy_concept>;
		using ref_counter_policy = policy<detail::ref_counter::policy_concept>;

	public:
		using handler_type = std::function<signature>;

	private:
		using impl_type = detail::signal_impl<signature, exception_handling_policy, threading_policy, state_populating_policy, life_assurance_policy, ref_counter_policy>;
		using impl_type_with_attr = detail::signal_with_attributes_impl<signature, exception_handling_policy, threading_policy, state_populating_policy, life_assurance_policy, ref_counter_policy>;
		using impl_type_ptr = detail::intrusive_ptr<impl_type>;

		using storage = typename creation_policy::template storage<impl_type_ptr, impl_type>;

	private:
		detail::creation_storage_adapter<storage>		_impl;

	public:
		template < typename... Args_ >
		signal(signal_attributes attributes, Args_&&... args)
		{
			if (attributes == signal_attributes::none)
				_impl.template create<impl_type>(std::forward<Args_>(args)...);
			else
				_impl.template create<impl_type_with_attr>(attributes, std::forward<Args_>(args)...);
		}

		template < typename Arg0_, typename... Args_ >
		signal(Arg0_&& arg0, Args_&&... args)
		{ _impl.template create<impl_type>(std::forward<Arg0_>(arg0), std::forward<Args_>(args)...); }

		template < bool has_default_ctor = std::is_constructible<impl_type>::value, typename = typename std::enable_if<has_default_ctor>::type >
		signal()
		{ _impl.template create<impl_type>(); }

		~signal()
		{
			if (_impl)
			{
				_impl->get_lock_primitive().lock_nonrecursive();
				auto sg = detail::at_scope_exit([&] { _impl->get_lock_primitive().unlock_nonrecursive(); } );

				_impl->finalize_nodes();
			}
		}

		signal(const signal&) = delete;
		signal& operator = (const signal&) = delete;

		auto lock_primitive() const -> decltype(_impl->get_lock_primitive().get_primitive())
		{ return _impl->get_lock_primitive().get_primitive(); }

		signal_connector<signature> connector() const
		{ return signal_connector<signature>(_impl.get_ptr()); }

		template < typename HandlerFunc_ >
		token connect(HandlerFunc_ handler, handler_attributes attributes = handler_attributes::none) const
		{ return _impl->connect(std::move(handler), attributes); }

		template < typename HandlerFunc_ >
		token connect(std::shared_ptr<task_executor> worker, HandlerFunc_ handler, handler_attributes attributes = handler_attributes::none) const
		{ return _impl->connect(std::move(worker), std::move(handler), attributes); }

		void operator() (ArgTypes_... args) const
		{
			if (_impl)
				_impl->invoke(args...);
		}
	};

#include <wigwag/detail/enable_warnings.hpp>

}

#endif
<|endoftext|>


<commit_before><commit_msg>Fix debug level for dumping intermediate files<commit_after><|endoftext|>


<commit_before>#include <Python.h>
#include "PyDKPython.h"
#include "DCObject.h"

using namespace DKFoundation;
using namespace DKFramework;

// 사이즈 체크.
static_assert(SIZEOF_LONG == sizeof(long), "size mismatch");
static_assert(SIZEOF_SIZE_T == sizeof(size_t), "size mismatch");
static_assert(SIZEOF_TIME_T == sizeof(time_t), "size mismatch");
static_assert(SIZEOF_VOID_P == sizeof(void*), "size mismatch");
static_assert(SIZEOF_DOUBLE == sizeof(double), "size mismatch");
static_assert(SIZEOF_FLOAT == sizeof(float), "size mismatch");
static_assert(SIZEOF_FPOS_T == sizeof(fpos_t), "size mismatch");
static_assert(SIZEOF_INT == sizeof(int), "size mismatch");
static_assert(SIZEOF_LONG_LONG == sizeof(long long), "size mismatch");
static_assert(SIZEOF_OFF_T == sizeof(off_t), "size mismatch");
static_assert(SIZEOF_SHORT == sizeof(short), "size mismatch");
static_assert(SIZEOF_WCHAR_T == sizeof(wchar_t), "size mismatch");

#ifndef _MSC_VER
#include <pthread.h>
//static_assert(SIZEOF__BOOL == sizeof(_Bool), "size mismatch");
static_assert(SIZEOF_LONG_DOUBLE == sizeof(long double), "size mismatch");
static_assert(SIZEOF_UINTPTR_T == sizeof(uintptr_t), "size mismatch");
static_assert(SIZEOF_PID_T == sizeof(pid_t), "size mismatch");
static_assert(SIZEOF_PTHREAD_T == sizeof(pthread_t), "size mismatch");
#endif

PyMODINIT_FUNC PyInit__dk_core(void)
{
	auto version = [](PyObject*, PyObject*)->PyObject*
	{
		const char* str = DKVersion();
		return PyUnicode_FromString(str);
	};
	auto copyright = [](PyObject*, PyObject*)->PyObject*
	{
		const char* str = DKCopyright();
		return PyUnicode_FromString(str);
	};
	auto build = [](PyObject*, PyObject*)->PyObject*
	{
		if (IsDebugBuild())
			return PyUnicode_FromString("Debug");
		return PyUnicode_FromString("Release");
	};
	auto isDebugBuild = [](PyObject*, PyObject*)->PyObject*
	{
		return PyBool_FromLong(IsDebugBuild());
	};
	auto platform = [](PyObject*, PyObject*)->PyObject*
	{
#if   defined(DKLIB_WIN32)
		return PyUnicode_FromString("windows");
#elif defined(DKLIB_APPLE_OSX)
		return PyUnicode_FromString("osx");
#elif defined(DKLIB_APPLE_IOS)
		return PyUnicode_FromString("ios");
#elif defined(DKLIB_LINUX)
	#ifdef __ANDROID__
		return PyUnicode_FromString("android");
	#else
		return PyUnicode_FromString("linux");
	#endif
#endif
		return PyUnicode_FromString("unknown");
	};
	auto random = [](PyObject*, PyObject*)->PyObject*
	{
		return PyLong_FromLong(DKRandom());
	};
	auto temporaryDirectory = [](PyObject*, PyObject*)->PyObject*
	{
		DKString str = DKTemporaryDirectory();
		return PyUnicode_FromWideChar(str, -1);
	};
	auto processArguments = [](PyObject*, PyObject*)->PyObject*
	{
		DKArray<DKString> args = DKProcessArguments();
		PyObject* tuple = PyTuple_New(args.Count());
		for (Py_ssize_t i = 0; i < args.Count(); ++i)
		{
			PyObject* obj = PyUnicode_FromWideChar(args.Value(i), -1);
			PyTuple_SET_ITEM(tuple, i, obj);
		}
		return tuple;
	};
	auto processEnvironments = [](PyObject*, PyObject*)->PyObject*
	{
		DKMap<DKString, DKString> envs = DKProcessEnvironments();
		PyObject* dict = PyDict_New();
		envs.EnumerateForward([&](DKMap<DKString, DKString>::Pair& pair)
		{
			PyObject* key = PyUnicode_FromWideChar(pair.key, -1);
			PyObject* val = PyUnicode_FromWideChar(pair.value, -1);

			PyDict_SetItem(dict, key, val);

			Py_DECREF(key);
			Py_DECREF(val);
		});
		return dict;
	};
	auto uuidgen = [](PyObject*, PyObject*)->PyObject*
	{
		return PyUnicode_FromWideChar(DKUUID::Create().String(), -1);
	};
	auto logger = [](PyObject*, PyObject* args)->PyObject*
	{
		const char* str;
		if (!PyArg_ParseTuple(args, "s", &str))
			return NULL;

		DKLog("%s", str);
		Py_RETURN_NONE;
	};
	auto objectCount = [](PyObject*, PyObject*)->PyObject*
	{
		return PyLong_FromSize_t(DCObjectCount());
	};
	auto threadSleep = [](PyObject*, PyObject* args)->PyObject*
	{
		double t = 0.0;
		if (!PyArg_ParseTuple(args, "d", &t))
			return NULL;

		Py_BEGIN_ALLOW_THREADS
		DKThread::Sleep(t);
		Py_END_ALLOW_THREADS
		Py_RETURN_NONE;
	};
	auto threadYield = [](PyObject*, PyObject*)->PyObject*
	{
		Py_BEGIN_ALLOW_THREADS
		DKThread::Yield();
		Py_END_ALLOW_THREADS
		Py_RETURN_NONE;
	};
	auto setDefaultClass = [](PyObject*, PyObject* args)->PyObject*
	{
		PyTypeObject* baseType = NULL;
		PyTypeObject* defaultType = NULL;
		if (!PyArg_ParseTuple(args, "O|O", &baseType, &defaultType))
			return NULL;

		if (!PyType_Check(baseType))
		{
			PyErr_Format(PyExc_TypeError, "first argument must a type object, not %.200s", Py_TYPE(baseType)->tp_name);
			return NULL;
		}
		if (defaultType)
		{
			if (!PyType_Check(defaultType))
			{
				PyErr_Format(PyExc_TypeError, "second argument must a type object, not %.200s", Py_TYPE(defaultType)->tp_name);
				return NULL;
			}
			if (!PyType_IsSubtype(defaultType, baseType))
			{
				PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", defaultType->tp_name, baseType->tp_name);
				return NULL;
			}
		}
		if (DCObjectSetDefaultClass(baseType, defaultType))
		{
			Py_RETURN_NONE;
		}
		PyErr_Format(PyExc_TypeError, "Cannot set default type. base type %.200s may not exist.", baseType->tp_name);
		return NULL;
	};
	auto defaultClass = [](PyObject*, PyObject* args)->PyObject*
	{
		PyTypeObject* baseType = NULL;
		if (!PyArg_ParseTuple(args, "O", &baseType))
			return NULL;

		if (!PyType_Check(baseType))
		{
			PyErr_Format(PyExc_TypeError, "argument must a type object, not %.200s", Py_TYPE(baseType)->tp_name);
			return NULL;
		}
		PyTypeObject* defaultType = DCObjectDefaultClass(baseType);
		if (defaultType)
		{
			Py_INCREF(defaultType);
			return (PyObject*)defaultType;
		}
		PyErr_Format(PyExc_TypeError, "Cannot set default type. base type %.200s may not exist.", baseType->tp_name);
		return NULL;
	};
	static PyMethodDef methods[] = {
		{ "version", version, METH_NOARGS },
		{ "copyright", copyright, METH_NOARGS },
		{ "build", build, METH_NOARGS },
		{ "isDebugBuild", isDebugBuild, METH_NOARGS },
		{ "platform", platform, METH_NOARGS },
		{ "random", random, METH_NOARGS },
		{ "temporaryDirectory", temporaryDirectory, METH_NOARGS },
		{ "processArguments", processArguments, METH_NOARGS },
		{ "processEnvironments", processEnvironments, METH_NOARGS },
		{ "uuidgen", uuidgen, METH_NOARGS },
		{ "objectCount", objectCount, METH_NOARGS },
		{ "threadSleep", threadSleep, METH_VARARGS },
		{ "threadYield", threadYield, METH_VARARGS },
		{ "log", logger, METH_VARARGS },
		{ "setDefaultClass", setDefaultClass, METH_VARARGS },
		{ "defaultClass", defaultClass, METH_VARARGS },
		{ 0, 0, 0, 0 }
	};
	static PyModuleDef igpy_module = {
		PyModuleDef_HEAD_INIT,
		PYDK_MODULE_NAME,
		PYDK_MODULE_DESC,
		-1,
		methods,
	};

	struct CoreTypes
	{
		const char* name;
		PyTypeObject* (*func)(void);
	};
#define CORE_TYPE_FUNC(x) { #x, PYDK_CORE_TYPE(x) }
	std::initializer_list<CoreTypes> types = {
		CORE_TYPE_FUNC(Data),
		CORE_TYPE_FUNC(Timer),
		CORE_TYPE_FUNC(Stream),
		CORE_TYPE_FUNC(ZipArchiver),
		CORE_TYPE_FUNC(ZipUnarchiver),
		CORE_TYPE_FUNC(RunLoopTimer),
		CORE_TYPE_FUNC(RunLoopOperationResult),
		CORE_TYPE_FUNC(Point),
		CORE_TYPE_FUNC(Size),
		CORE_TYPE_FUNC(Rect),
		CORE_TYPE_FUNC(Spline),
		CORE_TYPE_FUNC(Vector2),
		CORE_TYPE_FUNC(Vector3),
		CORE_TYPE_FUNC(Vector4),
		CORE_TYPE_FUNC(Quaternion),
		CORE_TYPE_FUNC(Matrix2),
		CORE_TYPE_FUNC(Matrix3),
		CORE_TYPE_FUNC(Matrix4),
		CORE_TYPE_FUNC(LinearTransform2),
		CORE_TYPE_FUNC(LinearTransform3),
		CORE_TYPE_FUNC(AffineTransform2),
		CORE_TYPE_FUNC(AffineTransform3),
		CORE_TYPE_FUNC(TransformUnit),
		CORE_TYPE_FUNC(USTransform),
		CORE_TYPE_FUNC(NSTransform),
		CORE_TYPE_FUNC(Color),
		CORE_TYPE_FUNC(App),
		CORE_TYPE_FUNC(Window),
		CORE_TYPE_FUNC(Screen),
		CORE_TYPE_FUNC(Frame),
		CORE_TYPE_FUNC(OpenGLContext),
		CORE_TYPE_FUNC(Renderer),
		CORE_TYPE_FUNC(BlendState),
		CORE_TYPE_FUNC(Font),
		CORE_TYPE_FUNC(Camera),
		CORE_TYPE_FUNC(RenderTarget),
		CORE_TYPE_FUNC(TextureSampler),
		CORE_TYPE_FUNC(Resource),
		CORE_TYPE_FUNC(Animation),
		CORE_TYPE_FUNC(GeometryBuffer),
		CORE_TYPE_FUNC(VertexBuffer),
		CORE_TYPE_FUNC(IndexBuffer),
		CORE_TYPE_FUNC(Material),
		CORE_TYPE_FUNC(Model),
		CORE_TYPE_FUNC(ActionController),
		CORE_TYPE_FUNC(CollisionObject),
		CORE_TYPE_FUNC(RigidBody),
		CORE_TYPE_FUNC(SoftBody),
		CORE_TYPE_FUNC(Constraint),
		CORE_TYPE_FUNC(ConeTwistConstraint),
		CORE_TYPE_FUNC(FixedConstraint),
		CORE_TYPE_FUNC(GearConstraint),
		CORE_TYPE_FUNC(Generic6DofConstraint),
		CORE_TYPE_FUNC(Generic6DofSpringConstraint),
		CORE_TYPE_FUNC(HingeConstraint),
		CORE_TYPE_FUNC(Point2PointConstraint),
		CORE_TYPE_FUNC(SliderConstraint),
		CORE_TYPE_FUNC(Mesh),
		CORE_TYPE_FUNC(StaticMesh),
		CORE_TYPE_FUNC(SkinMesh),
		CORE_TYPE_FUNC(Shader),
		CORE_TYPE_FUNC(ShaderProgram),
		CORE_TYPE_FUNC(Texture),
		CORE_TYPE_FUNC(Texture2D),
		CORE_TYPE_FUNC(Texture3D),
		CORE_TYPE_FUNC(TextureCube),
		CORE_TYPE_FUNC(CollisionShape),
		CORE_TYPE_FUNC(CompoundShape),
		CORE_TYPE_FUNC(ConcaveShape),
		CORE_TYPE_FUNC(StaticPlaneShape),
		CORE_TYPE_FUNC(StaticTriangleMeshShape),
		CORE_TYPE_FUNC(ConvexShape),
		CORE_TYPE_FUNC(CapsuleShape),
		CORE_TYPE_FUNC(ConeShape),
		CORE_TYPE_FUNC(CylinderShape),
		CORE_TYPE_FUNC(MultiSphereShape),
		CORE_TYPE_FUNC(PolyhedralConvexShape),
		CORE_TYPE_FUNC(BoxShape),
		CORE_TYPE_FUNC(ConvexHullShape),
		CORE_TYPE_FUNC(SphereShape),
		CORE_TYPE_FUNC(ResourceLoader),
		CORE_TYPE_FUNC(Scene),
		CORE_TYPE_FUNC(DynamicsScene),
		CORE_TYPE_FUNC(AnimatedTransform),
		CORE_TYPE_FUNC(AnimationController),
		CORE_TYPE_FUNC(AudioListener),
		CORE_TYPE_FUNC(AudioPlayer),
		CORE_TYPE_FUNC(AudioSource)
	};
	for (auto& t : types)
	{
		PyTypeObject* type = t.func();
		if (PyType_Ready(type) < 0)
			return NULL;
	}

	PyObject* module = PyModule_Create(&igpy_module);
	if (module == NULL)
		return NULL;

	for (auto& t : types)
	{
		PyTypeObject* type = t.func();
		Py_INCREF(type);
		PyModule_AddObject(module, t.name, (PyObject*)type);
	}

	auto typesIterBegin = types.begin();
	auto typesIterEnd = types.end();
	DCObjectInitDefaultClasses(types.size(), DKFunction([&typesIterBegin, &typesIterEnd]()->PyTypeObject*
	{
		PyTypeObject* tp = NULL;
		if (typesIterBegin != typesIterEnd)
		{
			tp = typesIterBegin->func();
			typesIterBegin++;
		}
		return tp;
	})->Invocation());

	PyEval_InitThreads();

	return module;
}
<commit_msg>cleanup() added.<commit_after>#include <Python.h>
#include "PyDKPython.h"
#include "DCObject.h"

using namespace DKFoundation;
using namespace DKFramework;

// 사이즈 체크.
static_assert(SIZEOF_LONG == sizeof(long), "size mismatch");
static_assert(SIZEOF_SIZE_T == sizeof(size_t), "size mismatch");
static_assert(SIZEOF_TIME_T == sizeof(time_t), "size mismatch");
static_assert(SIZEOF_VOID_P == sizeof(void*), "size mismatch");
static_assert(SIZEOF_DOUBLE == sizeof(double), "size mismatch");
static_assert(SIZEOF_FLOAT == sizeof(float), "size mismatch");
static_assert(SIZEOF_FPOS_T == sizeof(fpos_t), "size mismatch");
static_assert(SIZEOF_INT == sizeof(int), "size mismatch");
static_assert(SIZEOF_LONG_LONG == sizeof(long long), "size mismatch");
static_assert(SIZEOF_OFF_T == sizeof(off_t), "size mismatch");
static_assert(SIZEOF_SHORT == sizeof(short), "size mismatch");
static_assert(SIZEOF_WCHAR_T == sizeof(wchar_t), "size mismatch");

#ifndef _MSC_VER
#include <pthread.h>
//static_assert(SIZEOF__BOOL == sizeof(_Bool), "size mismatch");
static_assert(SIZEOF_LONG_DOUBLE == sizeof(long double), "size mismatch");
static_assert(SIZEOF_UINTPTR_T == sizeof(uintptr_t), "size mismatch");
static_assert(SIZEOF_PID_T == sizeof(pid_t), "size mismatch");
static_assert(SIZEOF_PTHREAD_T == sizeof(pthread_t), "size mismatch");
#endif

PyMODINIT_FUNC PyInit__dk_core(void)
{
	auto version = [](PyObject*, PyObject*)->PyObject*
	{
		const char* str = DKVersion();
		return PyUnicode_FromString(str);
	};
	auto copyright = [](PyObject*, PyObject*)->PyObject*
	{
		const char* str = DKCopyright();
		return PyUnicode_FromString(str);
	};
	auto build = [](PyObject*, PyObject*)->PyObject*
	{
		if (IsDebugBuild())
			return PyUnicode_FromString("Debug");
		return PyUnicode_FromString("Release");
	};
	auto isDebugBuild = [](PyObject*, PyObject*)->PyObject*
	{
		return PyBool_FromLong(IsDebugBuild());
	};
	auto platform = [](PyObject*, PyObject*)->PyObject*
	{
#if   defined(DKLIB_WIN32)
		return PyUnicode_FromString("windows");
#elif defined(DKLIB_APPLE_OSX)
		return PyUnicode_FromString("osx");
#elif defined(DKLIB_APPLE_IOS)
		return PyUnicode_FromString("ios");
#elif defined(DKLIB_LINUX)
	#ifdef __ANDROID__
		return PyUnicode_FromString("android");
	#else
		return PyUnicode_FromString("linux");
	#endif
#endif
		return PyUnicode_FromString("unknown");
	};
	auto random = [](PyObject*, PyObject*)->PyObject*
	{
		return PyLong_FromLong(DKRandom());
	};
	auto temporaryDirectory = [](PyObject*, PyObject*)->PyObject*
	{
		DKString str = DKTemporaryDirectory();
		return PyUnicode_FromWideChar(str, -1);
	};
	auto processArguments = [](PyObject*, PyObject*)->PyObject*
	{
		DKArray<DKString> args = DKProcessArguments();
		PyObject* tuple = PyTuple_New(args.Count());
		for (Py_ssize_t i = 0; i < args.Count(); ++i)
		{
			PyObject* obj = PyUnicode_FromWideChar(args.Value(i), -1);
			PyTuple_SET_ITEM(tuple, i, obj);
		}
		return tuple;
	};
	auto processEnvironments = [](PyObject*, PyObject*)->PyObject*
	{
		DKMap<DKString, DKString> envs = DKProcessEnvironments();
		PyObject* dict = PyDict_New();
		envs.EnumerateForward([&](DKMap<DKString, DKString>::Pair& pair)
		{
			PyObject* key = PyUnicode_FromWideChar(pair.key, -1);
			PyObject* val = PyUnicode_FromWideChar(pair.value, -1);

			PyDict_SetItem(dict, key, val);

			Py_DECREF(key);
			Py_DECREF(val);
		});
		return dict;
	};
	auto uuidgen = [](PyObject*, PyObject*)->PyObject*
	{
		return PyUnicode_FromWideChar(DKUUID::Create().String(), -1);
	};
	auto logger = [](PyObject*, PyObject* args)->PyObject*
	{
		const char* str;
		if (!PyArg_ParseTuple(args, "s", &str))
			return NULL;

		DKLog("%s", str);
		Py_RETURN_NONE;
	};
	auto cleanup = [](PyObject*, PyObject*)->PyObject*
	{
		DKAllocatorChain::Cleanup();
		Py_RETURN_NONE;
	};
	auto objectCount = [](PyObject*, PyObject*)->PyObject*
	{
		return PyLong_FromSize_t(DCObjectCount());
	};
	auto threadSleep = [](PyObject*, PyObject* args)->PyObject*
	{
		double t = 0.0;
		if (!PyArg_ParseTuple(args, "d", &t))
			return NULL;

		Py_BEGIN_ALLOW_THREADS
		DKThread::Sleep(t);
		Py_END_ALLOW_THREADS
		Py_RETURN_NONE;
	};
	auto threadYield = [](PyObject*, PyObject*)->PyObject*
	{
		Py_BEGIN_ALLOW_THREADS
		DKThread::Yield();
		Py_END_ALLOW_THREADS
		Py_RETURN_NONE;
	};
	auto setDefaultClass = [](PyObject*, PyObject* args)->PyObject*
	{
		PyTypeObject* baseType = NULL;
		PyTypeObject* defaultType = NULL;
		if (!PyArg_ParseTuple(args, "O|O", &baseType, &defaultType))
			return NULL;

		if (!PyType_Check(baseType))
		{
			PyErr_Format(PyExc_TypeError, "first argument must a type object, not %.200s", Py_TYPE(baseType)->tp_name);
			return NULL;
		}
		if (defaultType)
		{
			if (!PyType_Check(defaultType))
			{
				PyErr_Format(PyExc_TypeError, "second argument must a type object, not %.200s", Py_TYPE(defaultType)->tp_name);
				return NULL;
			}
			if (!PyType_IsSubtype(defaultType, baseType))
			{
				PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", defaultType->tp_name, baseType->tp_name);
				return NULL;
			}
		}
		if (DCObjectSetDefaultClass(baseType, defaultType))
		{
			Py_RETURN_NONE;
		}
		PyErr_Format(PyExc_TypeError, "Cannot set default type. base type %.200s may not exist.", baseType->tp_name);
		return NULL;
	};
	auto defaultClass = [](PyObject*, PyObject* args)->PyObject*
	{
		PyTypeObject* baseType = NULL;
		if (!PyArg_ParseTuple(args, "O", &baseType))
			return NULL;

		if (!PyType_Check(baseType))
		{
			PyErr_Format(PyExc_TypeError, "argument must a type object, not %.200s", Py_TYPE(baseType)->tp_name);
			return NULL;
		}
		PyTypeObject* defaultType = DCObjectDefaultClass(baseType);
		if (defaultType)
		{
			Py_INCREF(defaultType);
			return (PyObject*)defaultType;
		}
		PyErr_Format(PyExc_TypeError, "Cannot set default type. base type %.200s may not exist.", baseType->tp_name);
		return NULL;
	};
	static PyMethodDef methods[] = {
		{ "version", version, METH_NOARGS },
		{ "copyright", copyright, METH_NOARGS },
		{ "build", build, METH_NOARGS },
		{ "isDebugBuild", isDebugBuild, METH_NOARGS },
		{ "platform", platform, METH_NOARGS },
		{ "random", random, METH_NOARGS },
		{ "temporaryDirectory", temporaryDirectory, METH_NOARGS },
		{ "processArguments", processArguments, METH_NOARGS },
		{ "processEnvironments", processEnvironments, METH_NOARGS },
		{ "uuidgen", uuidgen, METH_NOARGS },
		{ "cleanup", cleanup, METH_NOARGS },
		{ "objectCount", objectCount, METH_NOARGS },
		{ "threadSleep", threadSleep, METH_VARARGS },
		{ "threadYield", threadYield, METH_VARARGS },
		{ "log", logger, METH_VARARGS },
		{ "setDefaultClass", setDefaultClass, METH_VARARGS },
		{ "defaultClass", defaultClass, METH_VARARGS },
		{ 0, 0, 0, 0 }
	};
	static PyModuleDef igpy_module = {
		PyModuleDef_HEAD_INIT,
		PYDK_MODULE_NAME,
		PYDK_MODULE_DESC,
		-1,
		methods,
	};

	struct CoreTypes
	{
		const char* name;
		PyTypeObject* (*func)(void);
	};
#define CORE_TYPE_FUNC(x) { #x, PYDK_CORE_TYPE(x) }
	std::initializer_list<CoreTypes> types = {
		CORE_TYPE_FUNC(Data),
		CORE_TYPE_FUNC(Timer),
		CORE_TYPE_FUNC(Stream),
		CORE_TYPE_FUNC(ZipArchiver),
		CORE_TYPE_FUNC(ZipUnarchiver),
		CORE_TYPE_FUNC(RunLoopTimer),
		CORE_TYPE_FUNC(RunLoopOperationResult),
		CORE_TYPE_FUNC(Point),
		CORE_TYPE_FUNC(Size),
		CORE_TYPE_FUNC(Rect),
		CORE_TYPE_FUNC(Spline),
		CORE_TYPE_FUNC(Vector2),
		CORE_TYPE_FUNC(Vector3),
		CORE_TYPE_FUNC(Vector4),
		CORE_TYPE_FUNC(Quaternion),
		CORE_TYPE_FUNC(Matrix2),
		CORE_TYPE_FUNC(Matrix3),
		CORE_TYPE_FUNC(Matrix4),
		CORE_TYPE_FUNC(LinearTransform2),
		CORE_TYPE_FUNC(LinearTransform3),
		CORE_TYPE_FUNC(AffineTransform2),
		CORE_TYPE_FUNC(AffineTransform3),
		CORE_TYPE_FUNC(TransformUnit),
		CORE_TYPE_FUNC(USTransform),
		CORE_TYPE_FUNC(NSTransform),
		CORE_TYPE_FUNC(Color),
		CORE_TYPE_FUNC(App),
		CORE_TYPE_FUNC(Window),
		CORE_TYPE_FUNC(Screen),
		CORE_TYPE_FUNC(Frame),
		CORE_TYPE_FUNC(OpenGLContext),
		CORE_TYPE_FUNC(Renderer),
		CORE_TYPE_FUNC(BlendState),
		CORE_TYPE_FUNC(Font),
		CORE_TYPE_FUNC(Camera),
		CORE_TYPE_FUNC(RenderTarget),
		CORE_TYPE_FUNC(TextureSampler),
		CORE_TYPE_FUNC(Resource),
		CORE_TYPE_FUNC(Animation),
		CORE_TYPE_FUNC(GeometryBuffer),
		CORE_TYPE_FUNC(VertexBuffer),
		CORE_TYPE_FUNC(IndexBuffer),
		CORE_TYPE_FUNC(Material),
		CORE_TYPE_FUNC(Model),
		CORE_TYPE_FUNC(ActionController),
		CORE_TYPE_FUNC(CollisionObject),
		CORE_TYPE_FUNC(RigidBody),
		CORE_TYPE_FUNC(SoftBody),
		CORE_TYPE_FUNC(Constraint),
		CORE_TYPE_FUNC(ConeTwistConstraint),
		CORE_TYPE_FUNC(FixedConstraint),
		CORE_TYPE_FUNC(GearConstraint),
		CORE_TYPE_FUNC(Generic6DofConstraint),
		CORE_TYPE_FUNC(Generic6DofSpringConstraint),
		CORE_TYPE_FUNC(HingeConstraint),
		CORE_TYPE_FUNC(Point2PointConstraint),
		CORE_TYPE_FUNC(SliderConstraint),
		CORE_TYPE_FUNC(Mesh),
		CORE_TYPE_FUNC(StaticMesh),
		CORE_TYPE_FUNC(SkinMesh),
		CORE_TYPE_FUNC(Shader),
		CORE_TYPE_FUNC(ShaderProgram),
		CORE_TYPE_FUNC(Texture),
		CORE_TYPE_FUNC(Texture2D),
		CORE_TYPE_FUNC(Texture3D),
		CORE_TYPE_FUNC(TextureCube),
		CORE_TYPE_FUNC(CollisionShape),
		CORE_TYPE_FUNC(CompoundShape),
		CORE_TYPE_FUNC(ConcaveShape),
		CORE_TYPE_FUNC(StaticPlaneShape),
		CORE_TYPE_FUNC(StaticTriangleMeshShape),
		CORE_TYPE_FUNC(ConvexShape),
		CORE_TYPE_FUNC(CapsuleShape),
		CORE_TYPE_FUNC(ConeShape),
		CORE_TYPE_FUNC(CylinderShape),
		CORE_TYPE_FUNC(MultiSphereShape),
		CORE_TYPE_FUNC(PolyhedralConvexShape),
		CORE_TYPE_FUNC(BoxShape),
		CORE_TYPE_FUNC(ConvexHullShape),
		CORE_TYPE_FUNC(SphereShape),
		CORE_TYPE_FUNC(ResourceLoader),
		CORE_TYPE_FUNC(Scene),
		CORE_TYPE_FUNC(DynamicsScene),
		CORE_TYPE_FUNC(AnimatedTransform),
		CORE_TYPE_FUNC(AnimationController),
		CORE_TYPE_FUNC(AudioListener),
		CORE_TYPE_FUNC(AudioPlayer),
		CORE_TYPE_FUNC(AudioSource)
	};
	for (auto& t : types)
	{
		PyTypeObject* type = t.func();
		if (PyType_Ready(type) < 0)
			return NULL;
	}

	PyObject* module = PyModule_Create(&igpy_module);
	if (module == NULL)
		return NULL;

	for (auto& t : types)
	{
		PyTypeObject* type = t.func();
		Py_INCREF(type);
		PyModule_AddObject(module, t.name, (PyObject*)type);
	}

	auto typesIterBegin = types.begin();
	auto typesIterEnd = types.end();
	DCObjectInitDefaultClasses(types.size(), DKFunction([&typesIterBegin, &typesIterEnd]()->PyTypeObject*
	{
		PyTypeObject* tp = NULL;
		if (typesIterBegin != typesIterEnd)
		{
			tp = typesIterBegin->func();
			typesIterBegin++;
		}
		return tp;
	})->Invocation());

	PyEval_InitThreads();

	return module;
}
<|endoftext|>