<commit_before>#include "../test.h"
#include <rxcpp/operators/rx-map.hpp>

SCENARIO("map stops on completion", "[map][operators]") {
    GIVEN("a test hot observable of ints") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;
        long invoked = 0;

        auto xs = sc.make_hot_observable({
            on.next(180, 1),
            on.next(210, 2),
            on.next(240, 3),
            on.next(290, 4),
            on.next(350, 5),
            on.completed(400),
            on.next(410, -1),
            on.completed(420),
            on.error(430, std::runtime_error("error on unsubscribed stream"))
        });

        WHEN("mapped to ints that are one larger") {

            auto res = w.start(
                [xs, &invoked]() {
                    return xs
                        .map([&invoked](int x) {
                            invoked++;
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output stops on completion") {
                auto required = rxu::to_vector({
                    on.next(210, 3),
                    on.next(240, 4),
                    on.next(290, 5),
                    on.next(350, 6),
                    on.completed(400)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was one subscription and one unsubscription") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 400)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

            THEN("map was called until completed") {
                REQUIRE(4 == invoked);
            }
        }
    }
}

SCENARIO("map - never", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        | rxo::map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        | rxo::as_dynamic();
                }
            );

            THEN("the output is empty") {
                auto required = std::vector<rxsc::test::messages<int>::recorded_type>();
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 1000)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }
        }
    }
}

SCENARIO("map - empty", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.completed(250)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains complete message") {
                auto required = rxu::to_vector({
                    on.completed(250)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 250)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map - items emitted", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.next(210, 2),
            on.next(240, 3),
            on.completed(300)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains items sent while subscribed") {
                auto required = rxu::to_vector({
                    on.next(210, 3),
                    on.next(240, 4),
                    on.completed(300)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 300)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map - throw", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        std::runtime_error ex("map on_error from source");

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.error(250, ex)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains only error") {
                auto required = rxu::to_vector({
                    on.error(250, ex)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 250)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map doesn't provide copies", "[map][operators][copies]")
{
    GIVEN("observable and subscriber")
    {
        auto          empty_on_next = [](copy_verifier) {};
        auto          sub           = rx::make_observer<copy_verifier>(empty_on_next);
        copy_verifier verifier{};
        auto          obs = verifier.get_observable().map([](auto&& v) { return std::forward<decltype(v)>(v); });
        WHEN("subscribe")
        {
            obs.subscribe(sub);
            THEN("no extra copies")
            {
                // 1 copy from map lambda
                REQUIRE(verifier.get_copy_count() == 1);
                 // 1 move to final lambda
                REQUIRE(verifier.get_move_count() == 1);
            }
        }
    }
}

SCENARIO("map doesn't provide copies for move", "[map][operators][copies]")
{
    GIVEN("observable and subscriber")
    {
        auto          empty_on_next = [](copy_verifier) {};
        auto          sub           = rx::make_observer<copy_verifier>(empty_on_next);
        copy_verifier verifier{};
        auto          obs = verifier.get_observable_for_move().map([](auto&& v) { return std::forward<decltype(v)>(v); });
        WHEN("subscribe")
        {
            obs.subscribe(sub);
            THEN("no extra copies")
            {
                REQUIRE(verifier.get_copy_count() == 0);
                // 1 move from map lambda +  1 move to final lambda
                REQUIRE(verifier.get_move_count() == 2);
            }
        }
    }
}
<commit_msg>Fix compilation on c++11. Auto&& not needed here<commit_after>#include "../test.h"
#include <rxcpp/operators/rx-map.hpp>

SCENARIO("map stops on completion", "[map][operators]") {
    GIVEN("a test hot observable of ints") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;
        long invoked = 0;

        auto xs = sc.make_hot_observable({
            on.next(180, 1),
            on.next(210, 2),
            on.next(240, 3),
            on.next(290, 4),
            on.next(350, 5),
            on.completed(400),
            on.next(410, -1),
            on.completed(420),
            on.error(430, std::runtime_error("error on unsubscribed stream"))
        });

        WHEN("mapped to ints that are one larger") {

            auto res = w.start(
                [xs, &invoked]() {
                    return xs
                        .map([&invoked](int x) {
                            invoked++;
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output stops on completion") {
                auto required = rxu::to_vector({
                    on.next(210, 3),
                    on.next(240, 4),
                    on.next(290, 5),
                    on.next(350, 6),
                    on.completed(400)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was one subscription and one unsubscription") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 400)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

            THEN("map was called until completed") {
                REQUIRE(4 == invoked);
            }
        }
    }
}

SCENARIO("map - never", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        | rxo::map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        | rxo::as_dynamic();
                }
            );

            THEN("the output is empty") {
                auto required = std::vector<rxsc::test::messages<int>::recorded_type>();
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 1000)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }
        }
    }
}

SCENARIO("map - empty", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.completed(250)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains complete message") {
                auto required = rxu::to_vector({
                    on.completed(250)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 250)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map - items emitted", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.next(210, 2),
            on.next(240, 3),
            on.completed(300)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains items sent while subscribed") {
                auto required = rxu::to_vector({
                    on.next(210, 3),
                    on.next(240, 4),
                    on.completed(300)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 300)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map - throw", "[map][operators]") {
    GIVEN("a source") {
        auto sc = rxsc::make_test();
        auto w = sc.create_worker();
        const rxsc::test::messages<int> on;

        std::runtime_error ex("map on_error from source");

        auto xs = sc.make_hot_observable({
            on.next(150, 1),
            on.error(250, ex)
        });

        WHEN("values are mapped") {

            auto res = w.start(
                [xs]() {
                    return xs
                        .map([](int x) {
                            return x + 1;
                        })
                        // forget type to workaround lambda deduction bug on msvc 2013
                        .as_dynamic();
                }
            );

            THEN("the output only contains only error") {
                auto required = rxu::to_vector({
                    on.error(250, ex)
                });
                auto actual = res.get_observer().messages();
                REQUIRE(required == actual);
            }

            THEN("there was 1 subscription/unsubscription to the source") {
                auto required = rxu::to_vector({
                    on.subscribe(200, 250)
                });
                auto actual = xs.subscriptions();
                REQUIRE(required == actual);
            }

        }
    }
}

SCENARIO("map doesn't provide copies", "[map][operators][copies]")
{
    GIVEN("observable and subscriber")
    {
        auto          empty_on_next = [](copy_verifier) {};
        auto          sub           = rx::make_observer<copy_verifier>(empty_on_next);
        copy_verifier verifier{};
        auto          obs = verifier.get_observable().map([](copy_verifier v) { return v; });
        WHEN("subscribe")
        {
            obs.subscribe(sub);
            THEN("no extra copies")
            {
                // 1 copy to map lambda
                REQUIRE(verifier.get_copy_count() == 1);
                 // 1 move from map lambda + 1 move to final lambda
                REQUIRE(verifier.get_move_count() == 2);
            }
        }
    }
}

SCENARIO("map doesn't provide copies for move", "[map][operators][copies]")
{
    GIVEN("observable and subscriber")
    {
        auto          empty_on_next = [](copy_verifier) {};
        auto          sub           = rx::make_observer<copy_verifier>(empty_on_next);
        copy_verifier verifier{};
        auto          obs = verifier.get_observable_for_move().map([](copy_verifier v) { return v; });
        WHEN("subscribe")
        {
            obs.subscribe(sub);
            THEN("no extra copies")
            {
                REQUIRE(verifier.get_copy_count() == 0);
                // 1 move to map lambda  + 1 move from map lambda +  1 move to final lambda
                REQUIRE(verifier.get_move_count() == 3);
            }
        }
    }
}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
* Martin Renou                                                             *
* Copyright (c) QuantStack                                                 *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

// This file is derived from tsimd (MIT License)
// https://github.com/ospray/tsimd/blob/master/benchmarks/mandelbrot.cpp
// Author Jefferson Amstutz / intel

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>

#include "pico_bench.hpp"

#define XSIMD_ENABLE_FALLBACK

#include <xsimd/xsimd.hpp>

// helper function to write the rendered image as PPM file
inline void writePPM(const std::string &fileName,
                     const int sizeX,
                     const int sizeY,
                     const int *pixel)
{
    FILE* file = fopen(fileName.c_str(), "wb");
    fprintf(file, "P6\n%i %i\n255\n", sizeX, sizeY);
    unsigned char* out = (unsigned char*)alloca(3 * sizeX);
    for (int y = 0; y < sizeY; y++)
    {
        const unsigned char* in =
            (const unsigned char*) &pixel[(sizeY - 1 - y) * sizeX];

        for (int x = 0; x < sizeX; x++)
        {
            out[3 * x + 0] = in[4 * x + 0];
            out[3 * x + 1] = in[4 * x + 1];
            out[3 * x + 2] = in[4 * x + 2];
        }

        fwrite(out, 3 * sizeX, sizeof(char), file);
    }
    fprintf(file, "\n");
    fclose(file);
}

namespace xsimd {

  template <std::size_t N>
  inline batch<int, N> mandel(const batch_bool<float, N> &_active,
                              const batch<float, N> &c_re,
                              const batch<float, N> &c_im,
                              int maxIters)
  {
      batch<float, N> z_re = c_re;
      batch<float, N> z_im = c_im;
      batch<int,   N> vi(0);

      for (int i = 0; i < maxIters; ++i)
      {
          auto active = _active & ((z_re * z_re + z_im * z_im) <= batch<float, N>(4.f));
          if (!xsimd::any(active))
          {
              break;
          }

          batch<float, N> new_re = z_re * z_re - z_im * z_im;
          batch<float, N> new_im = 2.f * z_re * z_im;

          z_re = c_re + new_re;
          z_im = c_im + new_im;

          vi = select(bool_cast(active), vi + 1, vi);
      }

      return vi;
  }

  template <std::size_t N>
  void mandelbrot(float x0,
                  float y0,
                  float x1,
                  float y1,
                  int width,
                  int height,
                  int maxIters,
                  int output[])
  {
      float dx = (x1 - x0) / width;
      float dy = (y1 - y0) / height;

      float arange[N];
      std::iota(&arange[0], &arange[N], 0.f);
      batch<float, N> programIndex(&arange[0], xsimd::aligned_mode());
      // std::iota(programIndex.begin(), programIndex.end(), 0.f);

      for (int j = 0; j < height; j++)
      {
          for (int i = 0; i < width; i += N)
          {
              batch<float, N> x(x0 + (i + programIndex) * dx);
              batch<float, N> y(y0 + j * dy);

              auto active = x < batch<float, N>(width);

              int base_index = (j * width + i);
              auto result    = mandel(active, x, y, maxIters);

              // implement masked store!
              // xsimd::store_aligned(result, output + base_index, active);
              batch<int, N> prev_data(output + base_index);
              select(bool_cast(active), result, prev_data)
                    .store_aligned(output + base_index);
          }
      }
  }

} // namespace xsimd

// omp version ////////////////////////////////////////////////////////////////

namespace omp {

#pragma omp declare simd
    template <typename T>
    inline int mandel(T c_re, T c_im, int count)
    {
        T z_re = c_re, z_im = c_im;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (z_re * z_re + z_im * z_im > 4.f)
            {
                break;
            }

            T new_re = z_re * z_re - z_im * z_im;
            T new_im = 2.f * z_re * z_im;
            z_re     = c_re + new_re;
            z_im     = c_im + new_im;
        }

        return i;
    }

    void mandelbrot(float x0, float y0, float x1, float y1, int width,
                    int height, int maxIterations, int output[])
    {
        float dx = (x1 - x0) / width;
        float dy = (y1 - y0) / height;

        for (int j = 0; j < height; j++)
        {

#pragma omp simd
            for (int i = 0; i < width; ++i)
            {
                float x = x0 + i * dx;
                float y = y0 + j * dy;

                int index = (j * width + i);
                output[index] = mandel<float>(x, y, maxIterations);
            }
        }
    }

} // namespace omp

// scalar version /////////////////////////////////////////////////////////////

namespace scalar {

    inline int mandel(float c_re, float c_im, int count)
    {
        float z_re = c_re, z_im = c_im;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (z_re * z_re + z_im * z_im > 4.f)
            {
                break;
            }

            float new_re = z_re * z_re - z_im * z_im;
            float new_im = 2.f * z_re * z_im;
            z_re         = c_re + new_re;
            z_im         = c_im + new_im;
        }

        return i;
    }

    void mandelbrot(float x0, float y0, float x1, float y1,
                    int width, int height, int maxIterations, int output[])
    {
        float dx = (x1 - x0) / width;
        float dy = (y1 - y0) / height;

        for (int j = 0; j < height; j++)
        {
            for (int i = 0; i < width; ++i)
            {
                float x = x0 + i * dx;
                float y = y0 + j * dy;

                int index     = (j * width + i);
                output[index] = mandel(x, y, maxIterations);
            }
        }
    }

}  // namespace scalar

int main()
{
    using namespace std::chrono;

    const unsigned int width  = 1024;
    const unsigned int height = 768;
    const float x0            = -2;
    const float x1            = 1;
    const float y0            = -1;
    const float y1            = 1;
    const int maxIters        = 256;

    std::vector<int, xsimd::aligned_allocator<int>> buf(width * height);

    auto bencher = pico_bench::Benchmarker<milliseconds>{64, seconds{10}};

    std::cout << "starting benchmarks (results in 'ms')... " << '\n';

    // scalar run ///////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_scalar = bencher([&]() {
      scalar::mandelbrot(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float scalar_min = stats_scalar.min().count();

    std::cout << '\n' << "scalar " << stats_scalar << '\n';

    writePPM("mandelbrot_scalar.ppm", width, height, buf.data());

    // omp run //////////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_omp = bencher([&]() {
      omp::mandelbrot(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float omp_min = stats_omp.min().count();

    std::cout << '\n' << "omp " << stats_omp << '\n';

    writePPM("mandelbrot_omp.ppm", width, height, buf.data());

    // xsimd_1 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_1 = bencher([&]() {
      xsimd::mandelbrot<1>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd1_min = stats_1.min().count();

    std::cout << '\n' << "xsimd_1 " << stats_1 << '\n';

    writePPM("mandelbrot_xsimd1.ppm", width, height, buf.data());

    // xsimd_4 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_4 = bencher([&]() {
      xsimd::mandelbrot<4>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd4_min = stats_4.min().count();

    std::cout << '\n' << "xsimd_4 " << stats_4 << '\n';

    writePPM("mandelbrot_xsimd4.ppm", width, height, buf.data());

    // xsimd_8 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_8 = bencher([&]() {
      xsimd::mandelbrot<8>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd8_min = stats_8.min().count();

    std::cout << '\n' << "xsimd_8 " << stats_8 << '\n';

    writePPM("mandelbrot_xsimd8.ppm", width, height, buf.data());

    // xsimd_16 run /////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_16 = bencher([&]() {
      xsimd::mandelbrot<16>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd16_min = stats_16.min().count();

    std::cout << '\n' << "xsimd_16 " << stats_16 << '\n';

    writePPM("mandelbrot_xsimd16.ppm", width, height, buf.data());

    // conclusions //////////////////////////////////////////////////////////////

    std::cout << '\n' << "Conclusions: " << '\n';

    // scalar //

    std::cout << '\n'
              << "--> scalar was " << omp_min / scalar_min
              << "x the speed of omp";

    std::cout << '\n'
              << "--> scalar was " << xsimd1_min / scalar_min
              << "x the speed of xsimd_1";

    std::cout << '\n'
              << "--> scalar was " << xsimd4_min / scalar_min
              << "x the speed of xsimd_4";

    std::cout << '\n'
              << "--> scalar was " << xsimd8_min / scalar_min
              << "x the speed of xsimd_8";

    std::cout << '\n'
              << "--> scalar was " << xsimd16_min / scalar_min
              << "x the speed of xsimd_16" << '\n';

    // omp //

    std::cout << '\n'
              << "--> omp was " << scalar_min / omp_min
              << "x the speed of scalar";

    std::cout << '\n'
              << "--> omp was " << xsimd1_min / omp_min
              << "x the speed of xsimd_1";

    std::cout << '\n'
              << "--> omp was " << xsimd4_min / omp_min
              << "x the speed of xsimd_4";

    std::cout << '\n'
              << "--> omp was " << xsimd8_min / omp_min
              << "x the speed of xsimd_8";

    std::cout << '\n'
              << "--> omp was " << xsimd16_min / omp_min
              << "x the speed of xsimd_16" << '\n';

    // xsimd1 //

    std::cout << '\n'
              << "--> xsimd1 was " << scalar_min / xsimd1_min
              << "x the speed of scalar";

    std::cout << '\n'
              << "--> xsimd1 was " << omp_min / xsimd1_min
              << "x the speed of omp";

    std::cout << '\n'
              << "--> xsimd1 was " << xsimd4_min / xsimd1_min
              << "x the speed of xsimd_4";

    std::cout << '\n'
              << "--> xsimd1 was " << xsimd8_min / xsimd1_min
              << "x the speed of xsimd_8";

    std::cout << '\n'
              << "--> xsimd1 was " << xsimd16_min / xsimd1_min
              << "x the speed of xsimd_16" << '\n';

    // xsimd4 //

    std::cout << '\n'
              << "--> xsimd4 was " << scalar_min / xsimd4_min
              << "x the speed of scalar";

    std::cout << '\n'
              << "--> xsimd4 was " << omp_min / xsimd4_min
              << "x the speed of omp";

    std::cout << '\n'
              << "--> xsimd4 was " << xsimd1_min / xsimd4_min
              << "x the speed of xsimd_1";

    std::cout << '\n'
              << "--> xsimd4 was " << xsimd8_min / xsimd4_min
              << "x the speed of xsimd_8";

    std::cout << '\n'
              << "--> xsimd4 was " << xsimd16_min / xsimd4_min
              << "x the speed of xsimd_16" << '\n';

    // xsimd8 //

    std::cout << '\n'
              << "--> xsimd8 was " << scalar_min / xsimd8_min
              << "x the speed of scalar";

    std::cout << '\n'
              << "--> xsimd8 was " << omp_min / xsimd8_min
              << "x the speed of omp";

    std::cout << '\n'
              << "--> xsimd8 was " << xsimd1_min / xsimd8_min
              << "x the speed of xsimd_1";

    std::cout << '\n'
              << "--> xsimd8 was " << xsimd4_min / xsimd8_min
              << "x the speed of xsimd_4";

    std::cout << '\n'
              << "--> xsimd8 was " << xsimd16_min / xsimd8_min
              << "x the speed of xsimd_16" << '\n';

    // xsimd16 //

    std::cout << '\n'
              << "--> xsimd16 was " << scalar_min / xsimd16_min
              << "x the speed of scalar";

    std::cout << '\n'
              << "--> xsimd16 was " << omp_min / xsimd16_min
              << "x the speed of omp";

    std::cout << '\n'
              << "--> xsimd16 was " << xsimd1_min / xsimd16_min
              << "x the speed of xsimd_1";

    std::cout << '\n'
              << "--> xsimd16 was " << xsimd4_min / xsimd16_min
              << "x the speed of xsimd_4";

    std::cout << '\n'
              << "--> xsimd16 was " << xsimd8_min / xsimd16_min
              << "x the speed of xsimd_8" << '\n';

    std::cout << '\n' << "wrote output images to 'mandelbrot_[type].ppm'" << '\n';

    return 0;
}
<commit_msg>minor changes<commit_after>/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
* Martin Renou                                                             *
* Copyright (c) QuantStack                                                 *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

// This file is derived from tsimd (MIT License)
// https://github.com/ospray/tsimd/blob/master/benchmarks/mandelbrot.cpp
// Author Jefferson Amstutz / intel

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>       // operator typeid

#include "pico_bench.hpp"

#define XSIMD_ENABLE_FALLBACK

#include <xsimd/xsimd.hpp>

// helper function to write the rendered image as PPM file
inline void writePPM(const std::string &fileName,
                     const int sizeX,
                     const int sizeY,
                     const int *pixel)
{
    FILE* file = fopen(fileName.c_str(), "wb");
    fprintf(file, "P6\n%i %i\n255\n", sizeX, sizeY);
    unsigned char* out = (unsigned char*)alloca(3 * sizeX);
    for (int y = 0; y < sizeY; y++)
    {
        const unsigned char* in =
            (const unsigned char*) &pixel[(sizeY - 1 - y) * sizeX];

        for (int x = 0; x < sizeX; x++)
        {
            out[3 * x + 0] = in[4 * x + 0];
            out[3 * x + 1] = in[4 * x + 1];
            out[3 * x + 2] = in[4 * x + 2];
        }

        fwrite(out, 3 * sizeX, sizeof(char), file);
    }
    fprintf(file, "\n");
    fclose(file);
}

namespace xsimd {

  template <class arch>
  inline batch<int, arch> mandel(const batch_bool<float, arch> &_active,
                              const batch<float, arch> &c_re,
                              const batch<float, arch> &c_im,
                              int maxIters)
  {
      using float_batch_type = batch<float, arch>;
      using int_batch_type = batch<int, arch>;

      constexpr std::size_t N = float_batch_type::size;

      float_batch_type z_re = c_re;
      float_batch_type z_im = c_im;
      int_batch_type vi(0);

      for (int i = 0; i < maxIters; ++i)
      {
          auto active = _active & ((z_re * z_re + z_im * z_im) <= float_batch_type(4.f));
          if (!xsimd::any(active))
          {
              break;
          }

          float_batch_type new_re = z_re * z_re - z_im * z_im;
          float_batch_type new_im = 2.f * z_re * z_im;

          z_re = c_re + new_re;
          z_im = c_im + new_im;

          vi = select(bool_cast(active), vi + 1, vi);
      }

      return vi;
  }

  template <class arch>
  void mandelbrot(float x0,
                  float y0,
                  float x1,
                  float y1,
                  int width,
                  int height,
                  int maxIters,
                  int output[])
  {
      using float_batch_type = batch<float, arch>;
      using int_batch_type = batch<int, arch>;

      constexpr std::size_t N = float_batch_type::size;
      float dx = (x1 - x0) / width;
      float dy = (y1 - y0) / height;

      float arange[N];
      std::iota(&arange[0], &arange[N], 0.f);
      //float_batch_type programIndex(&arange[0], xsimd::aligned_mode());

      auto programIndex = float_batch_type::load(&arange[0], xsimd::aligned_mode());
      // std::iota(programIndex.begin(), programIndex.end(), 0.f);

      for (int j = 0; j < height; j++)
      {
          for (int i = 0; i < width; i += N)
          {
              float_batch_type x(x0 + (i + programIndex) * dx);
              float_batch_type y(y0 + j * dy);

              auto active = x < float_batch_type(width);

              int base_index = (j * width + i);
              auto result    = mandel<arch>(active, x, y, maxIters);

              // implement masked store!
              // xsimd::store_aligned(result, output + base_index, active);
              int_batch_type prev_data(output + base_index);
              select(bool_cast(active), result, prev_data)
                    .store_aligned(output + base_index);
          }
      }
  }

} // namespace xsimd

// omp version ////////////////////////////////////////////////////////////////

namespace omp {

#pragma omp declare simd
    template <typename T>
    inline int mandel(T c_re, T c_im, int count)
    {
        T z_re = c_re, z_im = c_im;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (z_re * z_re + z_im * z_im > 4.f)
            {
                break;
            }

            T new_re = z_re * z_re - z_im * z_im;
            T new_im = 2.f * z_re * z_im;
            z_re     = c_re + new_re;
            z_im     = c_im + new_im;
        }

        return i;
    }

    void mandelbrot(float x0, float y0, float x1, float y1, int width,
                    int height, int maxIterations, int output[])
    {
        float dx = (x1 - x0) / width;
        float dy = (y1 - y0) / height;

        for (int j = 0; j < height; j++)
        {

#pragma omp simd
            for (int i = 0; i < width; ++i)
            {
                float x = x0 + i * dx;
                float y = y0 + j * dy;

                int index = (j * width + i);
                output[index] = mandel<float>(x, y, maxIterations);
            }
        }
    }

} // namespace omp

// scalar version /////////////////////////////////////////////////////////////

namespace scalar {

    inline int mandel(float c_re, float c_im, int count)
    {
        float z_re = c_re, z_im = c_im;
        int i;
        for (i = 0; i < count; ++i)
        {
            if (z_re * z_re + z_im * z_im > 4.f)
            {
                break;
            }

            float new_re = z_re * z_re - z_im * z_im;
            float new_im = 2.f * z_re * z_im;
            z_re         = c_re + new_re;
            z_im         = c_im + new_im;
        }

        return i;
    }

    void mandelbrot(float x0, float y0, float x1, float y1,
                    int width, int height, int maxIterations, int output[])
    {
        float dx = (x1 - x0) / width;
        float dy = (y1 - y0) / height;

        for (int j = 0; j < height; j++)
        {
            for (int i = 0; i < width; ++i)
            {
                float x = x0 + i * dx;
                float y = y0 + j * dy;

                int index     = (j * width + i);
                output[index] = mandel(x, y, maxIterations);
            }
        }
    }

}  // namespace scalar

template<class arch, class bencher_t>
void run_arch(
              bencher_t & bencher,
              float x0,
              float y0,
              float x1,
              float y1,
              int width,
              int height,
              int maxIters,
              std::vector<int, xsimd::aligned_allocator<int>> & buffer)
{
  std::fill(buffer.begin(), buffer.end(), 0);
  auto stats = bencher([&]() {
    xsimd::mandelbrot<arch>(x0, y0, x1, y1, width, height, maxIters, buffer.data());
  });

  const float scalar_min = stats.min().count();

  std::cout << '\n' << typeid(arch).name() <<" "<< stats << '\n';
  auto filename = std::string("mandelbrot_") + std::string(typeid(arch).name()) + std::string(".ppm");
  writePPM(filename.c_str(), width, height, buffer.data());

}

template<class T>
struct RunMandelbrot;

template<class ... Arch>
struct RunMandelbrot<xsimd::arch_list<Arch ...>>
{
    template<class bencher_t>
    static void run(
                  bencher_t & bencher,
                  float x0,
                  float y0,
                  float x1,
                  float y1,
                  int width,
                  int height,
                  int maxIters,
                  std::vector<int, xsimd::aligned_allocator<int>> & buffer)
    {
      using expand_type = int[];
      expand_type{(run_arch<Arch>(bencher, x0, y0,x1,x1,width,height, maxIters, buffer),0)...};
    }
};

int main()
{
    using namespace std::chrono;

    const unsigned int width  = 1024;
    const unsigned int height = 768;
    const float x0            = -2;
    const float x1            = 1;
    const float y0            = -1;
    const float y1            = 1;
    const int maxIters        = 256;

    std::vector<int, xsimd::aligned_allocator<int>> buf(width * height);

    auto bencher = pico_bench::Benchmarker<milliseconds>{64, seconds{10}};

    std::cout << "starting benchmarks (results in 'ms')... " << '\n';

    // scalar run ///////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_scalar = bencher([&]() {
      scalar::mandelbrot(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float scalar_min = stats_scalar.min().count();

    std::cout << '\n' << "scalar " << stats_scalar << '\n';

    writePPM("mandelbrot_scalar.ppm", width, height, buf.data());

    // omp run //////////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_omp = bencher([&]() {
      omp::mandelbrot(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float omp_min = stats_omp.min().count();

    std::cout << '\n' << "omp " << stats_omp << '\n';

    writePPM("mandelbrot_omp.ppm", width, height, buf.data());

    RunMandelbrot<xsimd::supported_architectures>::run(bencher, x0, y0, x1, y1, width, height, maxIters, buf);

    // xsimd_1 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_1 = bencher([&]() {
      xsimd::mandelbrot<xsimd::avx>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd1_min = stats_1.min().count();

    std::cout << '\n' << "xsimd_1 " << stats_1 << '\n';

    writePPM("mandelbrot_xsimd1.ppm", width, height, buf.data());

    // xsimd_4 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_4 = bencher([&]() {
      xsimd::mandelbrot<xsimd::avx>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd4_min = stats_4.min().count();

    std::cout << '\n' << "xsimd_4 " << stats_4 << '\n';

    writePPM("mandelbrot_xsimd4.ppm", width, height, buf.data());

    // xsimd_8 run //////////////////////////////////////////////////////////////

    std::fill(buf.begin(), buf.end(), 0);

    auto stats_8 = bencher([&]() {
      xsimd::mandelbrot<xsimd::avx>(x0, y0, x1, y1, width, height, maxIters, buf.data());
    });

    const float xsimd8_min = stats_8.min().count();

    std::cout << '\n' << "xsimd_8 " << stats_8 << '\n';

    writePPM("mandelbrot_xsimd8.ppm", width, height, buf.data());

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <time.h>
#include <cassert>
#include "SerialPortReceiverThread.h"

SerialPortReceiverThread::SerialPortReceiverThread(
	SerialPort& serialPort, ON_BYTE_RECEIVED onByteReceived)
	: serialPort(serialPort), onByteReceived(onByteReceived)
{

}

bool SerialPortReceiverThread::run()
{
	uint8_t data;
	if (serialPort.IsOpen()) {
		if (serialPort.Read(&data, 0, 1)) {
			this->onByteReceived(data);
		}
		else {
			Sleep(10);
		}
	}
	return true;
}
<commit_msg>Fix a bug receiving unknown character<commit_after>#include <iostream>
#include <time.h>
#include <cassert>
#include "SerialPortReceiverThread.h"

SerialPortReceiverThread::SerialPortReceiverThread(
	SerialPort& serialPort, ON_BYTE_RECEIVED onByteReceived)
	: serialPort(serialPort), onByteReceived(onByteReceived)
{

}

bool SerialPortReceiverThread::run()
{
	uint8_t data;
	if (serialPort.IsOpen()) {
		if (serialPort.Read(&data, 0, 1) == 1) {
			this->onByteReceived(data);
		}
		else {
			Sleep(10);
		}
	}
	return true;
}
<|endoftext|>


<commit_before>#include "Scene.h"
#include "../../OpenGLESApp2/OpenGLESApp2.Android.NativeActivity/Renderer.h"

namespace SunnySideUp {

  class TitleScene : public Mai::Scene {
  public:
	TitleScene() : result(Mai::SCENEID_CONTINUE), loaded(false) {}
	virtual ~TitleScene() {}
	virtual bool Load(Mai::Engine& engine) {
	  if (!loaded) {
		objList.reserve(8);
		Mai::Renderer& r = engine.GetRenderer();
		auto obj = r.CreateObject("TitleLogo", Mai::Material(Mai::Color4B(255, 255, 255, 255), 0, 0), "default");
		obj->SetTranslation(Mai::Vector3F(0, -5, 0));
		//obj->SetRotation(degreeToRadian<float>(0), degreeToRadian<float>(0), degreeToRadian<float>(0));
		//obj->SetScale(Vector3F(5, 5, 5));
		objList.push_back(obj);
		loaded = true;
	  }
	  status = STATUSCODE_RUNNABLE;
	  return true;
	}
	virtual bool Unload(Mai::Engine&) {
	  if (loaded) {
		objList.clear();
		loaded = false;
	  }
	  status = STATUSCODE_STOPPED;
	  return true;
	}
	virtual int Update(Mai::Engine& engine, float tick) {
	  Mai::Renderer& r = engine.GetRenderer();
	  r.Update(tick, Mai::Position3F(0, 0, 0), Mai::Vector3F(0, -1, 0), Mai::Vector3F(0, 0, -1));
	  return result;
	}
	virtual void ProcessWindowEvent(Mai::Engine& engine, const Mai::Event& e) {
	  switch (e.Type) {
	  case Mai::Event::EVENT_MOUSE_BUTTON_PRESSED:
		if (e.MouseButton.Button == MOUSEBUTTON_LEFT) {
		  result = SCENEID_STARTEVENT;
		}
		break;
	  default:
		break;
	  }
	}
	virtual void Draw(Mai::Engine& engine) {
	  Mai::Renderer& r = engine.GetRenderer();
	  r.Render(&objList[0], &objList[0] + objList.size());
	}
  private:
	std::vector<Mai::ObjectPtr> objList;
	int result;
	bool loaded;
  };

  Mai::ScenePtr CreateTitleScene(Mai::Engine&) {
	return Mai::ScenePtr(new TitleScene());
  }

} // namespace SunnySideUp
<commit_msg>add the using namespace.<commit_after>#include "Scene.h"
#include "../../OpenGLESApp2/OpenGLESApp2.Android.NativeActivity/Renderer.h"

namespace SunnySideUp {

  using namespace Mai;

  class TitleScene : public Scene {
  public:
	TitleScene() : result(SCENEID_CONTINUE), loaded(false) {}
	virtual ~TitleScene() {}
	virtual bool Load(Engine& engine) {
	  if (!loaded) {
		objList.reserve(8);
		Renderer& r = engine.GetRenderer();
		{
		  auto obj = r.CreateObject("TitleLogo", Material(Color4B(255, 255, 255, 255), 0, 0), "default");
		  obj->SetTranslation(Vector3F(0, -5, 0));
		  //obj->SetRotation(degreeToRadian<float>(0), degreeToRadian<float>(0), degreeToRadian<float>(0));
		  //obj->SetScale(Vector3F(5, 5, 5));
		  objList.push_back(obj);
		}
		loaded = true;
	  }
	  status = STATUSCODE_RUNNABLE;
	  return true;
	}
	virtual bool Unload(Engine&) {
	  if (loaded) {
		objList.clear();
		loaded = false;
	  }
	  status = STATUSCODE_STOPPED;
	  return true;
	}
	virtual int Update(Engine& engine, float tick) {
	  Renderer& r = engine.GetRenderer();
	  r.Update(tick, Position3F(0, 0, 0), Vector3F(0, -1, 0), Vector3F(0, 0, -1));
	  return result;
	}
	virtual void ProcessWindowEvent(Engine& engine, const Event& e) {
	  switch (e.Type) {
	  case Event::EVENT_MOUSE_BUTTON_PRESSED:
		if (e.MouseButton.Button == MOUSEBUTTON_LEFT) {
		  result = SCENEID_STARTEVENT;
		}
		break;
	  default:
		break;
	  }
	}
	virtual void Draw(Engine& engine) {
	  Renderer& r = engine.GetRenderer();
	  r.Render(&objList[0], &objList[0] + objList.size());
	}
  private:
	std::vector<ObjectPtr> objList;
	int result;
	bool loaded;
  };

  ScenePtr CreateTitleScene(Engine&) {
	return ScenePtr(new TitleScene());
  }

} // namespace SunnySideUp
<|endoftext|>


<commit_before>/**
 * @file Reader.hpp
 * @author Pallamidessi Joseph
 * @version 1.0
 *
 * @section LICENSE
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 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
 * General Public License for more details at
 * http://www.gnu.org/copyleft/gpl.html
**/
#ifndef READER_H__
#define READER_H__

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <AudioMonitorModule.h>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp>

class Reader {
public:
  Reader (char* path,AudioMonitorModule* sendingModule,MonitorParameter* params);
  virtual ~Reader ();

  void start();
  void join();
  void readAndSend();
  bool testLine(boost::filesystem::path extension,std::string buffer);
private:
  boost::filesystem::path mPathTo;
  boost::thread mThread;
  AudioMonitorModule* mSendingModule;
  MonitorParameter* mParams;

};

#endif /* end of include guard: READER_H__ */
<commit_msg>Doc doxygen documentation to class Reader<commit_after>/**
 * @file Reader.hpp
 * @author Pallamidessi Joseph
 * @version 1.0
 *
 * @section LICENSE
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 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
 * General Public License for more details at
 * http://www.gnu.org/copyleft/gpl.html
**/
#ifndef READER_H__
#define READER_H__

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <AudioMonitorModule.h>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp>

/**
*  /struct   Reader
*  /brief    Take an .csv .dat input file and simulated and EASEA node
*  /details  Used the communication modules from EASEA programs. Each Reader
*            object run in a separated thread.
**/
class Reader {
public:
  /**
  * /brief    Constructor of Reader
  * /details  Use a pre-existing AudioMonitorModule which initialized the
  *           communication to the central server.
  *
  * @param    path          Path to a data file (currently supported : EASEA formated .csv and
  *                         .dat)
  * @param    sendingModule An AudioMonitorModule correctly linked to a monitoring server.
  * @param    params        A MonitorParameter derived object
  **/
  Reader (char* path,AudioMonitorModule* sendingModule,MonitorParameter* params);
  /**
  * /brief    Destructor of Reader
  * /details  Free the associated AudioMonitorModule and MonitorParameter
  *
  **/
  virtual ~Reader ();

  /**
  * /brief    Start the simulation in an encapsulated thread
  * /details  Call readAndSend() in a boost::thread.
  *
  **/
  void start();
  /**
  * /brief    Join the encapsulated thread.
  * /details  Wrap boost::thread join() on the encapsulated thread.
  *
  **/
  void join();
  /**
  * /brief    The main loop, read from the input file to send a
  *           monitoring message.
  * /details
  **/
  void readAndSend();
  /**
  * /brief    Test if the given buffer correspond to a data line or not
  * /details  Check if '#' if the first letter of a .dat line, or if the first
  *           element is a letter in case of a .csv file
  *
  * @param    extension The input file path extension
  * @param    buffer    A buffer corresponding to a line of the file
  * @return   bool      True if it's a data line, false otherwise.
  **/
  bool testLine(boost::filesystem::path extension,std::string buffer);
private:
  boost::filesystem::path mPathTo;
  boost::thread mThread;
  AudioMonitorModule* mSendingModule;
  MonitorParameter* mParams;

};

#endif /* end of include guard: READER_H__ */
<|endoftext|>


<commit_before>#include "stdafx.h"
/*
* Copyright (c) 2009 SlimDX Group
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/

#include <iostream>

#include "SocketServer.h"

using boost::asio::ip::tcp;

typedef boost::shared_ptr<class TcpConnection> TcpConnectionPtr;

class TcpConnection : public boost::enable_shared_from_this<TcpConnection>
{
private:
	SocketServer& m_server;
	boost::asio::ip::tcp::socket m_socket;
	CRITICAL_SECTION m_writeLock;

	unsigned int m_parseOffset;
	unsigned int m_recvSize;

	static const int kBufferSize = 896;
	boost::array<char, kBufferSize> m_recvBuffer;

	void HandleWrite(const boost::system::error_code&, size_t);
	bool ContinueRead(const boost::system::error_code& err, size_t);
	void HandleRead( const boost::system::error_code& err, size_t);

	TcpConnection(SocketServer& server, boost::asio::io_service& io);

	void SendMapping(const Requests::GetFunctionMapping& request);

public:
	~TcpConnection();

	static TcpConnectionPtr Create(SocketServer& server, boost::asio::io_service& io)
	{
		return TcpConnectionPtr(new TcpConnection(server, io));
	}

	boost::asio::ip::tcp::socket& GetSocket()
	{
		return m_socket;
	}

	bool IsOpen() const { return m_socket.is_open(); }
	void Close() { m_socket.close(); }

	void BeginRead(unsigned int offset = 0);
	void Write(const void* data, size_t size);
};

TcpConnection::TcpConnection(SocketServer& server, boost::asio::io_service& io)
: m_server(server),
m_socket(io),
m_parseOffset(0)
{
	InitializeCriticalSection(&m_writeLock);
	//the use of 100 here is entirely arbitrary
	SetCriticalSectionSpinCount(&m_writeLock, 100);
}

TcpConnection::~TcpConnection()
{
	DeleteCriticalSection(&m_writeLock);
}

void TcpConnection::BeginRead(unsigned int offset)
{
	m_recvSize = kBufferSize - offset;
	boost::asio::async_read(m_socket, boost::asio::buffer(&m_recvBuffer[0] + offset, m_recvSize),
		//ContinueRead
		boost::bind(&TcpConnection::ContinueRead, shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred),
		//HandleRead
		boost::bind(&TcpConnection::HandleRead, shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred)
		);
}

void TcpConnection::Write(const void* data, size_t size)
{
	EnterLock writeLock(&m_writeLock);

	boost::asio::async_write(m_socket, boost::asio::buffer(data, size),
		boost::bind(&SocketServer::HandleWrite, &m_server,
		shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
}

void TcpConnection::SendMapping(const Requests::GetFunctionMapping& request)
{
	const FunctionInfo* func = m_server.ProfilerData().GetFunction(request.FunctionId);
	if(func != NULL)
	{
		Messages::MapFunction mapping;
		mapping.FunctionId = request.FunctionId;
		mapping.IsNative = func->IsNative;
		wcscpy_s(mapping.SymbolName, Messages::MapFunction::MaxNameSize, func->Name.c_str());
		wcscpy_s(mapping.Signature, Messages::MapFunction::MaxSignatureSize, func->Signature.c_str());
		mapping.Write(m_server, func->Name.size(), func->Signature.size());
	}
}

bool TcpConnection::ContinueRead(const boost::system::error_code&, size_t bytesRead)
{
	if(bytesRead < 1)
		return false;

	size_t prevBytes = kBufferSize - m_recvSize;

	char* bufPtr = &m_recvBuffer[m_parseOffset];
	size_t bytesToParse = bytesRead + prevBytes;
	while(bytesToParse > 0)
	{
		size_t bytesParsed = 0;
		switch(*bufPtr)
		{
		case CR_GetFunctionMapping:
			{
				if(bytesToParse < 5)
					goto FinishRead;
				Requests::GetFunctionMapping gfmReq = Requests::GetFunctionMapping::Read(++bufPtr, bytesParsed);
				SendMapping(gfmReq);
				break;
			}
		default:
			goto FinishRead;
		}

		bufPtr += bytesParsed;
		bytesToParse -= bytesParsed + 1;
	}

FinishRead:
	if(bytesRead >= m_recvSize)
	{
		//ran out of space, so don't keep reading
		//copy the remaining buffer to the beginning and store the offset to start the next recv there
		memmove_s(&m_recvBuffer[0], kBufferSize, bufPtr, bytesToParse);
		m_parseOffset = bytesToParse;
		return true;
	}

	m_parseOffset = bufPtr - &m_recvBuffer[0];
	return false;
}

void TcpConnection::HandleRead(const boost::system::error_code& err, size_t bytesRead)
{
	//this means the read ended, so we'll launch a new one
	BeginRead(m_parseOffset);
	m_parseOffset = 0;
}

void TcpConnection::HandleWrite(const boost::system::error_code& err, size_t)
{

}

SocketServer::SocketServer(IProfilerData& profilerData, unsigned short port)
: m_profilerData(profilerData),
m_io(),
m_acceptor(m_io, tcp::endpoint(tcp::v4(), port)),
m_onConnect(NULL),
m_onDisconnect(NULL),
m_sendBuffer(SendBufferSize),
m_writeStart(m_sendBuffer.GetBufferRoot()),
m_writeLength(0)
{
	InitializeCriticalSection(&m_writeLock);
}

SocketServer::~SocketServer()
{
	DeleteCriticalSection(&m_writeLock);
}

void SocketServer::Start()
{
	TcpConnectionPtr conn = TcpConnection::Create(*this, m_acceptor.io_service());
	m_acceptor.async_accept(conn->GetSocket(),
		boost::bind(&SocketServer::Accept, this, conn, boost::asio::placeholders::error));
}

void SocketServer::Run()
{
	m_io.run();
}

void SocketServer::Stop()
{
	int oldLength = InterlockedExchange(&m_writeLength, 0);
	char* bufferPos = m_sendBuffer.Alloc(0);
	Flush(oldLength, bufferPos);

	m_io.stop();

	for(size_t i = 0; i < m_connections.size(); ++i)
	{
		if(m_connections[i]->IsOpen())
			m_connections[i]->Close();
	}
}

void SocketServer::Accept(TcpConnectionPtr conn, const boost::system::error_code& error)
{
	if(!error)
	{
		EnterLock localLock(&m_writeLock);

		conn->BeginRead();
		m_connections.push_back(conn);

		if(m_connections.size() == 1 && m_onConnect)
			m_onConnect();

		Start();
	}
}

void SocketServer::HandleWrite(TcpConnectionPtr source, const boost::system::error_code& error, size_t)
{
	if(error)
	{
		std::string errorMessage = error.message();

		//we can remove this connection from our list
		EnterLock localLock(&m_writeLock);

		std::vector<TcpConnectionPtr>::iterator deadConn = std::find(m_connections.begin(), m_connections.end(), source);
		//this callback will trigger multiple times when multiple writes are queued up,
		//so we can't be sure the connection exists to erase
		if(deadConn != m_connections.end())
		{
			m_connections.erase(deadConn);

			if(m_connections.size() == 0 && m_onDisconnect)
			{
				m_onDisconnect();
			}
		}
	}
}

void SocketServer::WaitForConnection()
{
	if(m_connections.size() == 0)
		m_io.run_one();
}

void SocketServer::SetCallbacks(ServerCallback onConnect, ServerCallback onDisconnect)
{
	m_onConnect = onConnect;
	m_onDisconnect = onDisconnect;
}

void SocketServer::Write(const void* data, size_t sizeBytes)
{
	assert(sizeBytes < FlushSize); //this function will break otherwise

	char* bufferPos = m_sendBuffer.Alloc((LONG) sizeBytes);
	if(bufferPos == NULL)
		return;

	memcpy(bufferPos, data, sizeBytes);

	//Decide whether or not to flush
	bool flush = false;

#ifdef LOCKLESS
	LONG oldLength = InterlockedExchangeAdd(&m_writeLength, (LONG) sizeBytes);
	assert(oldLength < 2 * FlushSize);

	if(oldLength + sizeBytes >= FlushSize && oldLength < FlushSize)
	{
		//we're the ones who pushed the write length over the limit
		flush = true;
	}
	else if(bufferPos == m_sendBuffer.GetBufferRoot())
	{
		//this means the ring buffer has rolled over and it's our fault
		flush = true;
	}
#else
	LONG oldLength = m_writeLength;
	m_writeLength += sizeBytes;

	if(m_writeLength > FlushSize || bufferPos == m_sendBuffer.GetBufferRoot())
		flush = true;
#endif

	if(flush)
	{
		Flush(oldLength, bufferPos);
	}
}

void SocketServer::Flush(int oldLength, const char* bufferPos)
{
	if(oldLength == 0)
		return;

	EnterLock localLock(&m_writeLock);

#ifdef LOCKLESS
	//we do NOT flush the current write
	InterlockedExchangeAdd(&m_writeLength, -oldLength);
	//Since the introduction of the lock here, we don't need to do this interlocked
	//const char* writeStart = (char*) InterlockedExchange((LONG*) &m_writeStart, (LONG) bufferPos);
#else
	m_writeLength -= oldLength;
#endif

	for(size_t i = 0; i < m_connections.size(); ++i)
	{
		m_connections[i]->Write(m_writeStart, oldLength);
	}
	m_writeStart = bufferPos;
}
<commit_msg>Patched up a bug in the backend receive code.<commit_after>#include "stdafx.h"
/*
* Copyright (c) 2009 SlimDX Group
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/

#include <iostream>

#include "SocketServer.h"

using boost::asio::ip::tcp;

typedef boost::shared_ptr<class TcpConnection> TcpConnectionPtr;

class TcpConnection : public boost::enable_shared_from_this<TcpConnection>
{
private:
	SocketServer& m_server;
	boost::asio::ip::tcp::socket m_socket;
	CRITICAL_SECTION m_writeLock;

	unsigned int m_parseOffset;
	unsigned int m_recvSize;

	static const int kBufferSize = 896;
	boost::array<char, kBufferSize> m_recvBuffer;

	void HandleWrite(const boost::system::error_code&, size_t);
	bool ContinueRead(const boost::system::error_code& err, size_t);
	void HandleRead( const boost::system::error_code& err, size_t);

	TcpConnection(SocketServer& server, boost::asio::io_service& io);

	void SendMapping(const Requests::GetFunctionMapping& request);

public:
	~TcpConnection();

	static TcpConnectionPtr Create(SocketServer& server, boost::asio::io_service& io)
	{
		return TcpConnectionPtr(new TcpConnection(server, io));
	}

	boost::asio::ip::tcp::socket& GetSocket()
	{
		return m_socket;
	}

	bool IsOpen() const { return m_socket.is_open(); }
	void Close() { m_socket.close(); }

	void BeginRead(unsigned int offset = 0);
	void Write(const void* data, size_t size);
};

TcpConnection::TcpConnection(SocketServer& server, boost::asio::io_service& io)
: m_server(server),
m_socket(io),
m_parseOffset(0)
{
	InitializeCriticalSection(&m_writeLock);
	//the use of 100 here is entirely arbitrary
	SetCriticalSectionSpinCount(&m_writeLock, 100);
}

TcpConnection::~TcpConnection()
{
	DeleteCriticalSection(&m_writeLock);
}

void TcpConnection::BeginRead(unsigned int offset)
{
	m_recvSize = kBufferSize - offset;
	boost::asio::async_read(m_socket, boost::asio::buffer(&m_recvBuffer[0] + offset, m_recvSize),
		//ContinueRead
		boost::bind(&TcpConnection::ContinueRead, shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred),
		//HandleRead
		boost::bind(&TcpConnection::HandleRead, shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred)
		);
}

void TcpConnection::Write(const void* data, size_t size)
{
	EnterLock writeLock(&m_writeLock);

	boost::asio::async_write(m_socket, boost::asio::buffer(data, size),
		boost::bind(&SocketServer::HandleWrite, &m_server,
		shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
}

void TcpConnection::SendMapping(const Requests::GetFunctionMapping& request)
{
	const FunctionInfo* func = m_server.ProfilerData().GetFunction(request.FunctionId);
	if(func != NULL)
	{
		Messages::MapFunction mapping;
		mapping.FunctionId = request.FunctionId;
		mapping.IsNative = func->IsNative;
		wcscpy_s(mapping.SymbolName, Messages::MapFunction::MaxNameSize, func->Name.c_str());
		wcscpy_s(mapping.Signature, Messages::MapFunction::MaxSignatureSize, func->Signature.c_str());
		mapping.Write(m_server, func->Name.size(), func->Signature.size());
	}
	else
	{
#ifdef DEBUG
		__debugbreak();
#endif
	}
}

bool TcpConnection::ContinueRead(const boost::system::error_code&, size_t bytesRead)
{
	if(bytesRead < 1)
		return false;

	size_t prevBytes = kBufferSize - m_recvSize;
	size_t bytesToParse = bytesRead + prevBytes - m_parseOffset;

	char* bufPtr = &m_recvBuffer[m_parseOffset];
	while(bytesToParse > 0)
	{
		size_t bytesParsed = 0;
		switch(*bufPtr)
		{
		case CR_GetFunctionMapping:
			{
				if(bytesToParse < 5)
					goto FinishRead;
				Requests::GetFunctionMapping gfmReq = Requests::GetFunctionMapping::Read(++bufPtr, bytesParsed);
				SendMapping(gfmReq);
				break;
			}
		default:
#ifdef DEBUG
			__debugbreak();
#endif
			//this is considered catastrophic corruption, so terminate the connection
			m_socket.close();
			return true;
		}

		bufPtr += bytesParsed;
		bytesToParse -= bytesParsed + 1;
	}

FinishRead:
	if(bytesRead >= m_recvSize)
	{
		//ran out of space, so don't keep reading
		//copy the remaining buffer to the beginning and store the offset to start the next recv there
		memmove_s(&m_recvBuffer[0], kBufferSize, bufPtr, bytesToParse);
		m_parseOffset = bytesToParse;
		return true;
	}

	m_parseOffset = bufPtr - &m_recvBuffer[0];
	return false;
}

void TcpConnection::HandleRead(const boost::system::error_code& err, size_t bytesRead)
{
	//this means the read ended, so we'll launch a new one
	BeginRead(m_parseOffset);
	m_parseOffset = 0;
}

void TcpConnection::HandleWrite(const boost::system::error_code& err, size_t)
{

}

SocketServer::SocketServer(IProfilerData& profilerData, unsigned short port)
: m_profilerData(profilerData),
m_io(),
m_acceptor(m_io, tcp::endpoint(tcp::v4(), port)),
m_onConnect(NULL),
m_onDisconnect(NULL),
m_sendBuffer(SendBufferSize),
m_writeStart(m_sendBuffer.GetBufferRoot()),
m_writeLength(0)
{
	InitializeCriticalSection(&m_writeLock);
}

SocketServer::~SocketServer()
{
	DeleteCriticalSection(&m_writeLock);
}

void SocketServer::Start()
{
	TcpConnectionPtr conn = TcpConnection::Create(*this, m_acceptor.io_service());
	m_acceptor.async_accept(conn->GetSocket(),
		boost::bind(&SocketServer::Accept, this, conn, boost::asio::placeholders::error));
}

void SocketServer::Run()
{
	m_io.run();
}

void SocketServer::Stop()
{
	int oldLength = InterlockedExchange(&m_writeLength, 0);
	char* bufferPos = m_sendBuffer.Alloc(0);
	Flush(oldLength, bufferPos);

	m_io.stop();

	for(size_t i = 0; i < m_connections.size(); ++i)
	{
		if(m_connections[i]->IsOpen())
			m_connections[i]->Close();
	}
}

void SocketServer::Accept(TcpConnectionPtr conn, const boost::system::error_code& error)
{
	if(!error)
	{
		EnterLock localLock(&m_writeLock);

		conn->BeginRead();
		m_connections.push_back(conn);

		if(m_connections.size() == 1 && m_onConnect)
			m_onConnect();

		Start();
	}
}

void SocketServer::HandleWrite(TcpConnectionPtr source, const boost::system::error_code& error, size_t)
{
	if(error)
	{
		std::string errorMessage = error.message();

		//we can remove this connection from our list
		EnterLock localLock(&m_writeLock);

		std::vector<TcpConnectionPtr>::iterator deadConn = std::find(m_connections.begin(), m_connections.end(), source);
		//this callback will trigger multiple times when multiple writes are queued up,
		//so we can't be sure the connection exists to erase
		if(deadConn != m_connections.end())
		{
			m_connections.erase(deadConn);

			if(m_connections.size() == 0 && m_onDisconnect)
			{
				m_onDisconnect();
			}
		}
	}
}

void SocketServer::WaitForConnection()
{
	if(m_connections.size() == 0)
		m_io.run_one();
}

void SocketServer::SetCallbacks(ServerCallback onConnect, ServerCallback onDisconnect)
{
	m_onConnect = onConnect;
	m_onDisconnect = onDisconnect;
}

void SocketServer::Write(const void* data, size_t sizeBytes)
{
	assert(sizeBytes < FlushSize); //this function will break otherwise

	char* bufferPos = m_sendBuffer.Alloc((LONG) sizeBytes);
	if(bufferPos == NULL)
		return;

	memcpy(bufferPos, data, sizeBytes);

	//Decide whether or not to flush
	bool flush = false;

#ifdef LOCKLESS
	LONG oldLength = InterlockedExchangeAdd(&m_writeLength, (LONG) sizeBytes);
	assert(oldLength < 2 * FlushSize);

	if(oldLength + sizeBytes >= FlushSize && oldLength < FlushSize)
	{
		//we're the ones who pushed the write length over the limit
		flush = true;
	}
	else if(bufferPos == m_sendBuffer.GetBufferRoot())
	{
		//this means the ring buffer has rolled over and it's our fault
		flush = true;
	}
#else
	LONG oldLength = m_writeLength;
	m_writeLength += sizeBytes;

	if(m_writeLength > FlushSize || bufferPos == m_sendBuffer.GetBufferRoot())
		flush = true;
#endif

	if(flush)
	{
		Flush(oldLength, bufferPos);
	}
}

void SocketServer::Flush(int oldLength, const char* bufferPos)
{
	if(oldLength == 0)
		return;

	EnterLock localLock(&m_writeLock);

#ifdef LOCKLESS
	//we do NOT flush the current write
	InterlockedExchangeAdd(&m_writeLength, -oldLength);
	//Since the introduction of the lock here, we don't need to do this interlocked
	//const char* writeStart = (char*) InterlockedExchange((LONG*) &m_writeStart, (LONG) bufferPos);
#else
	m_writeLength -= oldLength;
#endif

	for(size_t i = 0; i < m_connections.size(); ++i)
	{
		m_connections[i]->Write(m_writeStart, oldLength);
	}
	m_writeStart = bufferPos;
}
<|endoftext|>


<commit_before>#pragma once

#include <iostream>

namespace RealRT
{

    class Vector3D
    {
        public:
            Vector3D(void) = default;

            Vector3D(float i, float j, float k);

            explicit Vector3D(const float *values);

            Vector3D(std::initializer_list<float> list);

            float I(void) const;

            float J(void) const;

            float K(void) const;

            Vector3D Add(const Vector3D &v) const

            Vector3D Subtract(const Vector3D &v) const

            Vector3D Normalize(void) const;

            float Distance(const Vector3D &rhs) const;

            float Magnitude(void) const;

            Vector3D Scale(float scalar) const;

            Vector3D Clip(float maxVal) const;

            Vector3D Weight(Vector3D dimWeights) const

            float Dot(const Vector3D &rhs) const;

            Vector3D Cross(const Vector3D &rhs) const;

            float operator [](int i) const;

            bool operator ==(const Vector3D &rhs) const;

            bool operator !=(const Vector3D &rhs) const;

            bool operator <(const Vector3D &rhs) const;

            bool operator <=(const Vector3D &rhs) const;

            bool operator >(const Vector3D &rhs) const;

            bool operator >=(const Vector3D &rhs) const;

            Vector3D operator +(const Vector3D &rhs) const;

            Vector3D operator -(const Vector3D &rhs) const;

            Vector3D &operator +=(const Vector3D &rhs);

            Vector3D &operator -=(const Vector3D &rhs);

            friend Vector3D operator *(float scalar, const Vector3D &v);

            friend Vector3D operator *(const Vector3D &v, float scalar);

            float operator *(const Vector3D &rhs) const;

            Vector3D &operator *=(float scalar);

            Vector3D operator %(const Vector3D &rhs) const;

            Vector3D &operator %=(const Vector3D &rhs);

            friend std::ostream &operator<<(std::ostream &os, const Vector3D &obj);

            friend std::istream &operator>>(std::istream &is, Vector3D &obj);

        private:

            float _I = 0.f, _J = 0.f, _K = 0.f;
        };

}
<commit_msg>Added missing semicolons<commit_after>#pragma once

#include <iostream>

namespace RealRT
{

    class Vector3D
    {
        public:
            Vector3D(void) = default;

            Vector3D(float i, float j, float k);

            explicit Vector3D(const float *values);

            Vector3D(std::initializer_list<float> list);

            float I(void) const;

            float J(void) const;

            float K(void) const;

            Vector3D Add(const Vector3D &v) const;

            Vector3D Subtract(const Vector3D &v) const;

            Vector3D Normalize(void) const;

            float Distance(const Vector3D &rhs) const;

            float Magnitude(void) const;

            Vector3D Scale(float scalar) const;

            Vector3D Clip(float maxVal) const;

            Vector3D Weight(Vector3D dimWeights) const;

            float Dot(const Vector3D &rhs) const;

            Vector3D Cross(const Vector3D &rhs) const;

            float operator [](int i) const;

            bool operator ==(const Vector3D &rhs) const;

            bool operator !=(const Vector3D &rhs) const;

            bool operator <(const Vector3D &rhs) const;

            bool operator <=(const Vector3D &rhs) const;

            bool operator >(const Vector3D &rhs) const;

            bool operator >=(const Vector3D &rhs) const;

            Vector3D operator +(const Vector3D &rhs) const;

            Vector3D operator -(const Vector3D &rhs) const;

            Vector3D &operator +=(const Vector3D &rhs);

            Vector3D &operator -=(const Vector3D &rhs);

            friend Vector3D operator *(float scalar, const Vector3D &v);

            friend Vector3D operator *(const Vector3D &v, float scalar);

            float operator *(const Vector3D &rhs) const;

            Vector3D &operator *=(float scalar);

            Vector3D operator %(const Vector3D &rhs) const;

            Vector3D &operator %=(const Vector3D &rhs);

            friend std::ostream &operator<<(std::ostream &os, const Vector3D &obj);

            friend std::istream &operator>>(std::istream &is, Vector3D &obj);

        private:

            float _I = 0.f, _J = 0.f, _K = 0.f;
        };

}
<|endoftext|>


<commit_before>#include "Scripting.h"
#include "Utilities/ResourceManager.h"
#include "Sound/Sound.h"
#include "Graphics/Graphics.h"

namespace
{

int RM_Load ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    SDL_RWops* ptr = ResourceManager::OpenFile(file);
    if (ptr)
    {
        size_t len;
        void* data = ResourceManager::ReadFull(&len, ptr, 1);
        lua_pushlstring(L, (const char*)data, len);
        free(data);
        return 1;
    }
    else
    {
        lua_pushliteral(L, "file not found");
        return lua_error(L);
    }
}

int RM_FileExists ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    bool exists = ResourceManager::FileExists(file);
    lua_pushboolean(L, exists ? 1 : 0);
    return 1;
}

int RM_Write ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    size_t len;
    const char* data = luaL_checklstring(L, 2, &len);
    ResourceManager::WriteFile(file, (const void*)data, len);
    return 0;
}

luaL_Reg registryResourceManager[] =
{
    "file_exists", RM_FileExists,
    "load", RM_Load,
    "write", RM_Write,
    NULL, NULL
};

int GFX_BeginFrame ( lua_State* L )
{
	Graphics::BeginFrame();
	return 0;
}

int GFX_EndFrame ( lua_State* L )
{
	Graphics::EndFrame();
	return 0;
}

int GFX_SetCamera ( lua_State* L )
{
	float ll_x, ll_y, tr_x, tr_y, rot = 0.0f;
	int nargs = lua_gettop(L);
	ll_x = luaL_checknumber(L, 1);
	ll_y = luaL_checknumber(L, 2);
	tr_x = luaL_checknumber(L, 3);
	tr_y = luaL_checknumber(L, 4);
	if (nargs > 4)
		rot = luaL_checknumber(L, 5);
	Graphics::SetCamera(vec2(ll_x, ll_y), vec2(tr_x, tr_y), rot);
	return 0;
}

int GFX_DrawImage ( lua_State* L )
{
	const char* imgName;
	float loc_x, loc_y, size_x, size_y;
	imgName = luaL_checkstring(L, 1);
	loc_x = luaL_checknumber(L, 2);
	loc_y = luaL_checknumber(L, 3);
	size_x = luaL_checknumber(L, 4);
	size_y = luaL_checknumber(L, 5);
	Graphics::DrawImage(imgName, vec2(loc_x, loc_y), vec2(size_x, size_y));
	return 0;
}

int GFX_DrawSprite ( lua_State* L )
{
	const char* spritesheet;
	int sheet_x, sheet_y, nargs = lua_gettop(L);
	float loc_x, loc_y, size_x, size_y, rot = 0.0f;
	spritesheet = luaL_checkstring(L, 1);
	sheet_x = luaL_checkinteger(L, 2);
	sheet_y = luaL_checkinteger(L, 3);
	loc_x = luaL_checknumber(L, 4);
	loc_y = luaL_checknumber(L, 5);
	size_x = luaL_checknumber(L, 6);
	size_y = luaL_checknumber(L, 7);
	if (nargs > 7)
		rot = luaL_checknumber(L, 8);
	Graphics::DrawSprite(spritesheet, sheet_x, sheet_y, vec2(loc_x, loc_y), vec2(size_x, size_y), rot);
	return 0;
}

luaL_Reg registryGraphics[] =
{
	"begin_frame", GFX_BeginFrame,
	"end_frame", GFX_EndFrame,
	"set_camera", GFX_SetCamera,
	"draw_image", GFX_DrawImage,
	"draw_sprite", GFX_DrawSprite,
    NULL, NULL
};

int Sound_Play ( lua_State* L )
{
    const char* sound;
    float pan = 0.0f;
    float volume = 1.0f;
    int nargs = lua_gettop(L);
    sound = luaL_checkstring(L, 1);
    if (nargs > 1)
        volume = luaL_checknumber(L, 2);
    if (nargs > 2)
        pan = luaL_checknumber(L, 3);
    Sound::PlaySound(sound, volume, pan);
    return 0;
}

int Sound_PlayMusic ( lua_State* L )
{
    const char* mus = luaL_checkstring(L, 1);
    Sound::PlayMusic(mus);
    return 0;
}

int Sound_StopMusic ( lua_State* L )
{
    Sound::StopMusic();
    return 0;
}

luaL_Reg registrySound[] =
{
    "play", Sound_Play,
    "play_music", Sound_PlayMusic,
    "stop_music", Sound_StopMusic,
    NULL, NULL
};

}

void __LuaBind ( lua_State* L )
{
    luaL_register(L, "resource_manager", registryResourceManager);
    luaL_register(L, "graphics", registryGraphics);
    luaL_register(L, "sound", registrySound);
}
<commit_msg>Added Lua bindings to the mode manager system<commit_after>#include "Scripting.h"
#include "Utilities/ResourceManager.h"
#include "Sound/Sound.h"
#include "Graphics/Graphics.h"
#include "Modes/ModeManager.h"

namespace
{

int MM_Switch ( lua_State* L )
{
	const char* newmode = luaL_checkstring(L, 1);
	SwitchMode(std::string(newmode));
	return 0;
}

luaL_Reg registryModeManager[] =
{
	"switch", MM_Switch,
	NULL, NULL
};

int RM_Load ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    SDL_RWops* ptr = ResourceManager::OpenFile(file);
    if (ptr)
    {
        size_t len;
        void* data = ResourceManager::ReadFull(&len, ptr, 1);
        lua_pushlstring(L, (const char*)data, len);
        free(data);
        return 1;
    }
    else
    {
        lua_pushliteral(L, "file not found");
        return lua_error(L);
    }
}

int RM_FileExists ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    bool exists = ResourceManager::FileExists(file);
    lua_pushboolean(L, exists ? 1 : 0);
    return 1;
}

int RM_Write ( lua_State* L )
{
    const char* file = luaL_checkstring(L, 1);
    size_t len;
    const char* data = luaL_checklstring(L, 2, &len);
    ResourceManager::WriteFile(file, (const void*)data, len);
    return 0;
}

luaL_Reg registryResourceManager[] =
{
    "file_exists", RM_FileExists,
    "load", RM_Load,
    "write", RM_Write,
    NULL, NULL
};

int GFX_BeginFrame ( lua_State* L )
{
	Graphics::BeginFrame();
	return 0;
}

int GFX_EndFrame ( lua_State* L )
{
	Graphics::EndFrame();
	return 0;
}

int GFX_SetCamera ( lua_State* L )
{
	float ll_x, ll_y, tr_x, tr_y, rot = 0.0f;
	int nargs = lua_gettop(L);
	ll_x = luaL_checknumber(L, 1);
	ll_y = luaL_checknumber(L, 2);
	tr_x = luaL_checknumber(L, 3);
	tr_y = luaL_checknumber(L, 4);
	if (nargs > 4)
		rot = luaL_checknumber(L, 5);
	Graphics::SetCamera(vec2(ll_x, ll_y), vec2(tr_x, tr_y), rot);
	return 0;
}

int GFX_DrawImage ( lua_State* L )
{
	const char* imgName;
	float loc_x, loc_y, size_x, size_y;
	imgName = luaL_checkstring(L, 1);
	loc_x = luaL_checknumber(L, 2);
	loc_y = luaL_checknumber(L, 3);
	size_x = luaL_checknumber(L, 4);
	size_y = luaL_checknumber(L, 5);
	Graphics::DrawImage(imgName, vec2(loc_x, loc_y), vec2(size_x, size_y));
	return 0;
}

int GFX_DrawSprite ( lua_State* L )
{
	const char* spritesheet;
	int sheet_x, sheet_y, nargs = lua_gettop(L);
	float loc_x, loc_y, size_x, size_y, rot = 0.0f;
	spritesheet = luaL_checkstring(L, 1);
	sheet_x = luaL_checkinteger(L, 2);
	sheet_y = luaL_checkinteger(L, 3);
	loc_x = luaL_checknumber(L, 4);
	loc_y = luaL_checknumber(L, 5);
	size_x = luaL_checknumber(L, 6);
	size_y = luaL_checknumber(L, 7);
	if (nargs > 7)
		rot = luaL_checknumber(L, 8);
	Graphics::DrawSprite(spritesheet, sheet_x, sheet_y, vec2(loc_x, loc_y), vec2(size_x, size_y), rot);
	return 0;
}

luaL_Reg registryGraphics[] =
{
	"begin_frame", GFX_BeginFrame,
	"end_frame", GFX_EndFrame,
	"set_camera", GFX_SetCamera,
	"draw_image", GFX_DrawImage,
	"draw_sprite", GFX_DrawSprite,
    NULL, NULL
};

int Sound_Play ( lua_State* L )
{
    const char* sound;
    float pan = 0.0f;
    float volume = 1.0f;
    int nargs = lua_gettop(L);
    sound = luaL_checkstring(L, 1);
    if (nargs > 1)
        volume = luaL_checknumber(L, 2);
    if (nargs > 2)
        pan = luaL_checknumber(L, 3);
    Sound::PlaySound(sound, volume, pan);
    return 0;
}

int Sound_PlayMusic ( lua_State* L )
{
    const char* mus = luaL_checkstring(L, 1);
    Sound::PlayMusic(mus);
    return 0;
}

int Sound_StopMusic ( lua_State* L )
{
    Sound::StopMusic();
    return 0;
}

luaL_Reg registrySound[] =
{
    "play", Sound_Play,
    "play_music", Sound_PlayMusic,
    "stop_music", Sound_StopMusic,
    NULL, NULL
};

}

void __LuaBind ( lua_State* L )
{
	luaL_register(L, "mode_manager", registryModeManager);
    luaL_register(L, "resource_manager", registryResourceManager);
    luaL_register(L, "graphics", registryGraphics);
    luaL_register(L, "sound", registrySound);
}
<|endoftext|>