<commit_before>#include <fstream>
#include <iostream>
#include <sstream>

#include "mcc/cfg/cfg.h"
#include "mcc/gas/gas.h"
#include "mcc/lvn/lvn.h"
#include "mcc/main.h"
#include "mcc/tac/tac.h"

using namespace mcc::tac;
using namespace mcc::cfg;
using namespace mcc::lvn;
using namespace mcc::gas;

int main(int argc, char **argv) {
  if (argc != 2) {
    std::cout << "usage: mC [file]" << std::endl;
    return -1;
  }

  std::ifstream input{argv[1]};
  std::stringstream buffer;
  buffer << input.rdbuf();
  auto source = buffer.str();
  auto tree = parser::parse(source);

  if (!tree) {
    std::cout << "File: " << argv[1] << " is not a valid mC file." << std::endl;
    return -1;
  }

  formatted_ostream out(std::cout);
  out << "Parsed:\n" << tree << "\n";

  Tac tac = Tac(tree);
  std::cout << "Three-Adress Code:" << std::endl;
  std::cout << tac.toString() << std::endl;

  LVN::transform(tac);
  std::cout << std::endl << "Three-Adress Code after LVN:" << std::endl;
  std::cout << tac.toString() << std::endl;

  auto graph = std::make_shared<Cfg>(tac);
  std::cout << std::endl << "BB:" << std::endl;

  auto bbIndex = tac.getBasicBlockIndex();

  graph->computeLiveInOut();
  graph->computeWorkList();
  for (auto const b : *bbIndex.get()) {
    std::cout << "LiveIn: { ";
    for (auto const in : graph->getLiveIn(b->getBlockId())) {
      std::cout << in->getName() << ", ";
    }
    std::cout << "}" << std::endl;

    std::cout << b->toString();

    std::cout << "LiveOut: { ";
    for (auto const out : graph->getLiveOut(b->getBlockId())) {
      std::cout << out->getName() << ", ";
    }
    std::cout << "}" << std::endl << std::endl;
  }

  // GNU Assembly
  std::cout << "GAS:" << std::endl;
  Gas gas = Gas(tac);

  auto map1 = gas.getFunctionStackSpaceMap();
  for (auto it = map1->begin(); it != map1->end(); ++it) {
    std::cout << it->first.get() << ": Stack Space = " << it->second
              << std::endl;
  }

  auto map2 = gas.getVariableStackOffsetMap();
  for (auto it = map2->begin(); it != map2->end(); ++it) {
    std::cout << it->first->getValue() << ": Stack Offset = " << it->second
              << std::endl;
  }

  auto outFileName = std::string(argv[1]) + ".s";
  std::ofstream output;

  std::cout << "Assembly:" << std::endl << gas.toString();

  output.open(outFileName);

  output << gas;

  output.flush();
  output.close();
}
<commit_msg>add compiler call to main<commit_after>#include <fstream>
#include <iostream>
#include <sstream>

#include "mcc/cfg/cfg.h"
#include "mcc/gas/gas.h"
#include "mcc/lvn/lvn.h"
#include "mcc/main.h"
#include "mcc/tac/tac.h"

using namespace mcc::tac;
using namespace mcc::cfg;
using namespace mcc::lvn;
using namespace mcc::gas;

int main(int argc, char **argv) {
  if (argc != 2) {
    std::cout << "usage: mC [file]" << std::endl;
    return -1;
  }

  std::ifstream input{argv[1]};
  std::stringstream buffer;
  buffer << input.rdbuf();
  auto source = buffer.str();
  auto tree = parser::parse(source);

  if (!tree) {
    std::cout << "File: " << argv[1] << " is not a valid mC file." << std::endl;
    return -1;
  }

  formatted_ostream out(std::cout);
  out << "Parsed:\n" << tree << "\n";

  Tac tac = Tac(tree);
  std::cout << "Three-Adress Code:" << std::endl;
  std::cout << tac.toString() << std::endl;

  LVN::transform(tac);
  std::cout << std::endl << "Three-Adress Code after LVN:" << std::endl;
  std::cout << tac.toString() << std::endl;

  auto graph = std::make_shared<Cfg>(tac);
  std::cout << std::endl << "BB:" << std::endl;

  auto bbIndex = tac.getBasicBlockIndex();

  graph->computeLiveInOut();
  graph->computeWorkList();
  for (auto const b : *bbIndex.get()) {
    std::cout << "LiveIn: { ";
    for (auto const in : graph->getLiveIn(b->getBlockId())) {
      std::cout << in->getName() << ", ";
    }
    std::cout << "}" << std::endl;

    std::cout << b->toString();

    std::cout << "LiveOut: { ";
    for (auto const out : graph->getLiveOut(b->getBlockId())) {
      std::cout << out->getName() << ", ";
    }
    std::cout << "}" << std::endl << std::endl;
  }

  // GNU Assembly
  std::cout << "GAS:" << std::endl;
  Gas gas = Gas(tac);

  auto map1 = gas.getFunctionStackSpaceMap();
  for (auto it = map1->begin(); it != map1->end(); ++it) {
    std::cout << it->first.get() << ": Stack Space = " << it->second
              << std::endl;
  }

  auto map2 = gas.getVariableStackOffsetMap();
  for (auto it = map2->begin(); it != map2->end(); ++it) {
    std::cout << it->first->getValue() << ": Stack Offset = " << it->second
              << std::endl;
  }

  auto outFileName = std::string(argv[1]) + ".s";
  std::ofstream output;

  std::cout << "Assembly:" << std::endl << gas.toString();

  output.open(outFileName);

  output << gas;

  output.flush();
  output.close();

  auto libFileName = std::string(argv[0]);

  // remove mcc at end to get path to mcc file
  libFileName = libFileName.substr(0, libFileName.size() - 3);

  // relative location of lib.c to mcc executable
  libFileName.append("../lib.c");

  std::string gccCall = "gcc ";
  gccCall.append(outFileName);
  gccCall.append(" ");
  gccCall.append(libFileName);
  gccCall.append(" -m32");

  std::system(gccCall.c_str());
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Kernels for colum-major matrix - row-major matrix multiplication and
 * assignment to a column-major matrix
 */

#pragma once

namespace etl {

namespace impl {

namespace vec {

/*!
 * \brief Optimized version of GEMM for assignment of a small
 * Column-Major Matrix - Row Major Matrix to a Column Major Matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 */
template <typename V, typename T>
void gemm_small_kernel_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    using vec_type = V;

    static constexpr size_t vec_size = vec_type::template traits<T>::size;

    const auto i_end = M & (size_t(-vec_size));

    size_t i = 0;

    for( ; i + 3 * vec_size < i_end; i += 4 * vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();
            auto r31 = vec_type::template zero<T>();
            auto r41 = vec_type::template zero<T>();

            auto r12 = vec_type::template zero<T>();
            auto r22 = vec_type::template zero<T>();
            auto r32 = vec_type::template zero<T>();
            auto r42 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);
                auto a3 = vec_type::loadu(a + i + k * M + 2 * vec_size);
                auto a4 = vec_type::loadu(a + i + k * M + 3 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
                r31 = vec_type::fmadd(a3, b1, r31);
                r41 = vec_type::fmadd(a4, b1, r41);

                r12 = vec_type::fmadd(a1, b2, r12);
                r22 = vec_type::fmadd(a2, b2, r22);
                r32 = vec_type::fmadd(a3, b2, r32);
                r42 = vec_type::fmadd(a4, b2, r42);
            }

            vec_type::storeu(c + i + (j + 0) * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + (j + 0) * M + 1 * vec_size, r21);
            vec_type::storeu(c + i + (j + 0) * M + 2 * vec_size, r31);
            vec_type::storeu(c + i + (j + 0) * M + 3 * vec_size, r41);

            vec_type::storeu(c + i + (j + 1) * M + 0 * vec_size, r12);
            vec_type::storeu(c + i + (j + 1) * M + 1 * vec_size, r22);
            vec_type::storeu(c + i + (j + 1) * M + 2 * vec_size, r32);
            vec_type::storeu(c + i + (j + 1) * M + 3 * vec_size, r42);
        }

        for (; j < N; ++j) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();
            auto r31 = vec_type::template zero<T>();
            auto r41 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);
                auto a3 = vec_type::loadu(a + i + k * M + 2 * vec_size);
                auto a4 = vec_type::loadu(a + i + k * M + 3 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
                r31 = vec_type::fmadd(a3, b1, r31);
                r41 = vec_type::fmadd(a4, b1, r41);
            }

            vec_type::storeu(c + i + j * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + j * M + 1 * vec_size, r21);
            vec_type::storeu(c + i + j * M + 2 * vec_size, r31);
            vec_type::storeu(c + i + j * M + 3 * vec_size, r41);
        }
    }

    for( ; i + 1 * vec_size < i_end; i += 2 * vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();

            auto r12 = vec_type::template zero<T>();
            auto r22 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);

                r12 = vec_type::fmadd(a1, b2, r12);
                r22 = vec_type::fmadd(a2, b2, r22);
            }

            vec_type::storeu(c + i + (j + 0) * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + (j + 0) * M + 1 * vec_size, r21);

            vec_type::storeu(c + i + (j + 1) * M + 0 * vec_size, r12);
            vec_type::storeu(c + i + (j + 1) * M + 1 * vec_size, r22);
        }

        for (; j < N; ++j) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
            }

            vec_type::storeu(c + i + j * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + j * M + 1 * vec_size, r21);
        }
    }

    for( ; i < i_end; i += vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r12 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r12 = vec_type::fmadd(a1, b2, r12);
            }

            vec_type::storeu(c + i + (j + 0) * M, r11);
            vec_type::storeu(c + i + (j + 1) * M, r12);
        }

        for (; j < N; ++j) {
            auto r11 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
            }

            vec_type::storeu(c + i + j * M, r11);
        }
    }

    for( ; i < M; ++i){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = T();
            auto r12 = T();

            for (size_t k = 0; k < K; ++k) {
                r11 += a[i + k * M] * b[k * N + (j + 0)];
                r12 += a[i + k * M] * b[k * N + (j + 1)];
            }

            c[i + (j + 0) * M] = r11;
            c[i + (j + 1) * M] = r12;
        }

        for (; j < N; ++j) {
            auto r11 = T();

            for (size_t k = 0; k < K; ++k) {
                r11 += a[i + k * M] * b[k * N + j];
            }

            c[i + j * M] = r11;
        }
    }
}

/*!
 * \brief Optimized version of GEMM for assignment of a large
 * Column-Major Matrix - Row Major Matrix to a Column Major Matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 */
template <typename V, typename T>
void gemm_large_kernel_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    cpp_unused(a);
    cpp_unused(b);
    cpp_unused(c);
    cpp_unused(M);
    cpp_unused(N);
    cpp_unused(K);
}

/*!
 * \brief Vectorized implementation of column-major matrix - row-major matrix
 * multiplication and assignment into a column-major matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 *
 * \param M The number of rows of the matrix A and rows of the matrix C
 * \param N The number of columns of the matrix B and columns of the matrix C
 * \param K The number of columns of the matrix A and rows of the matrix B
 */
template <typename T>
void gemm_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    cpp_assert(vec_enabled, "At least one vector mode must be enabled for impl::VEC");

    if (M * N <= gemm_rr_small_threshold) {
        gemm_small_kernel_cr_to_c<default_vec>(a, b, c, M, N, K);
    } else {
        direct_fill_n(c, M * N, T(0));
        gemm_large_kernel_cr_to_c<default_vec>(a, b, c, M, N, K);
    }
}

} //end of namespace vec
} //end of namespace impl
} //end of namespace etl
<commit_msg>Slight optimization<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Kernels for colum-major matrix - row-major matrix multiplication and
 * assignment to a column-major matrix
 */

#pragma once

namespace etl {

namespace impl {

namespace vec {

/*!
 * \brief Optimized version of GEMM for assignment of a small
 * Column-Major Matrix - Row Major Matrix to a Column Major Matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 */
template <typename V, typename T>
void gemm_small_kernel_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    using vec_type = V;

    static constexpr size_t vec_size = vec_type::template traits<T>::size;

    const auto i_end = M & (size_t(-vec_size));

    size_t i = 0;

    for( ; i + 3 * vec_size < i_end; i += 4 * vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();
            auto r31 = vec_type::template zero<T>();
            auto r41 = vec_type::template zero<T>();

            auto r12 = vec_type::template zero<T>();
            auto r22 = vec_type::template zero<T>();
            auto r32 = vec_type::template zero<T>();
            auto r42 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);
                auto a3 = vec_type::loadu(a + i + k * M + 2 * vec_size);
                auto a4 = vec_type::loadu(a + i + k * M + 3 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
                r31 = vec_type::fmadd(a3, b1, r31);
                r41 = vec_type::fmadd(a4, b1, r41);

                r12 = vec_type::fmadd(a1, b2, r12);
                r22 = vec_type::fmadd(a2, b2, r22);
                r32 = vec_type::fmadd(a3, b2, r32);
                r42 = vec_type::fmadd(a4, b2, r42);
            }

            vec_type::storeu(c + i + (j + 0) * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + (j + 0) * M + 1 * vec_size, r21);
            vec_type::storeu(c + i + (j + 0) * M + 2 * vec_size, r31);
            vec_type::storeu(c + i + (j + 0) * M + 3 * vec_size, r41);

            vec_type::storeu(c + i + (j + 1) * M + 0 * vec_size, r12);
            vec_type::storeu(c + i + (j + 1) * M + 1 * vec_size, r22);
            vec_type::storeu(c + i + (j + 1) * M + 2 * vec_size, r32);
            vec_type::storeu(c + i + (j + 1) * M + 3 * vec_size, r42);
        }

        if (j < N) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();
            auto r31 = vec_type::template zero<T>();
            auto r41 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);
                auto a3 = vec_type::loadu(a + i + k * M + 2 * vec_size);
                auto a4 = vec_type::loadu(a + i + k * M + 3 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
                r31 = vec_type::fmadd(a3, b1, r31);
                r41 = vec_type::fmadd(a4, b1, r41);
            }

            vec_type::storeu(c + i + j * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + j * M + 1 * vec_size, r21);
            vec_type::storeu(c + i + j * M + 2 * vec_size, r31);
            vec_type::storeu(c + i + j * M + 3 * vec_size, r41);
        }
    }

    for( ; i + 1 * vec_size < i_end; i += 2 * vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();

            auto r12 = vec_type::template zero<T>();
            auto r22 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);

                r12 = vec_type::fmadd(a1, b2, r12);
                r22 = vec_type::fmadd(a2, b2, r22);
            }

            vec_type::storeu(c + i + (j + 0) * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + (j + 0) * M + 1 * vec_size, r21);

            vec_type::storeu(c + i + (j + 1) * M + 0 * vec_size, r12);
            vec_type::storeu(c + i + (j + 1) * M + 1 * vec_size, r22);
        }

        if (j < N) {
            auto r11 = vec_type::template zero<T>();
            auto r21 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);
                auto a2 = vec_type::loadu(a + i + k * M + 1 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r21 = vec_type::fmadd(a2, b1, r21);
            }

            vec_type::storeu(c + i + j * M + 0 * vec_size, r11);
            vec_type::storeu(c + i + j * M + 1 * vec_size, r21);
        }
    }

    for( ; i < i_end; i += vec_size){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = vec_type::template zero<T>();
            auto r12 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);

                auto b1 = vec_type::set(b[k * N + (j + 0)]);
                auto b2 = vec_type::set(b[k * N + (j + 1)]);

                r11 = vec_type::fmadd(a1, b1, r11);
                r12 = vec_type::fmadd(a1, b2, r12);
            }

            vec_type::storeu(c + i + (j + 0) * M, r11);
            vec_type::storeu(c + i + (j + 1) * M, r12);
        }

        if (j < N) {
            auto r11 = vec_type::template zero<T>();

            for (size_t k = 0; k < K; ++k) {
                auto a1 = vec_type::loadu(a + i + k * M + 0 * vec_size);

                auto b1 = vec_type::set(b[k * N + j]);

                r11 = vec_type::fmadd(a1, b1, r11);
            }

            vec_type::storeu(c + i + j * M, r11);
        }
    }

    for( ; i < M; ++i){
        size_t j = 0;

        for (; j + 1 < N; j += 2) {
            auto r11 = T();
            auto r12 = T();

            for (size_t k = 0; k < K; ++k) {
                r11 += a[i + k * M] * b[k * N + (j + 0)];
                r12 += a[i + k * M] * b[k * N + (j + 1)];
            }

            c[i + (j + 0) * M] = r11;
            c[i + (j + 1) * M] = r12;
        }

        if (j < N) {
            auto r11 = T();

            for (size_t k = 0; k < K; ++k) {
                r11 += a[i + k * M] * b[k * N + j];
            }

            c[i + j * M] = r11;
        }
    }
}

/*!
 * \brief Optimized version of GEMM for assignment of a large
 * Column-Major Matrix - Row Major Matrix to a Column Major Matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 */
template <typename V, typename T>
void gemm_large_kernel_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    cpp_unused(a);
    cpp_unused(b);
    cpp_unused(c);
    cpp_unused(M);
    cpp_unused(N);
    cpp_unused(K);
}

/*!
 * \brief Vectorized implementation of column-major matrix - row-major matrix
 * multiplication and assignment into a column-major matrix.
 *
 * \param a The lhs matrix
 * \param b The rhs matrix
 * \param c The result matrix
 *
 * \param M The number of rows of the matrix A and rows of the matrix C
 * \param N The number of columns of the matrix B and columns of the matrix C
 * \param K The number of columns of the matrix A and rows of the matrix B
 */
template <typename T>
void gemm_cr_to_c(const T* a, const T* b, T* c, size_t M, size_t N, size_t K) {
    cpp_assert(vec_enabled, "At least one vector mode must be enabled for impl::VEC");

    if (M * N <= gemm_rr_small_threshold) {
        gemm_small_kernel_cr_to_c<default_vec>(a, b, c, M, N, K);
    } else {
        direct_fill_n(c, M * N, T(0));
        gemm_large_kernel_cr_to_c<default_vec>(a, b, c, M, N, K);
    }
}

} //end of namespace vec
} //end of namespace impl
} //end of namespace etl
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
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 author 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED

#include <boost/function.hpp>
#include <asio.hpp>
#include <list>
#include <cstring>

namespace libtorrent
{
	struct chained_buffer
	{
		chained_buffer(): m_bytes(0), m_capacity(0) {}

		struct buffer_t
		{
			boost::function<void(char*)> free; // destructs the buffer
			char* buf; // the first byte of the buffer
			int size; // the total size of the buffer

			char* start; // the first byte to send/receive in the buffer
			int used_size; // this is the number of bytes to send/receive
		};

		bool empty() const { return m_bytes == 0; }
		int size() const { return m_bytes; }
		int capacity() const { return m_capacity; }

		void pop_front(int bytes_to_pop)
		{
			assert(bytes_to_pop <= m_bytes);
			while (bytes_to_pop > 0 && !m_vec.empty())
			{
				buffer_t& b = m_vec.front();
				if (b.used_size > bytes_to_pop)
				{
					b.start += bytes_to_pop;
					b.used_size -= bytes_to_pop;
					m_bytes -= bytes_to_pop;
					assert(m_bytes <= m_capacity);
					assert(m_bytes >= 0);
					assert(m_capacity >= 0);
					break;
				}

				b.free(b.buf);
				m_bytes -= b.used_size;
				m_capacity -= b.size;
				bytes_to_pop -= b.used_size;
				assert(m_bytes >= 0);
				assert(m_capacity >= 0);
				assert(m_bytes <= m_capacity);
				m_vec.pop_front();
			}
		}

		template <class D>
		void append_buffer(char* buffer, int size, int used_size, D const& destructor)
		{
			assert(size >= used_size);
			buffer_t b;
			b.buf = buffer;
			b.size = size;
			b.start = buffer;
			b.used_size = used_size;
			b.free = destructor;
			m_vec.push_back(b);

			m_bytes += used_size;
			m_capacity += size;
			assert(m_bytes <= m_capacity);
		}

		// returns the number of bytes available at the
		// end of the last chained buffer.
		int space_in_last_buffer()
		{
			if (m_vec.empty()) return 0;
			buffer_t& b = m_vec.back();
			return b.size - b.used_size - (b.start - b.buf);
		}

		// tries to copy the given buffer to the end of the
		// last chained buffer. If there's not enough room
		// it returns false
		bool append(char const* buf, int size)
		{
			char* insert = allocate_appendix(size);
			if (insert == 0) return false;
			std::memcpy(insert, buf, size);
			return true;
		}

		// tries to allocate memory from the end
		// of the last buffer. If there isn't
		// enough room, returns 0
		char* allocate_appendix(int size)
		{
			if (m_vec.empty()) return 0;
			buffer_t& b = m_vec.back();
			char* insert = b.start + b.used_size;
			if (insert + size > b.buf + b.size) return 0;
			b.used_size += size;
			m_bytes += size;
			assert(m_bytes <= m_capacity);
			return insert;
		}

		std::list<asio::const_buffer> const& build_iovec(int to_send)
		{
			m_tmp_vec.clear();

			for (std::list<buffer_t>::iterator i = m_vec.begin()
				, end(m_vec.end()); to_send > 0 && i != end; ++i)
			{
				if (i->used_size > to_send)
				{
					assert(to_send > 0);
					m_tmp_vec.push_back(asio::const_buffer(i->start, to_send));
					break;
				}
				assert(i->used_size > 0);
				m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size));
				to_send -= i->used_size;
			}
			return m_tmp_vec;
		}

		~chained_buffer()
		{
			for (std::list<buffer_t>::iterator i = m_vec.begin()
				, end(m_vec.end()); i != end; ++i)
			{
				i->free(i->buf);
			}
		}

	private:

		// this is the list of all the buffers we want to
		// send
		std::list<buffer_t> m_vec;

		// this is the number of bytes in the send buf.
		// this will always be equal to the sum of the
		// size of all buffers in vec
		int m_bytes;

		// the total size of all buffers in the chain
		// including unused space
		int m_capacity;

		// this is the vector of buffers used when
		// invoking the async write call
		std::list<asio::const_buffer> m_tmp_vec;
	};
}

#endif

<commit_msg>fixed asio include header<commit_after>/*

Copyright (c) 2007, Arvid Norberg
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 author 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED

#include <boost/function.hpp>
#include <asio/buffer.hpp>
#include <list>
#include <cstring>

namespace libtorrent
{
	struct chained_buffer
	{
		chained_buffer(): m_bytes(0), m_capacity(0) {}

		struct buffer_t
		{
			boost::function<void(char*)> free; // destructs the buffer
			char* buf; // the first byte of the buffer
			int size; // the total size of the buffer

			char* start; // the first byte to send/receive in the buffer
			int used_size; // this is the number of bytes to send/receive
		};

		bool empty() const { return m_bytes == 0; }
		int size() const { return m_bytes; }
		int capacity() const { return m_capacity; }

		void pop_front(int bytes_to_pop)
		{
			assert(bytes_to_pop <= m_bytes);
			while (bytes_to_pop > 0 && !m_vec.empty())
			{
				buffer_t& b = m_vec.front();
				if (b.used_size > bytes_to_pop)
				{
					b.start += bytes_to_pop;
					b.used_size -= bytes_to_pop;
					m_bytes -= bytes_to_pop;
					assert(m_bytes <= m_capacity);
					assert(m_bytes >= 0);
					assert(m_capacity >= 0);
					break;
				}

				b.free(b.buf);
				m_bytes -= b.used_size;
				m_capacity -= b.size;
				bytes_to_pop -= b.used_size;
				assert(m_bytes >= 0);
				assert(m_capacity >= 0);
				assert(m_bytes <= m_capacity);
				m_vec.pop_front();
			}
		}

		template <class D>
		void append_buffer(char* buffer, int size, int used_size, D const& destructor)
		{
			assert(size >= used_size);
			buffer_t b;
			b.buf = buffer;
			b.size = size;
			b.start = buffer;
			b.used_size = used_size;
			b.free = destructor;
			m_vec.push_back(b);

			m_bytes += used_size;
			m_capacity += size;
			assert(m_bytes <= m_capacity);
		}

		// returns the number of bytes available at the
		// end of the last chained buffer.
		int space_in_last_buffer()
		{
			if (m_vec.empty()) return 0;
			buffer_t& b = m_vec.back();
			return b.size - b.used_size - (b.start - b.buf);
		}

		// tries to copy the given buffer to the end of the
		// last chained buffer. If there's not enough room
		// it returns false
		bool append(char const* buf, int size)
		{
			char* insert = allocate_appendix(size);
			if (insert == 0) return false;
			std::memcpy(insert, buf, size);
			return true;
		}

		// tries to allocate memory from the end
		// of the last buffer. If there isn't
		// enough room, returns 0
		char* allocate_appendix(int size)
		{
			if (m_vec.empty()) return 0;
			buffer_t& b = m_vec.back();
			char* insert = b.start + b.used_size;
			if (insert + size > b.buf + b.size) return 0;
			b.used_size += size;
			m_bytes += size;
			assert(m_bytes <= m_capacity);
			return insert;
		}

		std::list<asio::const_buffer> const& build_iovec(int to_send)
		{
			m_tmp_vec.clear();

			for (std::list<buffer_t>::iterator i = m_vec.begin()
				, end(m_vec.end()); to_send > 0 && i != end; ++i)
			{
				if (i->used_size > to_send)
				{
					assert(to_send > 0);
					m_tmp_vec.push_back(asio::const_buffer(i->start, to_send));
					break;
				}
				assert(i->used_size > 0);
				m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size));
				to_send -= i->used_size;
			}
			return m_tmp_vec;
		}

		~chained_buffer()
		{
			for (std::list<buffer_t>::iterator i = m_vec.begin()
				, end(m_vec.end()); i != end; ++i)
			{
				i->free(i->buf);
			}
		}

	private:

		// this is the list of all the buffers we want to
		// send
		std::list<buffer_t> m_vec;

		// this is the number of bytes in the send buf.
		// this will always be equal to the sum of the
		// size of all buffers in vec
		int m_bytes;

		// the total size of all buffers in the chain
		// including unused space
		int m_capacity;

		// this is the vector of buffers used when
		// invoking the async write call
		std::list<asio::const_buffer> m_tmp_vec;
	};
}

#endif

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_TOLERANCE_ITERATOR_HPP
#define MAPNIK_TOLERANCE_ITERATOR_HPP

//mapnik
#include <mapnik/debug.hpp>

namespace mapnik
{

struct exponential_function
{
    double operator()(double const& linear_position, double const& tolerance) const
    {
        return std::pow(1.3, linear_position) * linear_position /
            (4.0 * tolerance) + linear_position;
    }
};

template <typename Function>
class tolerance_iterator
{
public:
    tolerance_iterator(double label_position_tolerance, Function function)
        : tolerance_(label_position_tolerance),
          linear_position_(1.0),
          value_(0),
          initialized_(false),
          values_tried_(0),
          function_(function)
    {
    }

    tolerance_iterator(double label_position_tolerance)
        : tolerance_iterator(label_position_tolerance, Function())
    {
    }

    ~tolerance_iterator()
    {
        //std::cout << "values tried:" << values_tried_ << "\n";
    }

    double get() const
    {
        return -value_;
    }

    bool next()
    {
        ++values_tried_;
        if (values_tried_ > 255)
        {
            /* This point should not be reached during normal operation. But I can think of
             * cases where very bad spacing and or tolerance values are choosen and the
             * placement finder tries an excessive number of placements.
             * 255 is an arbitrarily chosen limit.
             */
            MAPNIK_LOG_WARN(placement_finder) << "Tried a huge number of placements. Please check "
                                                 "'label-position-tolerance' and 'spacing' parameters "
                                                 "of your TextSymbolizers.\n";
            return false;
        }
        if (!initialized_)
        {
            initialized_ = true;
            return true; //Always return value 0 as the first value.
        }
        if (value_ == 0)
        {
            value_ = function_(linear_position_, tolerance_);
            return value_ <= tolerance_;
        }
        value_ = -value_;
        if (value_ > 0)
        {
            linear_position_ += 1.0;
            value_ = function_(linear_position_, tolerance_);
        }
        if (value_ > tolerance_)
        {
            return false;
        }
        return true;
    }

    void reset()
    {
        linear_position_ = 1.0;
        value_ = .0;
        initialized_ = false;
        values_tried_ = 0;
    }

private:
    const double tolerance_;
    double linear_position_;
    double value_;
    bool initialized_;
    unsigned values_tried_;
    Function function_;
};

}//ns mapnik

#endif // MAPNIK_TOLERANCE_ITERATOR_HPP
<commit_msg>Tolerance iterator works on all symbolizers with 'placement' option<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_TOLERANCE_ITERATOR_HPP
#define MAPNIK_TOLERANCE_ITERATOR_HPP

//mapnik
#include <mapnik/debug.hpp>

namespace mapnik
{

struct exponential_function
{
    double operator()(double const& linear_position, double const& tolerance) const
    {
        return std::pow(1.3, linear_position) * linear_position /
            (4.0 * tolerance) + linear_position;
    }
};

template <typename Function>
class tolerance_iterator
{
public:
    tolerance_iterator(double label_position_tolerance, Function function)
        : tolerance_(label_position_tolerance),
          linear_position_(1.0),
          value_(0),
          initialized_(false),
          values_tried_(0),
          function_(function)
    {
    }

    tolerance_iterator(double label_position_tolerance)
        : tolerance_iterator(label_position_tolerance, Function())
    {
    }

    ~tolerance_iterator()
    {
        //std::cout << "values tried:" << values_tried_ << "\n";
    }

    double get() const
    {
        return -value_;
    }

    bool next()
    {
        ++values_tried_;
        if (values_tried_ > 255)
        {
            /* This point should not be reached during normal operation. But I can think of
             * cases where very bad spacing and or tolerance values are choosen and the
             * placement finder tries an excessive number of placements.
             * 255 is an arbitrarily chosen limit.
             */
            MAPNIK_LOG_WARN(placement_finder) << "Tried a huge number of placements. Please check "
                                                 "'position-tolerance' and 'spacing' parameters "
                                                 "of your symbolizer.\n";
            return false;
        }
        if (!initialized_)
        {
            initialized_ = true;
            return true; //Always return value 0 as the first value.
        }
        if (value_ == 0)
        {
            value_ = function_(linear_position_, tolerance_);
            return value_ <= tolerance_;
        }
        value_ = -value_;
        if (value_ > 0)
        {
            linear_position_ += 1.0;
            value_ = function_(linear_position_, tolerance_);
        }
        if (value_ > tolerance_)
        {
            return false;
        }
        return true;
    }

    void reset()
    {
        linear_position_ = 1.0;
        value_ = .0;
        initialized_ = false;
        values_tried_ = 0;
    }

private:
    const double tolerance_;
    double linear_position_;
    double value_;
    bool initialized_;
    unsigned values_tried_;
    Function function_;
};

}//ns mapnik

#endif // MAPNIK_TOLERANCE_ITERATOR_HPP
<|endoftext|>


<commit_before>#include <sys/socket.h>

#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <iostream>
#include <string>
#include <string.h>

using namespace std;

#define BUFF_SIZE 32
#define MESSAGE_END "\n\n"

#include "Socket.h"

Socket::Socket() {
    fd_ = 0;
    buffer = new char[BUFF_SIZE];
}

Socket::Socket(const int fd) {
    buffer = new char[BUFF_SIZE];
    setFd(fd);
}

Socket::~Socket() {
    if(fd_ != 0)
        close(fd_);
}

int Socket::write(string message) {
    const char * msg;
    int len, bytes_sent;

    message += "\n\n";
    msg = message.c_str();
    len = strlen(msg);
    bytes_sent = 0;

    while(len > 0){
        bytes_sent = send(fd_, msg, len, 0);
        if(bytes_sent == -1)
            return -1; // socket error, could not write
        len -= bytes_sent;
        msg = msg + bytes_sent;
    }

    return 0;
}

string Socket::popFromBuffer() {
    string partial;
    size_t nextStop;

    partial = buffer;
    nextStop = partial.find(MESSAGE_END);
    if (nextStop == string::npos) {
        buffer[0] = '\0';
    }
    else {
        buffer = buffer + nextStop + 2;
        partial = partial.substr(0, nextStop + 2);
    }

    return partial;
}

int Socket::read(string & message) {
    bool isComplete;
    int len;

    message = popFromBuffer();
    isComplete = (message.find(MESSAGE_END) != string::npos);

    while(!isComplete){
        len = recv(fd_, buffer, BUFF_SIZE - 1, 0);
        if (len == -1)
            return -1; // socket error, could not read
        else if(len == 0)
            return 0; // connection closed from other side

        buffer[len] = '\0'; // prevent buffer overflow
        message += popFromBuffer();
        isComplete = (message.find(MESSAGE_END) != string::npos);
    }

    message = message.substr(0, message.length() - 2); // remove MESSAGE_END
    return 1;
}

int Socket::getFd() const {
    return fd_;
}

void Socket::setFd(const int fd) {
    fd_ = fd;
}
<commit_msg>[code/socket] Fix some memory magic<commit_after>#include <sys/socket.h>

#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <iostream>
#include <string>
#include <string.h>

using namespace std;

#define BUFF_SIZE 32
#define MESSAGE_END "\n\n"

#include "Socket.h"

Socket::Socket() {
    fd_ = 0;
    buffer = new char[BUFF_SIZE];
}

Socket::Socket(const int fd) {
    buffer = new char[BUFF_SIZE];
    setFd(fd);
}

Socket::~Socket() {
    if(fd_ != 0)
        close(fd_);
}

int Socket::write(string message) {
    const char * msg;
    int len, bytes_sent;

    message += "\n\n";
    msg = message.c_str();
    len = strlen(msg);
    bytes_sent = 0;

    while(len > 0){
        bytes_sent = send(fd_, msg, len, 0);
        if(bytes_sent == -1)
            return -1; // socket error, could not write
        len -= bytes_sent;
        msg = msg + bytes_sent;
    }

    return 0;
}

string Socket::popFromBuffer() {
    string partial;
    size_t nextStop;
    partial = buffer;
    nextStop = partial.find(MESSAGE_END);
    if (nextStop == string::npos) {
        buffer[0] = '\0';
    }
    else {
        strcpy(buffer, buffer + nextStop + 2);
        partial = partial.substr(0, nextStop + 2);
    }
    return partial;
}

int Socket::read(string & message) {
    bool isComplete;
    int len;
    message = popFromBuffer();
    isComplete = (message.find(MESSAGE_END) != string::npos);

    while(!isComplete){
        len = recv(fd_, buffer, BUFF_SIZE - 1, 0);
        if (len == -1)
            return -1; // socket error, could not read
        else if(len == 0)
            return 0; // connection closed from other side

        buffer[len] = '\0'; // prevent buffer overflow
        message += popFromBuffer();
        isComplete = (message.find(MESSAGE_END) != string::npos);
    }

    message = message.substr(0, message.length() - 2); // remove MESSAGE_END
    return 1;
}

int Socket::getFd() const {
    return fd_;
}

void Socket::setFd(const int fd) {
    fd_ = fd;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_DEBUG_INFO_HPP
#define RJ_GAME_DEBUG_INFO_HPP

#include <rectojump/core/render.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/shared/debug_text.hpp>

#include <mlk/tools/compiletime.h>
#include <mlk/tools/stl_string_utl.h>

namespace rj
{
	struct debug_info_string_base
	{
		virtual ~debug_info_string_base() = default;
		virtual std::string get_formated() const = 0;
	};

	template<typename Func_Ret_Type>
	class debug_info_string : public debug_info_string_base
	{
		const std::string m_unformated_str;
		std::function<Func_Ret_Type()> m_func;

	public:
		template<typename Func>
		debug_info_string(const std::string& unformated_str, Func&& f) :
			m_unformated_str{unformated_str},
			m_func{f}
		{ }

		~debug_info_string() = default;

		std::string get_formated() const override
		{
			auto result(m_unformated_str);
            std::string str;
            if constexpr(std::is_same<std::string, Func_Ret_Type>())
                    str = m_func();
            else str = std::to_string(m_func());
//			auto str(std::to_string(m_func()));
			auto insert_pos(result.find("%%"));
			if(insert_pos != std::string::npos)
			{
				result.insert(insert_pos + 2, str);
				result.erase(insert_pos, 2);
			}
			return result;
		}
	};

	template<>
	inline std::string debug_info_string<void>::get_formated() const
	{return m_unformated_str;}

	// debug_info
	template<typename Game_Handler, typename Game>
	class debug_info
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		Game& m_game;

		sf::RectangleShape m_background{{100.f, 100.f}};
		debug_text m_text;
		std::vector<mlk::sptr<debug_info_string_base>> m_lines;

	public:
		debug_info(Game_Handler& gh) :
			m_gamehandler{gh},
			m_render{gh.rendermgr()},
            m_game{gh.get_game()},
			m_text{gh.datamgr()}
		{this->init();}

		void update(dur)
		{
			m_background.setSize(m_text.get_size());
			std::string display_text;
			for(auto& a : m_lines)
				display_text += a->get_formated();
			m_text.set_text(display_text);
		}

		void render()
		{m_render(m_background, m_text);}

	private:
		void init() noexcept
		{
			m_background.setPosition({1.f, 1.f});
			m_background.setFillColor({255, 150, 123, 220});
			m_background.setOutlineThickness(1);
			m_background.setOutlineColor({255, 0, 0});

			this->add_title_line("Performance");
            this->add_line("FPS:             %%", [this]{return m_gamehandler.gamewindow().get_updater().get_fps();});
            this->add_line("FDur:            %%\n", [this]{return m_gamehandler.gamewindow().get_updater().get_frameduration();});

			this->add_title_line("Components");
            this->add_line("Gameworld:       %%", [this]{return m_game.get_world().num_entities();});
            this->add_line("Background:      %%", [this]{return m_gamehandler.backgroundmgr().num_components_current_state();});
            this->add_line("Popups:          %%\n", [this]{return m_gamehandler.popupmgr().num_popups();});

			this->add_title_line("Managers");
            this->add_line("Data:            %%", [this]{return m_gamehandler.datamgr().num_data();});
            this->add_line("Levels:          %%\n", [this]{return m_gamehandler.levelmgr().num_levels();});

            this->add_title_line("States");
            this->add_line("Active (render): %%",
                           [this]{return std::string{state_as_string[(int)m_gamehandler.current_renderable_state()]};});
            this->add_line("Active (all):    %%",
            [this]
            {
                std::string active_states;
                for(std::size_t i{0}; i < (std::size_t)state::num; ++i)
                {
                    if(m_gamehandler.states() & (rj::state)i)
                        active_states += std::string{state_as_string[i]} + " ";
                }
                return active_states;
            });
        }

		void add_title_line(const std::string& text)
		{
			std::string app{'\n'};
			for(auto& a : text)
				app += "=";
			auto ptr(std::make_shared<debug_info_string<void>>(std::string{text + app + "\n"}, []{}));
			m_lines.emplace_back(ptr);
		}

		template<typename Func>
		void add_line(const std::string& text, Func&& f)
		{
			auto ptr(std::make_shared<debug_info_string<typename mlk::lambda_info<Func>::return_type>>(text + '\n', f));
			m_lines.emplace_back(ptr);
		}
	};
}

#endif // RJ_GAME_DEBUG_INFO_HPP
<commit_msg>clean<commit_after>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_DEBUG_INFO_HPP
#define RJ_GAME_DEBUG_INFO_HPP

#include <rectojump/core/render.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/shared/debug_text.hpp>

#include <mlk/tools/compiletime.h>
#include <mlk/tools/stl_string_utl.h>

namespace rj
{
	struct debug_info_string_base
	{
		virtual ~debug_info_string_base() = default;
		virtual std::string get_formated() const = 0;
	};

	template<typename Func_Ret_Type>
	class debug_info_string : public debug_info_string_base
	{
		const std::string m_unformated_str;
		std::function<Func_Ret_Type()> m_func;

	public:
		template<typename Func>
		debug_info_string(const std::string& unformated_str, Func&& f) :
			m_unformated_str{unformated_str},
			m_func{f}
		{ }

		~debug_info_string() = default;

		std::string get_formated() const override
		{
			auto result(m_unformated_str);
            std::string str;
            if constexpr(std::is_same<std::string, Func_Ret_Type>())
                    str = m_func();
            else str = std::to_string(m_func());
			auto insert_pos(result.find("%%"));
			if(insert_pos != std::string::npos)
			{
				result.insert(insert_pos + 2, str);
				result.erase(insert_pos, 2);
			}
			return result;
		}
	};

	template<>
	inline std::string debug_info_string<void>::get_formated() const
	{return m_unformated_str;}

	// debug_info
	template<typename Game_Handler, typename Game>
	class debug_info
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		Game& m_game;

		sf::RectangleShape m_background{{100.f, 100.f}};
		debug_text m_text;
		std::vector<mlk::sptr<debug_info_string_base>> m_lines;

	public:
		debug_info(Game_Handler& gh) :
			m_gamehandler{gh},
			m_render{gh.rendermgr()},
            m_game{gh.get_game()},
			m_text{gh.datamgr()}
		{this->init();}

		void update(dur)
		{
			m_background.setSize(m_text.get_size());
			std::string display_text;
			for(auto& a : m_lines)
				display_text += a->get_formated();
			m_text.set_text(display_text);
		}

		void render()
		{m_render(m_background, m_text);}

	private:
		void init() noexcept
		{
			m_background.setPosition({1.f, 1.f});
			m_background.setFillColor({255, 150, 123, 220});
			m_background.setOutlineThickness(1);
			m_background.setOutlineColor({255, 0, 0});

			this->add_title_line("Performance");
            this->add_line("FPS:             %%", [this]{return m_gamehandler.gamewindow().get_updater().get_fps();});
            this->add_line("FDur:            %%\n", [this]{return m_gamehandler.gamewindow().get_updater().get_frameduration();});

			this->add_title_line("Components");
            this->add_line("Gameworld:       %%", [this]{return m_game.get_world().num_entities();});
            this->add_line("Background:      %%", [this]{return m_gamehandler.backgroundmgr().num_components_current_state();});
            this->add_line("Popups:          %%\n", [this]{return m_gamehandler.popupmgr().num_popups();});

			this->add_title_line("Managers");
            this->add_line("Data:            %%", [this]{return m_gamehandler.datamgr().num_data();});
            this->add_line("Levels:          %%\n", [this]{return m_gamehandler.levelmgr().num_levels();});

            this->add_title_line("States");
            this->add_line("Active (render): %%",
                           [this]{return std::string{state_as_string[(int)m_gamehandler.current_renderable_state()]};});
            this->add_line("Active (all):    %%",
            [this]
            {
                std::string active_states;
                for(std::size_t i{0}; i < (std::size_t)state::num; ++i)
                {
                    if(m_gamehandler.states() & (rj::state)i)
                        active_states += std::string{state_as_string[i]} + " ";
                }
                return active_states;
            });
        }

		void add_title_line(const std::string& text)
		{
			std::string app{'\n'};
			for(auto& a : text)
				app += "=";
			auto ptr(std::make_shared<debug_info_string<void>>(std::string{text + app + "\n"}, []{}));
			m_lines.emplace_back(ptr);
		}

		template<typename Func>
		void add_line(const std::string& text, Func&& f)
		{
			auto ptr(std::make_shared<debug_info_string<typename mlk::lambda_info<Func>::return_type>>(text + '\n', f));
			m_lines.emplace_back(ptr);
		}
	};
}

#endif // RJ_GAME_DEBUG_INFO_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_ANALYZE_HPP
#define TAO_PEGTL_CONTRIB_ANALYZE_HPP

#include <cassert>
#include <cstddef>
#include <iostream>
#include <map>
#include <set>
#include <stdexcept>
#include <string_view>
#include <utility>
#include <vector>

#include "../config.hpp"
#include "../demangle.hpp"

#include "analyze_traits.hpp"

#include "internal/set_stack_guard.hpp"
#include "internal/vector_stack_guard.hpp"

#include "../internal/dependent_false.hpp"

namespace TAO_PEGTL_NAMESPACE
{
   namespace internal
   {
      struct analyze_entry
      {
         explicit analyze_entry( const analyze_type in_type ) noexcept
            : type( in_type )
         {}

         const analyze_type type;
         std::vector< std::string_view > subs;
      };

      class analyze_cycles_impl
      {
      public:
         analyze_cycles_impl( analyze_cycles_impl&& ) = delete;
         analyze_cycles_impl( const analyze_cycles_impl& ) = delete;

         ~analyze_cycles_impl() = default;

         void operator=( analyze_cycles_impl&& ) = delete;
         void operator=( const analyze_cycles_impl& ) = delete;

         [[nodiscard]] std::size_t problems()
         {
            for( auto i = m_info.begin(); i != m_info.end(); ++i ) {
               m_results[ i->first ] = work( i, false );
               m_cache.clear();
            }
            return m_problems;
         }

         template< typename Rule >
         [[nodiscard]] bool consumes() const
         {
            return m_results.at( demangle< Rule >() );
         }

      protected:
         explicit analyze_cycles_impl( const int verbose ) noexcept
            : m_verbose( verbose ),
              m_problems( 0 )
         {}

         [[nodiscard]] std::map< std::string_view, analyze_entry >::const_iterator find( const std::string_view name ) const noexcept
         {
            const auto iter = m_info.find( name );
            assert( iter != m_info.end() );
            return iter;
         }

         [[nodiscard]] bool work( const std::map< std::string_view, analyze_entry >::const_iterator& start, const bool accum )
         {
            if( const auto j = m_cache.find( start->first ); j != m_cache.end() ) {
               return j->second;
            }
            if( const auto g = set_stack_guard( m_stack, start->first ) ) {
               const auto v = vector_stack_guard( m_trace, start->first );
               switch( start->second.type ) {
                  case analyze_type::any: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = true;
                  }
                  case analyze_type::opt: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = false;
                  }
                  case analyze_type::seq: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = a;
                  }
                  case analyze_type::sor: {
                     bool a = true;
                     for( const auto& r : start->second.subs ) {
                        a = a && work( find( r ), accum );
                     }
                     return m_cache[ start->first ] = a;
                  }
               }
               assert( false );  // LCOV_EXCL_LINE
            }
            if( !accum ) {
               ++m_problems;
               if( m_verbose >= 0 ) {
                  std::cerr << "problem: cycle without progress detected at rule " << start->first << std::endl;  // LCOV_EXCL_LINE
                  if( m_verbose > 0 ) {  // LCOV_EXCL_LINE
                     for( const auto& r : m_trace ) {  // LCOV_EXCL_LINE
                        std::cerr << "   involved (transformed) rule: " << r << std::endl;  // LCOV_EXCL_LINE
                     }
                  }
               }
            }
            return m_cache[ start->first ] = accum;
         }

         const int m_verbose;

         std::size_t m_problems;

         std::map< std::string_view, analyze_entry > m_info;
         std::set< std::string_view > m_stack;
         std::vector< std::string_view > m_trace;
         std::map< std::string_view, bool > m_cache;
         std::map< std::string_view, bool > m_results;
      };

      template< typename Name >
      std::string_view analyze_insert( std::map< std::string_view, analyze_entry >& info )
      {
         using Traits = analyze_traits< Name, typename Name::rule_t >;

         const auto [ i, b ] = info.try_emplace( demangle< Name >(), Traits::type_v );
         if( b ) {
            analyze_insert_impl( typename Traits::subs_t(), i->second.subs, info );
         }
         return i->first;
      }

      template< typename... Subs >
      void analyze_insert_impl( type_list< Subs... > /*unused*/, std::vector< std::string_view >& subs, std::map< std::string_view, analyze_entry >& info )
      {
         ( subs.emplace_back( analyze_insert< Subs >( info ) ), ... );
      }

      template< typename Grammar >
      class analyze_cycles
         : public analyze_cycles_impl
      {
      public:
         explicit analyze_cycles( const int verbose )
            : analyze_cycles_impl( verbose )
         {
            analyze_insert< Grammar >( m_info );
         }
      };

   }  // namespace internal

   template< typename Grammar >
   [[nodiscard]] std::size_t analyze( const int verbose = 0 )
   {
      return internal::analyze_cycles< Grammar >( verbose ).problems();
   }

}  // namespace TAO_PEGTL_NAMESPACE

#endif
<commit_msg>Formatting.<commit_after>// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_ANALYZE_HPP
#define TAO_PEGTL_CONTRIB_ANALYZE_HPP

#include <cassert>
#include <cstddef>
#include <iostream>
#include <map>
#include <set>
#include <stdexcept>
#include <string_view>
#include <utility>
#include <vector>

#include "../config.hpp"
#include "../demangle.hpp"

#include "analyze_traits.hpp"

#include "internal/set_stack_guard.hpp"
#include "internal/vector_stack_guard.hpp"

#include "../internal/dependent_false.hpp"

namespace TAO_PEGTL_NAMESPACE
{
   namespace internal
   {
      struct analyze_entry
      {
         explicit analyze_entry( const analyze_type in_type ) noexcept
            : type( in_type )
         {}

         const analyze_type type;
         std::vector< std::string_view > subs;
      };

      class analyze_cycles_impl
      {
      public:
         analyze_cycles_impl( analyze_cycles_impl&& ) = delete;
         analyze_cycles_impl( const analyze_cycles_impl& ) = delete;

         ~analyze_cycles_impl() = default;

         void operator=( analyze_cycles_impl&& ) = delete;
         void operator=( const analyze_cycles_impl& ) = delete;

         [[nodiscard]] std::size_t problems()
         {
            for( auto i = m_info.begin(); i != m_info.end(); ++i ) {
               m_results[ i->first ] = work( i, false );
               m_cache.clear();
            }
            return m_problems;
         }

         template< typename Rule >
         [[nodiscard]] bool consumes() const
         {
            return m_results.at( demangle< Rule >() );
         }

      protected:
         explicit analyze_cycles_impl( const int verbose ) noexcept
            : m_verbose( verbose ),
              m_problems( 0 )
         {}

         [[nodiscard]] std::map< std::string_view, analyze_entry >::const_iterator find( const std::string_view name ) const noexcept
         {
            const auto iter = m_info.find( name );
            assert( iter != m_info.end() );
            return iter;
         }

         [[nodiscard]] bool work( const std::map< std::string_view, analyze_entry >::const_iterator& start, const bool accum )
         {
            if( const auto j = m_cache.find( start->first ); j != m_cache.end() ) {
               return j->second;
            }
            if( const auto g = set_stack_guard( m_stack, start->first ) ) {
               const auto v = vector_stack_guard( m_trace, start->first );
               switch( start->second.type ) {
                  case analyze_type::any: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = true;
                  }
                  case analyze_type::opt: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = false;
                  }
                  case analyze_type::seq: {
                     bool a = false;
                     for( const auto& r : start->second.subs ) {
                        a = a || work( find( r ), accum || a );
                     }
                     return m_cache[ start->first ] = a;
                  }
                  case analyze_type::sor: {
                     bool a = true;
                     for( const auto& r : start->second.subs ) {
                        a = a && work( find( r ), accum );
                     }
                     return m_cache[ start->first ] = a;
                  }
               }
               assert( false );  // LCOV_EXCL_LINE
            }
            if( !accum ) {
               ++m_problems;
               if( m_verbose >= 0 ) {
                  std::cerr << "problem: cycle without progress detected at rule " << start->first << std::endl;  // LCOV_EXCL_LINE
                  if( m_verbose > 0 ) {                                                                           // LCOV_EXCL_LINE
                     for( const auto& r : m_trace ) {                                                             // LCOV_EXCL_LINE
                        std::cerr << "   involved (transformed) rule: " << r << std::endl;                        // LCOV_EXCL_LINE
                     }
                  }
               }
            }
            return m_cache[ start->first ] = accum;
         }

         const int m_verbose;

         std::size_t m_problems;

         std::map< std::string_view, analyze_entry > m_info;
         std::set< std::string_view > m_stack;
         std::vector< std::string_view > m_trace;
         std::map< std::string_view, bool > m_cache;
         std::map< std::string_view, bool > m_results;
      };

      template< typename Name >
      std::string_view analyze_insert( std::map< std::string_view, analyze_entry >& info )
      {
         using Traits = analyze_traits< Name, typename Name::rule_t >;

         const auto [ i, b ] = info.try_emplace( demangle< Name >(), Traits::type_v );
         if( b ) {
            analyze_insert_impl( typename Traits::subs_t(), i->second.subs, info );
         }
         return i->first;
      }

      template< typename... Subs >
      void analyze_insert_impl( type_list< Subs... > /*unused*/, std::vector< std::string_view >& subs, std::map< std::string_view, analyze_entry >& info )
      {
         ( subs.emplace_back( analyze_insert< Subs >( info ) ), ... );
      }

      template< typename Grammar >
      class analyze_cycles
         : public analyze_cycles_impl
      {
      public:
         explicit analyze_cycles( const int verbose )
            : analyze_cycles_impl( verbose )
         {
            analyze_insert< Grammar >( m_info );
         }
      };

   }  // namespace internal

   template< typename Grammar >
   [[nodiscard]] std::size_t analyze( const int verbose = 0 )
   {
      return internal::analyze_cycles< Grammar >( verbose ).problems();
   }

}  // namespace TAO_PEGTL_NAMESPACE

#endif
<|endoftext|>


<commit_before>// Copyright (C) 2016 Zhe Wang <0x1998@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <ni/logging/log_worker.hh>

#include <x86intrin.h>

#include <ni/logging/log_message.hh>
#include <ni/logging/logger.hh>
#include <ni/logging/message_bus.hh>

namespace ni
{
namespace logging
{

LogWorker::LogWorker(MessageBus& message_bus)
  : m_input(message_bus)
  , m_thread()
  , m_stopping()
{
}

LogWorker::~LogWorker()
{
  stop();
}

void LogWorker::start(pthread_attr_t* attrs)
{
  assert(!m_thread);
  pthread_create(&m_thread, attrs, LogWorker::start_thread, this);
  pthread_setname_np(m_thread, "LogWorker");
}

void* LogWorker::start_thread(void* args)
{
  static_cast<LogWorker*>(args)->run();
  return nullptr;
}

void LogWorker::run()
{
  size_t spins = 0;
  std::vector<Logger*> loggers;
  std::unique_ptr<LogMessage> msg;
  auto flush_loggers = [&]
  {
    for (Logger* logger : loggers)
      logger->flush();
  };

  while (true)
  {
    bool has_messages = false;
    loggers.clear();

    for (MessageBus::ChannelPtr& channel : m_input.channels())
    {
      msg.reset(channel->pop());
      if (!msg)
        continue;

      loggers.emplace_back(msg->logger);
      msg->logger->save(msg.get());
      msg = nullptr;
      has_messages = true;
    }

    if (has_messages)
    {
      flush_loggers();
      spins = 0;
      continue;
    }

    if (m_stopping.load(std::memory_order_acquire))
    {
      flush_loggers();
      return;
    }

    if (!spins)
      flush_loggers();

    if (spins < MAX_SPINS)
    {
      __pause();
      ++spins;
    }
    else
    {
      m_input.wait();
      spins = 0;
    }
  }
}

void LogWorker::stop()
{
  if (!m_thread)
    return;
  m_stopping.store(true, std::memory_order_release);
  m_input.notify();
  pthread_join(m_thread, nullptr);
  m_thread = 0;
}

} // namespace logging
} // namespace ni
<commit_msg>Change LogWorker thread name to "Logging"<commit_after>// Copyright (C) 2016 Zhe Wang <0x1998@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <ni/logging/log_worker.hh>

#include <x86intrin.h>

#include <ni/logging/log_message.hh>
#include <ni/logging/logger.hh>
#include <ni/logging/message_bus.hh>

namespace ni
{
namespace logging
{

LogWorker::LogWorker(MessageBus& message_bus)
  : m_input(message_bus)
  , m_thread()
  , m_stopping()
{
}

LogWorker::~LogWorker()
{
  stop();
}

void LogWorker::start(pthread_attr_t* attrs)
{
  assert(!m_thread);
  pthread_create(&m_thread, attrs, LogWorker::start_thread, this);
  pthread_setname_np(m_thread, "Logging");
}

void* LogWorker::start_thread(void* args)
{
  static_cast<LogWorker*>(args)->run();
  return nullptr;
}

void LogWorker::run()
{
  size_t spins = 0;
  std::vector<Logger*> loggers;
  std::unique_ptr<LogMessage> msg;
  auto flush_loggers = [&]
  {
    for (Logger* logger : loggers)
      logger->flush();
  };

  while (true)
  {
    bool has_messages = false;
    loggers.clear();

    for (MessageBus::ChannelPtr& channel : m_input.channels())
    {
      msg.reset(channel->pop());
      if (!msg)
        continue;

      loggers.emplace_back(msg->logger);
      msg->logger->save(msg.get());
      msg = nullptr;
      has_messages = true;
    }

    if (has_messages)
    {
      flush_loggers();
      spins = 0;
      continue;
    }

    if (m_stopping.load(std::memory_order_acquire))
    {
      flush_loggers();
      return;
    }

    if (!spins)
      flush_loggers();

    if (spins < MAX_SPINS)
    {
      __pause();
      ++spins;
    }
    else
    {
      m_input.wait();
      spins = 0;
    }
  }
}

void LogWorker::stop()
{
  if (!m_thread)
    return;
  m_stopping.store(true, std::memory_order_release);
  m_input.notify();
  pthread_join(m_thread, nullptr);
  m_thread = 0;
}

} // namespace logging
} // namespace ni
<|endoftext|>


<commit_before>#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "ChatColor.h"

const std::string cChatColor::Color     = "\xc2\xa7";  // or in other words: "§" in UTF-8
const std::string cChatColor::Delimiter = "\xc2\xa7";  // or in other words: "§" in UTF-8
const std::string cChatColor::Black       = cChatColor::Color + "0";
const std::string cChatColor::Navy        = cChatColor::Color + "1";
const std::string cChatColor::Green       = cChatColor::Color + "2";
const std::string cChatColor::Blue        = cChatColor::Color + "3";
const std::string cChatColor::Red         = cChatColor::Color + "4";
const std::string cChatColor::Purple      = cChatColor::Color + "5";
const std::string cChatColor::Gold        = cChatColor::Color + "6";
const std::string cChatColor::LightGray   = cChatColor::Color + "7";
const std::string cChatColor::Gray        = cChatColor::Color + "8";
const std::string cChatColor::DarkPurple  = cChatColor::Color + "9";
const std::string cChatColor::LightGreen  = cChatColor::Color + "a";
const std::string cChatColor::LightBlue   = cChatColor::Color + "b";
const std::string cChatColor::Rose        = cChatColor::Color + "c";
const std::string cChatColor::LightPurple = cChatColor::Color + "d";
const std::string cChatColor::Yellow      = cChatColor::Color + "e";
const std::string cChatColor::White       = cChatColor::Color + "f";

const std::string cChatColor::Random      = cChatColor::Color + "k";
const std::string cChatColor::Bold        = cChatColor::Color + "l";
const std::string cChatColor::Strikethrough = cChatColor::Color + "m";
const std::string cChatColor::Underlined  = cChatColor::Color + "n";
const std::string cChatColor::Italic      = cChatColor::Color + "o";
const std::string cChatColor::Plain       = cChatColor::Color + "r";

const std::string cChatColor::MakeColor( const AString & a_Color )
{
	return a_Color;
}

<commit_msg>Finally removed the function.<commit_after>#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "ChatColor.h"

const std::string cChatColor::Color     = "\xc2\xa7";  // or in other words: "§" in UTF-8
const std::string cChatColor::Delimiter = "\xc2\xa7";  // or in other words: "§" in UTF-8
const std::string cChatColor::Black       = cChatColor::Color + "0";
const std::string cChatColor::Navy        = cChatColor::Color + "1";
const std::string cChatColor::Green       = cChatColor::Color + "2";
const std::string cChatColor::Blue        = cChatColor::Color + "3";
const std::string cChatColor::Red         = cChatColor::Color + "4";
const std::string cChatColor::Purple      = cChatColor::Color + "5";
const std::string cChatColor::Gold        = cChatColor::Color + "6";
const std::string cChatColor::LightGray   = cChatColor::Color + "7";
const std::string cChatColor::Gray        = cChatColor::Color + "8";
const std::string cChatColor::DarkPurple  = cChatColor::Color + "9";
const std::string cChatColor::LightGreen  = cChatColor::Color + "a";
const std::string cChatColor::LightBlue   = cChatColor::Color + "b";
const std::string cChatColor::Rose        = cChatColor::Color + "c";
const std::string cChatColor::LightPurple = cChatColor::Color + "d";
const std::string cChatColor::Yellow      = cChatColor::Color + "e";
const std::string cChatColor::White       = cChatColor::Color + "f";

const std::string cChatColor::Random      = cChatColor::Color + "k";
const std::string cChatColor::Bold        = cChatColor::Color + "l";
const std::string cChatColor::Strikethrough = cChatColor::Color + "m";
const std::string cChatColor::Underlined  = cChatColor::Color + "n";
const std::string cChatColor::Italic      = cChatColor::Color + "o";
const std::string cChatColor::Plain       = cChatColor::Color + "r";

<|endoftext|>


<commit_before>#include "../include/Core/Game.h"

#include "Core/Player.h"
#include "Network/Server.h"
#include "Core/Derived/Constant.h"
#include "Core/Derived/Creature.h"
#include "Core/Derived/Spell.h"

#include <thread>
#include "boost/thread.hpp"

void Game::Start()
{
	cout << "Game started!" << endl;

	// Inital draw and mulligan
	MulliganState();

	// "Normal" game loop logic
	PlayState();
}

void Game::MulliganState()
{
	// Each player draws 5 cards
	for (auto i : Players)
	{
		//i->Draw(5);
	}

	// Let them decide what cards to keep
	int playersDone = 0;
	vector<Player*> tempPlayers = Players;
	Player* tempPlayer;

	cout << tempPlayers.size() << endl;

	for (auto player : Players)
	{
		player->m_Client->Write("Select the cards you wish to keep...");
		//player->m_Client->Write(print cards in hand)
	}

	while (true)
	{
		for (Player* player : tempPlayers)
		{
			if (!player->Mulligan.empty())
			{
				// Store the pointer of the player done mulliganning
				tempPlayer = player;
				playersDone++;
			}
		}

		// Attempt to remove it
		tempPlayers.erase(remove(tempPlayers.begin(), tempPlayers.end(), tempPlayer), tempPlayers.end());

		// Are we done?
		if (playersDone == Players.size())
		{
			break;
		}
	}

	// Make sure all players have 5 cards in hand
	for (auto i : Players)
	{
		size_t HandSize = i->Hand.size();
		if (HandSize < 5)
		{
			//i->Draw(5 - HandSize);
		}
	}
}

void Game::PlayState() const
{
	// Listen for messages from the correct client
	while (true)
	{
		if (!ActivePlayer->m_Client->Listening)
		{
			ActivePlayer->m_Client->StartListening();
		}
	}
}

void Game::StartTurn() const
{
	m_Server->WriteToAll("It is " + ActivePlayer->Name + "'s turn");
}

void Game::EndTurn() const
{
	m_Server->WriteToAll(ActivePlayer->Name + " turn end");
}

void Game::AttackPlay(std::string attack)
{
	m_Server->WriteToAll(ActivePlayer->Name + " attack: " + attack);
}

void Game::CardPlay(int index)
{
	Card* card = ActivePlayer->Hand.at(index);
	CardOrder.push_back(card);

	// Check the derived type of the card object and play it in the appropriate area
	if (Creature* creature = Creature::GetCreature(card))
	{
		card->Owner->Creatures.push_back(creature);
	}
	if (Spell* spell = Spell::GetSpell(card))
	{
		card->Owner->Spells.push_back(spell);
	}
	if (Constant* constant = Constant::GetConstant(card))
	{
		card->Owner->Constants.push_back(constant);
	}

	m_Server->WriteToAll(ActivePlayer->Name + " plays card at: " + to_string(index));
}

void Game::HandlePlay(string play)
{
	switch (play.at(0))
	{
		case CARD_PROTOCOL:
		{
			int index = stoi(GetAfterChar(play, CARD_PROTOCOL));
			CardPlay(index);
			break;
		}

		case ATTACK_PROTOCOL:
		{
			std::string attack = GetAfterChar(play, ATTACK_PROTOCOL);
			AttackPlay(attack);
			break;
		}

		case END_PROTOCOL:
		{
			EndTurn();
			break;
		}

		default: {};
	}
}

void Game::ChangeActivePlayer()
{
	//If the active player is the last item in the vector
	if (ActiveIndex == (Players.size() - 1))
	{
		//Set it to the front of the vector
		ActiveIndex = 0;
	}
	else
	{
		ActiveIndex++;
	}

	// Set the active player pointer
	ActivePlayer = Players.at(ActiveIndex);
}

void Game::ClearDeadCards()
{
}

void Game::ClearDeadPlayers()
{
}

void Game::CheckEffects(Action* action)
{
}

bool Game::IsGameOver()
{
	int aliveCounter = 0;

	for (auto player : Players)
	{
		if (player->Alive)
		{
			aliveCounter++;
		}
	}

	if (aliveCounter <= 1)
	{
		// There is one or less players alive
		return true;
	}
	return false;
}

Game::Game(vector<Player*> players, Server* server)
	: PLAYER_HEALTH(30), PLAYER_MANA(1), Players(players), ActivePlayer(players.at(0)), ActiveIndex(0), m_Server(server)
{
	cout << "Game created, initializing game settings..." << endl;

	for (auto p : Players)
	{
		cout << p->Name << " is here with us today!" << endl;
	}

	// Right now the first player given is the first active player (first to play)
	// Set all the players heal and starting mana according to this games settings
	for (auto player : Players)
	{
		player->Health = PLAYER_HEALTH;
		player->Mana = PLAYER_MANA;
		player->TotalMana = PLAYER_MANA;
		player->CurrentGame = this;
	}
}

Game::~Game()
{
}

std::string Game::GetAfterChar(std::string data, char splitter)
{
	std::string substring = data.substr(data.find(splitter) + 1);
	return substring;
}
<commit_msg>Changed if's to else if's when type checking the card to play. Used the remove from hand method and changed the message written to all players.<commit_after>#include "../include/Core/Game.h"

#include "Core/Player.h"
#include "Network/Server.h"
#include "Core/Derived/Constant.h"
#include "Core/Derived/Creature.h"
#include "Core/Derived/Spell.h"

#include <thread>
#include "boost/thread.hpp"

void Game::Start()
{
	cout << "Game started!" << endl;

	// Inital draw and mulligan
	MulliganState();

	// "Normal" game loop logic
	PlayState();
}

void Game::MulliganState()
{
	// Each player draws 5 cards
	for (auto i : Players)
	{
		//i->Draw(5);
	}

	// Let them decide what cards to keep
	int playersDone = 0;
	vector<Player*> tempPlayers = Players;
	Player* tempPlayer;

	cout << tempPlayers.size() << endl;

	for (auto player : Players)
	{
		player->m_Client->Write("Select the cards you wish to keep...");
		//player->m_Client->Write(print cards in hand)
	}

	while (true)
	{
		for (Player* player : tempPlayers)
		{
			if (!player->Mulligan.empty())
			{
				// Store the pointer of the player done mulliganning
				tempPlayer = player;
				playersDone++;
			}
		}

		// Attempt to remove it
		tempPlayers.erase(remove(tempPlayers.begin(), tempPlayers.end(), tempPlayer), tempPlayers.end());

		// Are we done?
		if (playersDone == Players.size())
		{
			break;
		}
	}

	// Make sure all players have 5 cards in hand
	for (auto i : Players)
	{
		size_t HandSize = i->Hand.size();
		if (HandSize < 5)
		{
			//i->Draw(5 - HandSize);
		}
	}
}

void Game::PlayState() const
{
	// Listen for messages from the correct client
	while (true)
	{
		if (!ActivePlayer->m_Client->Listening)
		{
			ActivePlayer->m_Client->StartListening();
		}
	}
}

void Game::StartTurn() const
{
	m_Server->WriteToAll("It is " + ActivePlayer->Name + "'s turn");
}

void Game::EndTurn() const
{
	m_Server->WriteToAll(ActivePlayer->Name + " turn end");
}

void Game::AttackPlay(std::string attack)
{
	m_Server->WriteToAll(ActivePlayer->Name + " attack: " + attack);
}

void Game::CardPlay(int index)
{
	Card* card = ActivePlayer->Hand.at(index);
	CardOrder.push_back(card);

	// Check the derived type of the card object and play it in the appropriate area
	if (Creature* creature = Creature::GetCreature(card))
	{
		card->Owner->Creatures.push_back(creature);
	}
	else if (Spell* spell = Spell::GetSpell(card))
	{
		card->Owner->Spells.push_back(spell);
	}
	else if (Constant* constant = Constant::GetConstant(card))
	{
		card->Owner->Constants.push_back(constant);
	}

	// The card was played, lets remove it from the active players hand
	ActivePlayer->RemoveFromHand(card);

	m_Server->WriteToAll(card->Owner->Name + " played " + card->Name);
}

void Game::HandlePlay(string play)
{
	switch (play.at(0))
	{
		case CARD_PROTOCOL:
		{
			int index = stoi(GetAfterChar(play, CARD_PROTOCOL));
			CardPlay(index);
			break;
		}

		case ATTACK_PROTOCOL:
		{
			std::string attack = GetAfterChar(play, ATTACK_PROTOCOL);
			AttackPlay(attack);
			break;
		}

		case END_PROTOCOL:
		{
			EndTurn();
			break;
		}

		default: {};
	}
}

void Game::ChangeActivePlayer()
{
	//If the active player is the last item in the vector
	if (ActiveIndex == (Players.size() - 1))
	{
		//Set it to the front of the vector
		ActiveIndex = 0;
	}
	else
	{
		ActiveIndex++;
	}

	// Set the active player pointer
	ActivePlayer = Players.at(ActiveIndex);
}

void Game::ClearDeadCards()
{
}

void Game::ClearDeadPlayers()
{
}

void Game::CheckEffects(Action* action)
{
}

bool Game::IsGameOver()
{
	int aliveCounter = 0;

	for (auto player : Players)
	{
		if (player->Alive)
		{
			aliveCounter++;
		}
	}

	if (aliveCounter <= 1)
	{
		// There is one or less players alive
		return true;
	}
	return false;
}

Game::Game(vector<Player*> players, Server* server)
	: PLAYER_HEALTH(30), PLAYER_MANA(1), Players(players), ActivePlayer(players.at(0)), ActiveIndex(0), m_Server(server)
{
	cout << "Game created, initializing game settings..." << endl;

	for (auto p : Players)
	{
		cout << p->Name << " is here with us today!" << endl;
	}

	// Right now the first player given is the first active player (first to play)
	// Set all the players heal and starting mana according to this games settings
	for (auto player : Players)
	{
		player->Health = PLAYER_HEALTH;
		player->Mana = PLAYER_MANA;
		player->TotalMana = PLAYER_MANA;
		player->CurrentGame = this;
	}
}

Game::~Game()
{
}

std::string Game::GetAfterChar(std::string data, char splitter)
{
	std::string substring = data.substr(data.find(splitter) + 1);
	return substring;
}
<|endoftext|>