<commit_before>/*******************************************************************************
 * c7a/common/logger.hpp
 *
 * Simple and less simple logging classes.
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_COMMON_LOGGER_HEADER
#define C7A_COMMON_LOGGER_HEADER

#include <iostream>
#include <map>
#include <mutex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>

namespace c7a {
namespace common {

//! thread-id to name mapping for better multi-threaded log output
class ThreadNameDirectory
{
public:
    //! Defines a name for the current thread, only if no name was set
    //! previously
    void NameThisThread(const std::string& name) {
        std::lock_guard<std::mutex> lock(mutex_);
        thread_names_[std::this_thread::get_id()] = name;
    }

    //! Returns the name of the current thread or 'unknown [id]'
    std::string NameForThisThread() {
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = thread_names_.find(std::this_thread::get_id());
        if (it != thread_names_.end()) {
            return it->second;
        }
        std::ostringstream ss;
        ss << "unknown " << std::this_thread::get_id();
        return ss.str();
    }

private:
    std::map<std::thread::id, std::string> thread_names_;
    std::mutex mutex_;
};

//! access global singleton
ThreadNameDirectory & GetThreadDirectory();

/*!
 * A simple logging class which outputs a std::endl during destruction.
 * Depending on the real parameter the output may be suppressed.
 */
template <bool Active>
class Logger
{ };

template <>
class Logger<true>
{
protected:
    //! collector stream
    std::ostringstream oss_;

    //! the global mutex of logger and spacing logger
    static std::mutex mutex_;

    //! for access to mutex_
    template <bool Active>
    friend class SpacingLogger;

public:
    //! Real active flag
    static const bool active = true;

    Logger() {
        oss_ << "[" << GetThreadDirectory().NameForThisThread() << "] ";
    }

    //! output any type, including io manipulators
    template <typename AnyType>
    Logger& operator << (const AnyType& at) {
        oss_ << at;
        return *this;
    }

    //! destructor: output a newline
    ~Logger() {
        oss_ << "\n";
        // lock the global mutex of logger for serialized output in
        // multi-threaded programs.
        std::unique_lock<std::mutex> lock;
        std::cout << oss_.str();
        std::cout.flush();
    }
};

template <>
class Logger<false>
{
public:
    //! Real active flag
    static const bool active = false;

    //! output any type, including io manipulators
    template <typename AnyType>
    Logger& operator << (const AnyType&) {
        return *this;
    }
};

/*!
 * A logging class which outputs spaces between elements pushed via
 * operator<<. Depending on the real parameter the output may be suppressed.
 */
template <bool Real>
class SpacingLogger
{ };

template <>
class SpacingLogger<true>
{
protected:
    //! true until the first element it outputted.
    bool first_;

    //! collector stream
    std::ostringstream oss_;

public:
    //! Real active flag
    static const bool active = true;

    //! constructor: if real = false the output is suppressed.
    SpacingLogger()
        : first_(true) {
        oss_ << "[" << GetThreadDirectory().NameForThisThread() << "] ";
    }

    //! output any type, including io manipulators
    template <typename AnyType>
    SpacingLogger& operator << (const AnyType& at) {
        if (!first_) oss_ << ' ';
        else first_ = false;

        oss_ << at;

        return *this;
    }

    //! destructor: output a newline
    ~SpacingLogger() {
        oss_ << "\n";
        // lock the global mutex of logger for serialized output in
        // multi-threaded programs.
        std::unique_lock<std::mutex> lock;
        std::cout << oss_.str();
        std::cout.flush();
    }
};

template <>
class SpacingLogger<false>
{
public:
    //! Real active flag
    static const bool active = false;

    //! output any type, including io manipulators
    template <typename AnyType>
    SpacingLogger& operator << (const AnyType&) {
        return *this;
    }
};

// //! Default logging method: output if the local debug variable is true.
#define LOG ::c7a::common::Logger<debug>()

// //! Override default output: never or always output log.
#define LOG0 ::c7a::common::Logger<false>()
#define LOG1 ::c7a::common::Logger<true>()

// //! Explicitly specify the condition for logging
#define LOGC(cond) ::c7a::common::Logger<cond>()

//! Default logging method: output if the local debug variable is true.
#define sLOG ::c7a::common::SpacingLogger<debug>()

//! Override default output: never or always output log.
#define sLOG0 ::c7a::common::SpacingLogger<false>()
#define sLOG1 ::c7a::common::SpacingLogger<true>()

//! Explicitly specify the condition for logging
#define sLOGC(cond) ::c7a::common::SpacingLogger(cond)

/******************************************************************************/

//! Instead of abort(), throw the output the message via an exception.
#define die(msg)                                            \
    do {                                                    \
        std::ostringstream oss;                             \
        oss << msg << " @ " << __FILE__ << ':' << __LINE__; \
        throw std::runtime_error(oss.str());                \
    } while (0)

//! Check condition X and die miserably if false. Same as assert() except this
//! is also active in Release mode.
#define die_unless(X) \
    do { if (!(X)) die("Assertion \"" #X "\" failed"); } while (0)

//! Check that X == Y or die miserably, but output the values of X and Y for
//! better debugging.
#define die_unequal(X, Y)                         \
    do {                                          \
        if ((X) != (Y))                           \
            die("Inequality: " #X " != " #Y " : " \
                "\"" << "\" != \"" << Y << "\""); \
    } while (0)

} // namespace common
} // namespace c7a

#endif // !C7A_COMMON_LOGGER_HEADER

/******************************************************************************/
<commit_msg>Enumerate all messages printted by logger<commit_after>/*******************************************************************************
 * c7a/common/logger.hpp
 *
 * Simple and less simple logging classes.
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_COMMON_LOGGER_HEADER
#define C7A_COMMON_LOGGER_HEADER

#include <iostream>
#include <map>
#include <mutex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>
#include <iomanip>

namespace c7a {
namespace common {

//! thread-id to name mapping for better multi-threaded log output
class ThreadNameDirectory
{
public:
    //! Defines a name for the current thread, only if no name was set
    //! previously
    void NameThisThread(const std::string& name) {
        std::lock_guard<std::mutex> lock(mutex_);
        threads_[std::this_thread::get_id()] = StringCount(name, 0);
    }

    //! Returns the name of the current thread or 'unknown [id]'
    std::string NameForThisThread() {
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = threads_.find(std::this_thread::get_id());
        if (it != threads_.end()) {
            StringCount& sc = it->second;
            if (true) {
                std::ostringstream ss;
                // print "name #msg";
                ss << sc.first << ' '
                   << std::setfill('0') << std::setw(6) << sc.second++;
                return ss.str();
            }
            else {
                return sc.first;
            }
        }
        std::ostringstream ss;
        ss << "unknown " << std::this_thread::get_id();
        return ss.str();
    }

private:
    using StringCount = std::pair<std::string, size_t>;
    //! map thread id -> (name, message counter)
    std::map<std::thread::id, StringCount> threads_;
    std::mutex mutex_;
};

//! access global singleton
ThreadNameDirectory & GetThreadDirectory();

/*!
 * A simple logging class which outputs a std::endl during destruction.
 * Depending on the real parameter the output may be suppressed.
 */
template <bool Active>
class Logger
{ };

template <>
class Logger<true>
{
protected:
    //! collector stream
    std::ostringstream oss_;

    //! the global mutex of logger and spacing logger
    static std::mutex mutex_;

    //! for access to mutex_
    template <bool Active>
    friend class SpacingLogger;

public:
    //! Real active flag
    static const bool active = true;

    Logger() {
        oss_ << "[" << GetThreadDirectory().NameForThisThread() << "] ";
    }

    //! output any type, including io manipulators
    template <typename AnyType>
    Logger& operator << (const AnyType& at) {
        oss_ << at;
        return *this;
    }

    //! destructor: output a newline
    ~Logger() {
        oss_ << "\n";
        // lock the global mutex of logger for serialized output in
        // multi-threaded programs.
        std::unique_lock<std::mutex> lock;
        std::cout << oss_.str();
        std::cout.flush();
    }
};

template <>
class Logger<false>
{
public:
    //! Real active flag
    static const bool active = false;

    //! output any type, including io manipulators
    template <typename AnyType>
    Logger& operator << (const AnyType&) {
        return *this;
    }
};

/*!
 * A logging class which outputs spaces between elements pushed via
 * operator<<. Depending on the real parameter the output may be suppressed.
 */
template <bool Real>
class SpacingLogger
{ };

template <>
class SpacingLogger<true>
{
protected:
    //! true until the first element it outputted.
    bool first_;

    //! collector stream
    std::ostringstream oss_;

public:
    //! Real active flag
    static const bool active = true;

    //! constructor: if real = false the output is suppressed.
    SpacingLogger()
        : first_(true) {
        oss_ << "[" << GetThreadDirectory().NameForThisThread() << "] ";
    }

    //! output any type, including io manipulators
    template <typename AnyType>
    SpacingLogger& operator << (const AnyType& at) {
        if (!first_) oss_ << ' ';
        else first_ = false;

        oss_ << at;

        return *this;
    }

    //! destructor: output a newline
    ~SpacingLogger() {
        oss_ << "\n";
        // lock the global mutex of logger for serialized output in
        // multi-threaded programs.
        std::unique_lock<std::mutex> lock;
        std::cout << oss_.str();
        std::cout.flush();
    }
};

template <>
class SpacingLogger<false>
{
public:
    //! Real active flag
    static const bool active = false;

    //! output any type, including io manipulators
    template <typename AnyType>
    SpacingLogger& operator << (const AnyType&) {
        return *this;
    }
};

// //! Default logging method: output if the local debug variable is true.
#define LOG ::c7a::common::Logger<debug>()

// //! Override default output: never or always output log.
#define LOG0 ::c7a::common::Logger<false>()
#define LOG1 ::c7a::common::Logger<true>()

// //! Explicitly specify the condition for logging
#define LOGC(cond) ::c7a::common::Logger<cond>()

//! Default logging method: output if the local debug variable is true.
#define sLOG ::c7a::common::SpacingLogger<debug>()

//! Override default output: never or always output log.
#define sLOG0 ::c7a::common::SpacingLogger<false>()
#define sLOG1 ::c7a::common::SpacingLogger<true>()

//! Explicitly specify the condition for logging
#define sLOGC(cond) ::c7a::common::SpacingLogger(cond)

/******************************************************************************/

//! Instead of abort(), throw the output the message via an exception.
#define die(msg)                                            \
    do {                                                    \
        std::ostringstream oss;                             \
        oss << msg << " @ " << __FILE__ << ':' << __LINE__; \
        throw std::runtime_error(oss.str());                \
    } while (0)

//! Check condition X and die miserably if false. Same as assert() except this
//! is also active in Release mode.
#define die_unless(X) \
    do { if (!(X)) die("Assertion \"" #X "\" failed"); } while (0)

//! Check that X == Y or die miserably, but output the values of X and Y for
//! better debugging.
#define die_unequal(X, Y)                         \
    do {                                          \
        if ((X) != (Y))                           \
            die("Inequality: " #X " != " #Y " : " \
                "\"" << "\" != \"" << Y << "\""); \
    } while (0)

} // namespace common
} // namespace c7a

#endif // !C7A_COMMON_LOGGER_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>#include "Halide.h"
#include <stdio.h>
#include <future>

using namespace Halide;

static std::atomic<int> foo;

int main(int argc, char **argv) {
    // Test if the compiler itself is thread-safe. This test is
    // intended to be run in a thread-sanitizer.
    std::vector<std::future<void>> futures;
    for (int i = 0; i < 1000; i++) {
        futures.emplace_back(std::async(std::launch::async, []{
            Func f;
            Var x;
            f(x) = x;
            f.realize(100);
        }));
    }

    for (auto &f : futures) {
        f.wait();
    }

    printf("Success!\n");

    return 0;
}
<commit_msg>Use a pool of 8 threads.<commit_after>#include "Halide.h"
#include <stdio.h>
#include <thread>

using namespace Halide;

int main(int argc, char **argv) {
    // Test if the compiler itself is thread-safe. This test is
    // intended to be run in a thread-sanitizer.

    // std::thread has implementation-dependent behavior; some implementations
    // may refuse to create an arbitrary number. So let's create a smallish
    // number (8) and have each one do enough work that contention is likely
    // to be encountered.
    constexpr int total_iters = 1024;
    constexpr int num_threads = 8;

    std::vector<std::thread> threads;
    for (int i = 0; i < num_threads; i++) {
        threads.emplace_back([]{
            for (int i = 0; i < (total_iters / num_threads); i++) {
                Func f;
                Var x;
                f(x) = x;
                f.realize(100);
            }
        });
    }

    for (auto &t : threads) {
        t.join();
    }

    printf("Success!\n");

    return 0;
}
<|endoftext|>


<commit_before>#include "extern.h"
#include "colorstring.h"
#include "configuration.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

size_t dummyWriter(void *, size_t size, size_t nmemb, void *){
  return size*nmemb;
}

bool twitterShout(sstring from, sstring msg)
{
  CURL *curl;
  CURLcode res;

  if(gamePort!=PROD_GAMEPORT)
    return false;

  struct curl_httppost *formpost=NULL;
  struct curl_httppost *lastptr=NULL;
  struct curl_slist *headerlist=NULL;
  static const char buf[] = "Expect:";

  msg=stripColorCodes(msg);

  curl_global_init(CURL_GLOBAL_ALL);

  curl_formadd(&formpost, &lastptr,
	       CURLFORM_COPYNAME, "status",
	       CURLFORM_COPYCONTENTS,
	       (format("%s: %s")% from% msg).str().c_str(),
	       CURLFORM_END);

  curl = curl_easy_init();
  headerlist = curl_slist_append(headerlist, buf);

  curl_easy_setopt(curl, CURLOPT_URL,
		   "http://twitter.com/statuses/update.xml");
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
  curl_easy_setopt(curl, CURLOPT_USERPWD, "sneezymud:kegenlgn");
  //  curl_easy_setopt(curl, CURLOPT_USERNAME, "sneezymud");
  //  curl_easy_setopt(curl, CURLOPT_PASSWORD, "kegenlgn");
  curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, dummyWriter);

  res = curl_easy_perform(curl);

  curl_easy_cleanup(curl);
  curl_formfree(formpost);
  curl_slist_free_all (headerlist);

  if(res){
    vlogf(LOG_PEEL, format("curl failed: %i") % res);
  }

  return true;

}

<commit_msg>stripped color codes from shouter name<commit_after>#include "extern.h"
#include "colorstring.h"
#include "configuration.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

size_t dummyWriter(void *, size_t size, size_t nmemb, void *){
  return size*nmemb;
}

bool twitterShout(sstring from, sstring msg)
{
  CURL *curl;
  CURLcode res;

  if(gamePort!=PROD_GAMEPORT)
    return false;

  struct curl_httppost *formpost=NULL;
  struct curl_httppost *lastptr=NULL;
  struct curl_slist *headerlist=NULL;
  static const char buf[] = "Expect:";

  from=stripColorCodes(from);
  msg=stripColorCodes(msg);

  curl_global_init(CURL_GLOBAL_ALL);

  curl_formadd(&formpost, &lastptr,
	       CURLFORM_COPYNAME, "status",
	       CURLFORM_COPYCONTENTS,
	       (format("%s: %s")% from% msg).str().c_str(),
	       CURLFORM_END);

  curl = curl_easy_init();
  headerlist = curl_slist_append(headerlist, buf);

  curl_easy_setopt(curl, CURLOPT_URL,
		   "http://twitter.com/statuses/update.xml");
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
  curl_easy_setopt(curl, CURLOPT_USERPWD, "sneezymud:kegenlgn");
  //  curl_easy_setopt(curl, CURLOPT_USERNAME, "sneezymud");
  //  curl_easy_setopt(curl, CURLOPT_PASSWORD, "kegenlgn");
  curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, dummyWriter);

  res = curl_easy_perform(curl);

  curl_easy_cleanup(curl);
  curl_formfree(formpost);
  curl_slist_free_all (headerlist);

  if(res){
    vlogf(LOG_PEEL, format("curl failed: %i") % res);
  }

  return true;

}

<|endoftext|>


<commit_before>#include "application.hpp"
#include <SDL2/SDL.h>
#include <stdexcept>

Application *Application::instance_ = nullptr;

Application::Application(int &argc, char **argv)
{
    if (instance_ != nullptr)
        throw std::runtime_error("The program can have only one instance of Application");
    instance_ = this;
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
        throw std::runtime_error("SDL_Init Error: " + std::string(SDL_GetError()));
}

Application::~Application()
{
    SDL_Quit();
    instance_ = nullptr;
}

int Application::exec()
{
    bool done = false;
    while (!done)
    {
        SDL_Event e;
        while (SDL_PollEvent(&e))
        {
            switch (e.type)
            {
            case SDL_QUIT:
                done = true;
                break;
            }
        }
    }
    return 0;
}

Application *Application::instance()
{
    return instance_;
}

void Application::addWidget(Widget *)
{

}

void Application::removeWidget(Widget *)
{

}
<commit_msg>Fix build for Mac OS X<commit_after>#include "application.hpp"
#include <SDL2/SDL.h>
#include <stdexcept>
#include <string>

Application *Application::instance_ = nullptr;

Application::Application(int &argc, char **argv)
{
    if (instance_ != nullptr)
        throw std::runtime_error("The program can have only one instance of Application");
    instance_ = this;
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
        throw std::runtime_error("SDL_Init Error: " + std::string(SDL_GetError()));
}

Application::~Application()
{
    SDL_Quit();
    instance_ = nullptr;
}

int Application::exec()
{
    bool done = false;
    while (!done)
    {
        SDL_Event e;
        while (SDL_PollEvent(&e))
        {
            switch (e.type)
            {
            case SDL_QUIT:
                done = true;
                break;
            }
        }
    }
    return 0;
}

Application *Application::instance()
{
    return instance_;
}

void Application::addWidget(Widget *)
{

}

void Application::removeWidget(Widget *)
{

}
<|endoftext|>


<commit_before>#include <tracking.h>
#include <pidData.h>
#include <main.h>
#include <spiMaster.h>

/* *** Private variables *** */

mirrorOutput lastPidOut;
adcSample lastAdcRead;
volatile unsigned samplesProcessed = 0;
volatile bool enteringTracking = false;
volatile bool lockedOn = false;
volatile uint64_t numLockedOn = 0;
volatile uint64_t totalPowerReceivedBeforeIncoherent = 0;
volatile uint64_t totalPowerReceived = 0;
const uint64_t maxPower = 1ULL << 32;

void sendOutput(mirrorOutput& output);

void trackingSetup() {
    // Begin dma transaction
    pidDataSetup();
}

void enterTracking() {
    enteringTracking = true; // Set this flag that we want to enter tracking mode, but the real setup work is done in firstLoopTracking()
    // This is because enterTracking() is called in an interrupt before the main loop is finished doing its thing
}

void firstLoopTracking() {
    noInterrupts();
    numLockedOn = 0;
    samplesProcessed = 0;
    lockedOn = false;
    totalPowerReceivedBeforeIncoherent = 0;
    totalPowerReceived = 0;
    interrupts();

    debugPrintf("About to clear dma: offset is (this might be high) %d\n", adcGetOffset());
    adcStartSampling();
    assert(!adcSampleReady());
    debugPrintf("Cleared dma: offset is (this should be <= 4) %d\n", adcGetOffset());
    assert(!enteringTracking);
    enterPidData();
    debugPrintf("Entered tracking\n");
    debugPrintf("Offset %d\n", adcGetOffset());
}

void leaveTracking() {
    leavePidData();
    noInterrupts();
    enteringTracking = false;
    numLockedOn = 0;
    totalPowerReceivedBeforeIncoherent = 0;
    totalPowerReceived = 0;
    samplesProcessed = 0;
    interrupts();
}

void incoherentProcess(const volatile adcSample& s, adcSample& output) {
    output.copy(s);
}

void pidProcess(const volatile adcSample& s) {
    lastAdcRead.copy(s);
    totalPowerReceivedBeforeIncoherent += s.axis1;
    totalPowerReceivedBeforeIncoherent += s.axis2;
    totalPowerReceivedBeforeIncoherent += s.axis3;
    totalPowerReceivedBeforeIncoherent += s.axis4;

    adcSample incoherentOutput;
    incoherentProcess(s, incoherentOutput);
    lockedOn = false;
    if (lockedOn) {
        numLockedOn++;
    }
    totalPowerReceived += incoherentOutput.axis1;
    totalPowerReceived += incoherentOutput.axis2;
    totalPowerReceived += incoherentOutput.axis3;
    totalPowerReceived += incoherentOutput.axis4;

    mirrorOutput out;
    out.x_low = incoherentOutput.axis1; // TODO: REMOVE
    lastPidOut.copy(out);
    pidSample samplePid(s, incoherentOutput, out);
    recordPid(samplePid);
    sendOutput(out);
    samplesProcessed++;
}

void taskTracking() {
    if (enteringTracking) {
        enteringTracking = false;
        firstLoopTracking();
    }

    if (micros() % 100 == 0) {
        assert(adcGetOffset() < 2); // We should be able to keep up with data generation
        if (adcGetOffset() >= 2) {
            debugPrintf("Offset is too high! It is %d\n", adcGetOffset());
        }
    }
    if (adcSampleReady()) {
        volatile adcSample s = *adcGetSample();
        //s.axis1 = samplesProcessed; // TODO: remove
        pidProcess(s);
    }
    taskPidData();
}

void trackingHeartbeat() {
    pidDataHeartbeat();
    char lastAdcReadBuf[40];
    char lastPidOutBuf[40];
    lastAdcRead.toString(lastAdcReadBuf, 40);
    lastPidOut.toString(lastPidOutBuf, 40);
    debugPrintf("Last pid output %s, last adc read %s, total power in %u (percent of max), after incoherent %u,  samples processed %u\n", lastPidOutBuf, lastAdcReadBuf, (uint32_t) (totalPowerReceivedBeforeIncoherent / maxPower / 4), (uint32_t) (totalPowerReceived / maxPower / 4), samplesProcessed);
    int a = lastAdcRead.axis3/4;
    int b = lastAdcRead.axis4/4;
    int c = lastAdcRead.axis1/4;
    int d = lastAdcRead.axis2/4;
    debugPrintf("X %d Y %d\n", (a + d - b - c), a + b - c - d);
}

void enterCalibration() {
    enterTracking();
}

void leaveCalibration() {
    leaveTracking();
}

void taskCalibration() {
    taskTracking();
}

void calibrationHeartbeat() {
    trackingHeartbeat();
}
<commit_msg>testing git account permissions<commit_after>#include <tracking.h>
#include <pidData.h>
#include <main.h>
#include <spiMaster.h>

/* *** Private variables *** */

mirrorOutput lastPidOut;
adcSample lastAdcRead;
volatile unsigned samplesProcessed = 0;
volatile bool enteringTracking = false;
volatile bool lockedOn = false;
volatile uint64_t numLockedOn = 0;
volatile uint64_t totalPowerReceivedBeforeIncoherent = 0;
volatile uint64_t totalPowerReceived = 0;
const uint64_t maxPower = 1ULL << 32;

void sendOutput(mirrorOutput& output);

void trackingSetup() {
    // Begin dma transaction
    pidDataSetup();
}

void enterTracking() {
    enteringTracking = true; // Set this flag that we want to enter tracking mode, but the real setup work is done in firstLoopTracking()
    // This is because enterTracking() is called in an interrupt before the main loop is finished doing its thing
}

void firstLoopTracking() {
    noInterrupts();
    numLockedOn = 0;
    samplesProcessed = 0;
    lockedOn = false;
    totalPowerReceivedBeforeIncoherent = 0;
    totalPowerReceived = 0;
    interrupts();

    debugPrintf("About to clear dma: offset is (this might be high) %d\n", adcGetOffset());
    adcStartSampling();
    assert(!adcSampleReady());
    debugPrintf("Cleared dma: offset is (this should be <= 4) %d\n", adcGetOffset());
    assert(!enteringTracking);
    enterPidData();
    debugPrintf("Entered tracking\n");
    debugPrintf("Offset %d\n", adcGetOffset());
}

void leaveTracking() {
    leavePidData();
    noInterrupts();
    enteringTracking = false;
    numLockedOn = 0;
    totalPowerReceivedBeforeIncoherent = 0;
    totalPowerReceived = 0;
    samplesProcessed = 0;
    interrupts();
}

void incoherentProcess(const volatile adcSample& s, adcSample& output) {
    output.copy(s);
}

void pidProcess(const volatile adcSample& s) {
    lastAdcRead.copy(s);
    totalPowerReceivedBeforeIncoherent += s.axis1;
    totalPowerReceivedBeforeIncoherent += s.axis2;
    totalPowerReceivedBeforeIncoherent += s.axis3;
    totalPowerReceivedBeforeIncoherent += s.axis4;

    adcSample incoherentOutput;
    incoherentProcess(s, incoherentOutput);
    lockedOn = false;
    if (lockedOn) {
        numLockedOn++;
    }
    totalPowerReceived += incoherentOutput.axis1;
    totalPowerReceived += incoherentOutput.axis2;
    totalPowerReceived += incoherentOutput.axis3;
    totalPowerReceived += incoherentOutput.axis4;

    mirrorOutput out;
    out.x_low = incoherentOutput.axis1; //  TODO: REMOVE
    lastPidOut.copy(out);
    pidSample samplePid(s, incoherentOutput, out);
    recordPid(samplePid);
    sendOutput(out);
    samplesProcessed++;
}

void taskTracking() {
    if (enteringTracking) {
        enteringTracking = false;
        firstLoopTracking();
    }

    if (micros() % 100 == 0) {
        assert(adcGetOffset() < 2); // We should be able to keep up with data generation
        if (adcGetOffset() >= 2) {
            debugPrintf("Offset is too high! It is %d\n", adcGetOffset());
        }
    }
    if (adcSampleReady()) {
        volatile adcSample s = *adcGetSample();
        //s.axis1 = samplesProcessed; // TODO: remove
        pidProcess(s);
    }
    taskPidData();
}

void trackingHeartbeat() {
    pidDataHeartbeat();
    char lastAdcReadBuf[40];
    char lastPidOutBuf[40];
    lastAdcRead.toString(lastAdcReadBuf, 40);
    lastPidOut.toString(lastPidOutBuf, 40);
    debugPrintf("Last pid output %s, last adc read %s, total power in %u (percent of max), after incoherent %u,  samples processed %u\n", lastPidOutBuf, lastAdcReadBuf, (uint32_t) (totalPowerReceivedBeforeIncoherent / maxPower / 4), (uint32_t) (totalPowerReceived / maxPower / 4), samplesProcessed);
    int a = lastAdcRead.axis3/4;
    int b = lastAdcRead.axis4/4;
    int c = lastAdcRead.axis1/4;
    int d = lastAdcRead.axis2/4;
    debugPrintf("X %d Y %d\n", (a + d - b - c), a + b - c - d);
}

void enterCalibration() {
    enterTracking();
}

void leaveCalibration() {
    leaveTracking();
}

void taskCalibration() {
    taskTracking();
}

void calibrationHeartbeat() {
    trackingHeartbeat();
}
<|endoftext|>


<commit_before>#ifndef COUNT_NEW_HPP
#define COUNT_NEW_HPP

# include <cstdlib>
# include <cassert>
# include <new>

#if  __has_feature(address_sanitizer) \
  || __has_feature(memory_sanitizer)
#define DISABLE_NEW_COUNT
#endif

class MemCounter
{
public:
    // Make MemCounter super hard to accidentally construct or copy.
    class MemCounterCtorArg_ {};
    explicit MemCounter(MemCounterCtorArg_) {}

private:
    MemCounter(MemCounter const &);
    MemCounter & operator=(MemCounter const &);

public:
    // All checks return true when disable_checking is enabled.
    static const bool disable_checking;

    int outstanding_new = 0;
    int new_called = 0;
    int delete_called = 0;
    int last_new_size = 0;

    int outstanding_array_new = 0;
    int new_array_called = 0;
    int delete_array_called = 0;
    int last_new_array_size = 0;

public:
    void newCalled(std::size_t s)
    {
        assert(s);
        ++new_called;
        ++outstanding_new;
        last_new_size = s;
    }

    void deleteCalled(void * p)
    {
        assert(p);
        --outstanding_new;
        ++delete_called;
    }

    void newArrayCalled(std::size_t s)
    {
        assert(s);
        ++outstanding_array_new;
        ++new_array_called;
        last_new_array_size = s;
    }

    void deleteArrayCalled(void * p)
    {
        assert(p);
        --outstanding_array_new;
        ++delete_array_called;
    }

    void reset()
    {
        outstanding_new = 0;
        new_called = 0;
        delete_called = 0;
        last_new_size = 0;

        outstanding_array_new = 0;
        new_array_called = 0;
        delete_array_called = 0;
        last_new_array_size = 0;
    }

public:
    bool checkOutstandingNewEq(int n) const
    {
        return disable_checking || n == outstanding_new;
    }

    bool checkOutstandingNewNotEq(int n) const
    {
        return disable_checking || n != outstanding_new;
    }

    bool checkNewCalledEq(int n) const
    {
        return disable_checking || n == new_called;
    }

    bool checkNewCalledNotEq(int n) const
    {
        return disable_checking || n != new_called;
    }

    bool checkDeleteCalledEq(int n) const
    {
        return disable_checking || n == delete_called;
    }

    bool checkDeleteCalledNotEq(int n) const
    {
        return disable_checking || n != delete_called;
    }

    bool checkLastNewSizeEq(int n) const
    {
        return disable_checking || n == last_new_size;
    }

    bool checkLastNewSizeNotEq(int n) const
    {
        return disable_checking || n != last_new_size;
    }

    bool checkOutstandingArrayNewEq(int n) const
    {
        return disable_checking || n == outstanding_array_new;
    }

    bool checkOutstandingArrayNewNotEq(int n) const
    {
        return disable_checking || n != outstanding_array_new;
    }

    bool checkNewArrayCalledEq(int n) const
    {
        return disable_checking || n == new_array_called;
    }

    bool checkNewArrayCalledNotEq(int n) const
    {
        return disable_checking || n != new_array_called;
    }

    bool checkDeleteArrayCalledEq(int n) const
    {
        return disable_checking || n == delete_array_called;
    }

    bool checkDeleteArrayCalledNotEq(int n) const
    {
        return disable_checking || n != delete_array_called;
    }

    bool checkLastNewArraySizeEq(int n) const
    {
        return disable_checking || n == last_new_array_size;
    }

    bool checkLastNewArraySizeNotEq(int n) const
    {
        return disable_checking || n != last_new_array_size;
    }
};

#ifdef DISABLE_NEW_COUNT
  const bool MemCounter::disable_checking = true;
#else
  const bool MemCounter::disable_checking = false;
#endif

MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));

#ifndef DISABLE_NEW_COUNT
void* operator new(std::size_t s) throw(std::bad_alloc)
{
    globalMemCounter.newCalled(s);
    return std::malloc(s);
}

void  operator delete(void* p) throw()
{
    globalMemCounter.deleteCalled(p);
    std::free(p);
}

void* operator new[](std::size_t s) throw(std::bad_alloc)
{
    globalMemCounter.newArrayCalled(s);
    return operator new(s);
}

void operator delete[](void* p) throw()
{
    globalMemCounter.deleteArrayCalled(p);
    operator delete(p);
}

#endif // DISABLE_NEW_COUNT

#endif /* COUNT_NEW_HPP */
<commit_msg>Ensure __has_feature is defined in test/support/count_new.hpp<commit_after>#ifndef COUNT_NEW_HPP
#define COUNT_NEW_HPP

# include <cstdlib>
# include <cassert>
# include <new>

#ifndef __has_feature
#  define __has_feature(x)
#endif

#if  __has_feature(address_sanitizer) \
  || __has_feature(memory_sanitizer)
#define DISABLE_NEW_COUNT
#endif

class MemCounter
{
public:
    // Make MemCounter super hard to accidentally construct or copy.
    class MemCounterCtorArg_ {};
    explicit MemCounter(MemCounterCtorArg_) {}

private:
    MemCounter(MemCounter const &);
    MemCounter & operator=(MemCounter const &);

public:
    // All checks return true when disable_checking is enabled.
    static const bool disable_checking;

    int outstanding_new = 0;
    int new_called = 0;
    int delete_called = 0;
    int last_new_size = 0;

    int outstanding_array_new = 0;
    int new_array_called = 0;
    int delete_array_called = 0;
    int last_new_array_size = 0;

public:
    void newCalled(std::size_t s)
    {
        assert(s);
        ++new_called;
        ++outstanding_new;
        last_new_size = s;
    }

    void deleteCalled(void * p)
    {
        assert(p);
        --outstanding_new;
        ++delete_called;
    }

    void newArrayCalled(std::size_t s)
    {
        assert(s);
        ++outstanding_array_new;
        ++new_array_called;
        last_new_array_size = s;
    }

    void deleteArrayCalled(void * p)
    {
        assert(p);
        --outstanding_array_new;
        ++delete_array_called;
    }

    void reset()
    {
        outstanding_new = 0;
        new_called = 0;
        delete_called = 0;
        last_new_size = 0;

        outstanding_array_new = 0;
        new_array_called = 0;
        delete_array_called = 0;
        last_new_array_size = 0;
    }

public:
    bool checkOutstandingNewEq(int n) const
    {
        return disable_checking || n == outstanding_new;
    }

    bool checkOutstandingNewNotEq(int n) const
    {
        return disable_checking || n != outstanding_new;
    }

    bool checkNewCalledEq(int n) const
    {
        return disable_checking || n == new_called;
    }

    bool checkNewCalledNotEq(int n) const
    {
        return disable_checking || n != new_called;
    }

    bool checkDeleteCalledEq(int n) const
    {
        return disable_checking || n == delete_called;
    }

    bool checkDeleteCalledNotEq(int n) const
    {
        return disable_checking || n != delete_called;
    }

    bool checkLastNewSizeEq(int n) const
    {
        return disable_checking || n == last_new_size;
    }

    bool checkLastNewSizeNotEq(int n) const
    {
        return disable_checking || n != last_new_size;
    }

    bool checkOutstandingArrayNewEq(int n) const
    {
        return disable_checking || n == outstanding_array_new;
    }

    bool checkOutstandingArrayNewNotEq(int n) const
    {
        return disable_checking || n != outstanding_array_new;
    }

    bool checkNewArrayCalledEq(int n) const
    {
        return disable_checking || n == new_array_called;
    }

    bool checkNewArrayCalledNotEq(int n) const
    {
        return disable_checking || n != new_array_called;
    }

    bool checkDeleteArrayCalledEq(int n) const
    {
        return disable_checking || n == delete_array_called;
    }

    bool checkDeleteArrayCalledNotEq(int n) const
    {
        return disable_checking || n != delete_array_called;
    }

    bool checkLastNewArraySizeEq(int n) const
    {
        return disable_checking || n == last_new_array_size;
    }

    bool checkLastNewArraySizeNotEq(int n) const
    {
        return disable_checking || n != last_new_array_size;
    }
};

#ifdef DISABLE_NEW_COUNT
  const bool MemCounter::disable_checking = true;
#else
  const bool MemCounter::disable_checking = false;
#endif

MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));

#ifndef DISABLE_NEW_COUNT
void* operator new(std::size_t s) throw(std::bad_alloc)
{
    globalMemCounter.newCalled(s);
    return std::malloc(s);
}

void  operator delete(void* p) throw()
{
    globalMemCounter.deleteCalled(p);
    std::free(p);
}

void* operator new[](std::size_t s) throw(std::bad_alloc)
{
    globalMemCounter.newArrayCalled(s);
    return operator new(s);
}

void operator delete[](void* p) throw()
{
    globalMemCounter.deleteArrayCalled(p);
    operator delete(p);
}

#endif // DISABLE_NEW_COUNT

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


<commit_before>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/alert_types.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;
using boost::filesystem::exists;

void test_swarm()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48010, 49000), "0.0.0.0", 0);
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49010, 50000), "0.0.0.0", 0);
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50010, 51000), "0.0.0.0", 0);

	ses1.set_severity_level(alert::debug);
	ses2.set_severity_level(alert::debug);
	ses3.set_severity_level(alert::debug);

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 100000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses1.set_max_uploads(1);
	ses2.set_download_rate_limit(int(rate_limit / 5));
	ses3.set_download_rate_limit(int(rate_limit / 5));
	ses2.set_upload_rate_limit(int(rate_limit / 10));
	ses3.set_upload_rate_limit(int(rate_limit / 10));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	settings.auto_upload_slots = true;
	settings.auto_upload_slots_rate_based = false;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false, true, "_unchoke");

	session_status st = ses1.status();
	TEST_CHECK(st.allowed_upload_slots == 1);
	for (int i = 0; i < 50; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		st = ses1.status();
		if (st.allowed_upload_slots >= 2) break;

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << " " << st.allowed_upload_slots << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		test_sleep(1000);
	}

	TEST_CHECK(st.allowed_upload_slots == 2);

	// make sure the files are deleted
	ses1.remove_torrent(tor1, session::delete_files);
	ses2.remove_torrent(tor2, session::delete_files);
	ses3.remove_torrent(tor3, session::delete_files);
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1_unchoke"); } catch (std::exception&) {}
	try { remove_all("./tmp2_unchoke"); } catch (std::exception&) {}
	try { remove_all("./tmp3_unchoke"); } catch (std::exception&) {}

	test_swarm();

	test_sleep(2000);
	TEST_CHECK(!exists("./tmp1_unchoke/temporary"));
	TEST_CHECK(!exists("./tmp2_unchoke/temporary"));
	TEST_CHECK(!exists("./tmp3_unchoke/temporary"));

	remove_all("./tmp1_unchoke");
	remove_all("./tmp2_unchoke");
	remove_all("./tmp3_unchoke");

	return 0;
}

<commit_msg>fixed auto unchoke test<commit_after>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/alert_types.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;
using boost::filesystem::exists;

void test_swarm()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48010, 49000), "0.0.0.0", 0);
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49010, 50000), "0.0.0.0", 0);
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50010, 51000), "0.0.0.0", 0);

	ses1.set_severity_level(alert::debug);
	ses2.set_severity_level(alert::debug);
	ses3.set_severity_level(alert::debug);

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 100000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses1.set_max_uploads(1);
	ses2.set_download_rate_limit(int(rate_limit / 5));
	ses3.set_download_rate_limit(int(rate_limit / 5));
	ses2.set_upload_rate_limit(int(rate_limit / 10));
	ses3.set_upload_rate_limit(int(rate_limit / 10));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	settings.auto_upload_slots = true;
	settings.auto_upload_slots_rate_based = false;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false, true, "_unchoke");

	session_status st = ses1.status();
	TEST_CHECK(st.allowed_upload_slots == 1);
	for (int i = 0; i < 50; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		st = ses1.status();
		std::cerr << st.allowed_upload_slots << " ";
		if (st.allowed_upload_slots >= 2) break;

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << " " << st.allowed_upload_slots << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		test_sleep(1000);
	}

	TEST_CHECK(st.allowed_upload_slots >= 2);

	// make sure the files are deleted
	ses1.remove_torrent(tor1, session::delete_files);
	ses2.remove_torrent(tor2, session::delete_files);
	ses3.remove_torrent(tor3, session::delete_files);
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1_unchoke"); } catch (std::exception&) {}
	try { remove_all("./tmp2_unchoke"); } catch (std::exception&) {}
	try { remove_all("./tmp3_unchoke"); } catch (std::exception&) {}

	test_swarm();

	test_sleep(2000);
	TEST_CHECK(!exists("./tmp1_unchoke/temporary"));
	TEST_CHECK(!exists("./tmp2_unchoke/temporary"));
	TEST_CHECK(!exists("./tmp3_unchoke/temporary"));

	remove_all("./tmp1_unchoke");
	remove_all("./tmp2_unchoke");
	remove_all("./tmp3_unchoke");

	return 0;
}

<|endoftext|>


<commit_before>//Study Area
#include "studyarea.h"
#include "flashcard.h"
#include <QtWidgets>
#include <QtGui>

StudyArea::StudyArea(Deck *_deck, QStackedWidget* pages_in, DeckMenu* parent_in)
{
    scores = new QLabel;
    grid = new QGridLayout;
    parent = parent_in;
    deck = _deck;
    pages = pages_in;
    curCard = _deck->getTop();
    grid->addWidget(curCard,1,0,1,3);

    QPushButton *back = new QPushButton("Back to Deck Selection");
    connect(back, SIGNAL(clicked()), this, SLOT(goBack()));
    grid->addWidget(back,0,0,1,1);

    QPushButton *right = new QPushButton;
    right->setFixedSize(65,65);
    QPixmap pm(":/green_check.png");
    pm = pm.scaled(65, 65, Qt::KeepAspectRatio);
    QIcon ic(pm);
    right->setIcon(ic);
    QSize iconSize(65, 65);
    right->setIconSize(iconSize);
    grid->addWidget(right,2,0,1,1,Qt::AlignLeft);
    connect(right,SIGNAL(clicked()),this,SLOT(correct()));

    QPushButton *wrong = new QPushButton;
    wrong->setFixedSize(65,65);
    QPixmap pm2(":/red_x.png");
    pm2 = pm2.scaled(65, 65, Qt::KeepAspectRatio);
    QIcon ic2(pm2);
    wrong->setIcon(ic2);
    wrong->setIconSize(iconSize);
    grid->addWidget(wrong,2,2,1,1,Qt::AlignRight);
    connect(wrong,SIGNAL(clicked()),this,SLOT(incorrect()));

    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    grid->addWidget(scores,2,1,1,1,Qt::AlignCenter);

    grid->setRowStretch(0,0);
    grid->setRowStretch(1,1);
    grid->setRowStretch(2,0);
    this->setLayout(grid);
}

StudyArea::~StudyArea()
{

}

void StudyArea::correct()
{
    curCard->correct();
    deck->shuffle();
    deck->getDeckScore();
    grid->removeWidget(curCard);
    curCard->hide();
    if (!curCard->isFront()) curCard->Flip();
    curCard = deck->getTop();
    grid->addWidget(curCard,1,0,1,3);
    curCard->show();
    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    deck->autoSave();

}

void StudyArea::incorrect()
{
    curCard->incorrect();
    deck->shuffle();
    grid->removeWidget(curCard);
    curCard->hide();
    if (!curCard->isFront()) curCard->Flip();
    curCard = deck->getTop();
    grid->addWidget(curCard,1,0,1,3);
    curCard->show();
    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    deck->autoSave();
}

void StudyArea::goBack()
{
    parent->updateMenu();
    int nextIndex = pages->currentIndex()-1;
    pages->removeWidget(pages->currentWidget());
    pages->setCurrentIndex(nextIndex);
}
<commit_msg>Tooltips in study area<commit_after>//Study Area
#include "studyarea.h"
#include "flashcard.h"
#include <QtWidgets>
#include <QtGui>

StudyArea::StudyArea(Deck *_deck, QStackedWidget* pages_in, DeckMenu* parent_in)
{
    scores = new QLabel;
    grid = new QGridLayout;
    parent = parent_in;
    deck = _deck;
    pages = pages_in;
    curCard = _deck->getTop();
    curCard->setToolTip("Click to flip!");
    grid->addWidget(curCard,1,0,1,3);

    QPushButton *back = new QPushButton("Back");
    back->setShortcut(QKeySequence(" "));
    connect(back, SIGNAL(clicked()), this, SLOT(goBack()));
    grid->addWidget(back,0,0,1,1);

    QPushButton *right = new QPushButton;
    right->setToolTip("Click if you knew the answer");
    right->setFixedSize(65,65);
    QPixmap pm(":/green_check.png");
    pm = pm.scaled(65, 65, Qt::KeepAspectRatio);
    QIcon ic(pm);
    right->setIcon(ic);
    QSize iconSize(65, 65);
    right->setIconSize(iconSize);
    grid->addWidget(right,2,0,1,1,Qt::AlignLeft);
    connect(right,SIGNAL(clicked()),this,SLOT(correct()));

    QPushButton *wrong = new QPushButton;
    wrong->setToolTip("Click if you didn't know the answer.");
    wrong->setFixedSize(65,65);
    QPixmap pm2(":/red_x.png");
    pm2 = pm2.scaled(65, 65, Qt::KeepAspectRatio);
    QIcon ic2(pm2);
    wrong->setIcon(ic2);
    wrong->setIconSize(iconSize);
    grid->addWidget(wrong,2,2,1,1,Qt::AlignRight);
    connect(wrong,SIGNAL(clicked()),this,SLOT(incorrect()));

    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    grid->addWidget(scores,2,1,1,1,Qt::AlignCenter);

    grid->setRowStretch(0,0);
    grid->setRowStretch(1,1);
    grid->setRowStretch(2,0);
    this->setLayout(grid);
}

StudyArea::~StudyArea()
{

}

void StudyArea::correct()
{
    curCard->correct();
    deck->shuffle();
    deck->getDeckScore();
    grid->removeWidget(curCard);
    curCard->hide();
    if (!curCard->isFront()) curCard->Flip();
    curCard = deck->getTop();
    grid->addWidget(curCard,1,0,1,3);
    curCard->show();
    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    deck->autoSave();

}

void StudyArea::incorrect()
{
    curCard->incorrect();
    deck->shuffle();
    grid->removeWidget(curCard);
    curCard->hide();
    if (!curCard->isFront()) curCard->Flip();
    curCard = deck->getTop();
    grid->addWidget(curCard,1,0,1,3);
    curCard->show();
    scores->setText("Card Score: " + QString::number(curCard->getScore()));
    deck->autoSave();
}

void StudyArea::goBack()
{
    parent->updateMenu();
    int nextIndex = pages->currentIndex()-1;
    pages->removeWidget(pages->currentWidget());
    pages->setCurrentIndex(nextIndex);
}
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018-2019 Baldur Karlsson
 *
 * 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 "vk_test.h"

TEST(VK_Image_Layouts, VulkanGraphicsTest)
{
  static constexpr const char *Description =
      "Tests edge-cases of image layout transitions, such as images being in UNDEFINED, "
      "PREINITIALIZED or PRESENT_SRC at the start of the frame.";

  std::string common = R"EOSHADER(

#version 420 core

struct v2f
{
	vec4 pos;
	vec4 col;
	vec4 uv;
};

)EOSHADER";

  const std::string vertex = R"EOSHADER(

layout(location = 0) in vec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec2 UV;

layout(location = 0) out v2f vertOut;

void main()
{
	vertOut.pos = vec4(Position.xyz*vec3(1,-1,1), 1);
	gl_Position = vertOut.pos;
	vertOut.col = Color;
	vertOut.uv = vec4(UV.xy, 0, 1);
}

)EOSHADER";

  const std::string pixel = R"EOSHADER(

layout(location = 0) in v2f vertIn;

layout(location = 0, index = 0) out vec4 Color;

void main()
{
	Color = vertIn.col;
}

)EOSHADER";

  int main()
  {
    // initialise, create window, create context, etc
    if(!Init())
      return 3;

    VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo());

    vkh::GraphicsPipelineCreateInfo pipeCreateInfo;

    pipeCreateInfo.layout = layout;
    pipeCreateInfo.renderPass = mainWindow->rp;

    pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
    pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
        vkh::vertexAttr(0, 0, DefaultA2V, pos), vkh::vertexAttr(1, 0, DefaultA2V, col),
        vkh::vertexAttr(2, 0, DefaultA2V, uv),
    };

    pipeCreateInfo.stages = {
        CompileShaderModule(common + vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
        CompileShaderModule(common + pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
    };

    VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);

    AllocatedBuffer vb(
        allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
                                                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT),
        VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    vb.upload(DefaultTri);

    vkh::ImageCreateInfo preinitInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM,
                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
    preinitInfo.tiling = VK_IMAGE_TILING_LINEAR;
    preinitInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;

    const VkPhysicalDeviceMemoryProperties *props = NULL;
    vmaGetMemoryProperties(allocator, &props);

    while(Running())
    {
      VkImage preinitImg = VK_NULL_HANDLE;
      VkDeviceMemory preinitMem = VK_NULL_HANDLE;

      vkCreateImage(device, preinitInfo, NULL, &preinitImg);

      setName(preinitImg, "Image:Preinitialised");

      AllocatedImage undefImg(allocator, vkh::ImageCreateInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM,
                                                              VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                                                                  VK_IMAGE_USAGE_SAMPLED_BIT),
                              VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));

      setName(undefImg.image, "Image:Undefined");

      {
        VkMemoryRequirements mrq;
        vkGetImageMemoryRequirements(device, preinitImg, &mrq);

        VkMemoryAllocateInfo info = {};
        info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        info.allocationSize = mrq.size;
        info.memoryTypeIndex = 100;

        for(uint32_t i = 0; i < props->memoryTypeCount; i++)
        {
          if(mrq.memoryTypeBits & (1 << i) &&
             (props->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
          {
            info.memoryTypeIndex = i;
            break;
          }
        }

        TEST_ASSERT(info.memoryTypeIndex != 100, "Couldn't find compatible memory type");

        vkAllocateMemory(device, &info, NULL, &preinitMem);
        vkBindImageMemory(device, preinitImg, preinitMem, 0);

        void *data = NULL;
        vkMapMemory(device, preinitMem, 0, mrq.size, 0, &data);
        memset(data, 0x40, mrq.size);
        vkUnmapMemory(device, preinitMem);
      }

      VkCommandBuffer cmd = GetCommandBuffer();

      vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());

      VkImage swapimg = mainWindow->GetImage();
      if(curFrame <= mainWindow->GetCount())
        setName(swapimg, "Image:Swapchain");

      setMarker(cmd, "Before Transition");

      // after the first N frames, we expect the swapchain to be in PRESENT_SRC
      vkh::cmdPipelineBarrier(cmd, {
                                       vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT,
                                                               curFrame <= mainWindow->GetCount()
                                                                   ? VK_IMAGE_LAYOUT_UNDEFINED
                                                                   : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
                                                               VK_IMAGE_LAYOUT_GENERAL, swapimg),
                                   });

      vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
                           vkh::ClearColorValue(0.4f, 0.5f, 0.6f, 1.0f), 1,
                           vkh::ImageSubresourceRange());

      // the manual images are transitioned into general for copying, from pre-initialised and
      // undefined
      vkh::cmdPipelineBarrier(
          cmd, {
                   vkh::ImageMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
                                           VK_IMAGE_LAYOUT_PREINITIALIZED,
                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, preinitImg),
                   vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
                                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, undefImg.image),
               });

      VkImageCopy region = {
          {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
          {0, 0, 0},
          {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
          {0, 0, 0},
          {4, 4, 1},
      };

      vkCmdCopyImage(cmd, preinitImg, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, undefImg.image,
                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

      vkCmdBeginRenderPass(
          cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
          VK_SUBPASS_CONTENTS_INLINE);

      vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
      vkCmdSetViewport(cmd, 0, 1, &mainWindow->viewport);
      vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
      vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
      vkCmdDraw(cmd, 3, 1, 0, 0);

      vkCmdEndRenderPass(cmd);

      FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkEndCommandBuffer(cmd);

      Submit(0, 1, {cmd});

      Present();

      vkDeviceWaitIdle(device);

      vkDestroyImage(device, preinitImg, NULL);
      vkFreeMemory(device, preinitMem, NULL);
    }

    return 0;
  }
};

REGISTER_TEST();
<commit_msg>Fix 32-bit compilation of autotest demos<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018-2019 Baldur Karlsson
 *
 * 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 "vk_test.h"

TEST(VK_Image_Layouts, VulkanGraphicsTest)
{
  static constexpr const char *Description =
      "Tests edge-cases of image layout transitions, such as images being in UNDEFINED, "
      "PREINITIALIZED or PRESENT_SRC at the start of the frame.";

  std::string common = R"EOSHADER(

#version 420 core

struct v2f
{
	vec4 pos;
	vec4 col;
	vec4 uv;
};

)EOSHADER";

  const std::string vertex = R"EOSHADER(

layout(location = 0) in vec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec2 UV;

layout(location = 0) out v2f vertOut;

void main()
{
	vertOut.pos = vec4(Position.xyz*vec3(1,-1,1), 1);
	gl_Position = vertOut.pos;
	vertOut.col = Color;
	vertOut.uv = vec4(UV.xy, 0, 1);
}

)EOSHADER";

  const std::string pixel = R"EOSHADER(

layout(location = 0) in v2f vertIn;

layout(location = 0, index = 0) out vec4 Color;

void main()
{
	Color = vertIn.col;
}

)EOSHADER";

  int main()
  {
    // initialise, create window, create context, etc
    if(!Init())
      return 3;

    VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo());

    vkh::GraphicsPipelineCreateInfo pipeCreateInfo;

    pipeCreateInfo.layout = layout;
    pipeCreateInfo.renderPass = mainWindow->rp;

    pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
    pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
        vkh::vertexAttr(0, 0, DefaultA2V, pos), vkh::vertexAttr(1, 0, DefaultA2V, col),
        vkh::vertexAttr(2, 0, DefaultA2V, uv),
    };

    pipeCreateInfo.stages = {
        CompileShaderModule(common + vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
        CompileShaderModule(common + pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
    };

    VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);

    AllocatedBuffer vb(
        allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
                                                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT),
        VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    vb.upload(DefaultTri);

    vkh::ImageCreateInfo preinitInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM,
                                     VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
    preinitInfo.tiling = VK_IMAGE_TILING_LINEAR;
    preinitInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;

    const VkPhysicalDeviceMemoryProperties *props = NULL;
    vmaGetMemoryProperties(allocator, &props);

    while(Running())
    {
      VkImage preinitImg = VK_NULL_HANDLE;
      VkDeviceMemory preinitMem = VK_NULL_HANDLE;

      vkCreateImage(device, preinitInfo, NULL, &preinitImg);

      setName(preinitImg, "Image:Preinitialised");

      AllocatedImage undefImg(allocator, vkh::ImageCreateInfo(4, 4, 0, VK_FORMAT_R8G8B8A8_UNORM,
                                                              VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                                                                  VK_IMAGE_USAGE_SAMPLED_BIT),
                              VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));

      setName(undefImg.image, "Image:Undefined");

      {
        VkMemoryRequirements mrq;
        vkGetImageMemoryRequirements(device, preinitImg, &mrq);

        VkMemoryAllocateInfo info = {};
        info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        info.allocationSize = mrq.size;
        info.memoryTypeIndex = 100;

        for(uint32_t i = 0; i < props->memoryTypeCount; i++)
        {
          if(mrq.memoryTypeBits & (1 << i) &&
             (props->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
          {
            info.memoryTypeIndex = i;
            break;
          }
        }

        TEST_ASSERT(info.memoryTypeIndex != 100, "Couldn't find compatible memory type");

        vkAllocateMemory(device, &info, NULL, &preinitMem);
        vkBindImageMemory(device, preinitImg, preinitMem, 0);

        void *data = NULL;
        vkMapMemory(device, preinitMem, 0, mrq.size, 0, &data);
        memset(data, 0x40, (size_t)mrq.size);
        vkUnmapMemory(device, preinitMem);
      }

      VkCommandBuffer cmd = GetCommandBuffer();

      vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());

      VkImage swapimg = mainWindow->GetImage();
      if((size_t)curFrame <= mainWindow->GetCount())
        setName(swapimg, "Image:Swapchain");

      setMarker(cmd, "Before Transition");

      // after the first N frames, we expect the swapchain to be in PRESENT_SRC
      vkh::cmdPipelineBarrier(cmd,
                              {
                                  vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT,
                                                          (size_t)curFrame <= mainWindow->GetCount()
                                                              ? VK_IMAGE_LAYOUT_UNDEFINED
                                                              : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
                                                          VK_IMAGE_LAYOUT_GENERAL, swapimg),
                              });

      vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
                           vkh::ClearColorValue(0.4f, 0.5f, 0.6f, 1.0f), 1,
                           vkh::ImageSubresourceRange());

      // the manual images are transitioned into general for copying, from pre-initialised and
      // undefined
      vkh::cmdPipelineBarrier(
          cmd, {
                   vkh::ImageMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
                                           VK_IMAGE_LAYOUT_PREINITIALIZED,
                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, preinitImg),
                   vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
                                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, undefImg.image),
               });

      VkImageCopy region = {
          {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
          {0, 0, 0},
          {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
          {0, 0, 0},
          {4, 4, 1},
      };

      vkCmdCopyImage(cmd, preinitImg, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, undefImg.image,
                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

      vkCmdBeginRenderPass(
          cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
          VK_SUBPASS_CONTENTS_INLINE);

      vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
      vkCmdSetViewport(cmd, 0, 1, &mainWindow->viewport);
      vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
      vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
      vkCmdDraw(cmd, 3, 1, 0, 0);

      vkCmdEndRenderPass(cmd);

      FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkEndCommandBuffer(cmd);

      Submit(0, 1, {cmd});

      Present();

      vkDeviceWaitIdle(device);

      vkDestroyImage(device, preinitImg, NULL);
      vkFreeMemory(device, preinitMem, NULL);
    }

    return 0;
  }
};

REGISTER_TEST();
<|endoftext|>


<commit_before>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <ctime>

#include <boost/numeric/ublas/io.hpp>

#include <scsi/constants.h>
#include <scsi/base.h>
#include <scsi/moment2.h>
#include <scsi/chg_stripper.h>
#include <scsi/state/vector.h>
#include <scsi/state/matrix.h>

typedef Moment2State state_t;

typedef boost::numeric::ublas::vector<double> value_vec;
typedef boost::numeric::ublas::matrix<double> value_mat;

extern int glps_debug;

void PrtVec(const std::vector<double> &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtVec(const Moment2State::vector_t &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtMat(const value_mat &M)
{
    for (size_t j = 0; j < M.size1(); j++) {
        for (size_t k = 0; k < M.size2(); k++)
            std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << M(j, k);
        std::cout << "\n";
    }
}

void PrtState(std::vector<state_t*> StatePtr)
{
    int k;

    for (k = 0; k < StatePtr.size(); k++) {
        std::cout << "\n";
        PrtVec(StatePtr[k]->moment0);
        std::cout << "\n";
        PrtMat(StatePtr[k]->state);
        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr[k]->pos << "\n";
    }
}

std::vector<double> GetChgState(Config &conf)
{
    return conf.get<std::vector<double> >("IonChargeStates");
}

std::vector<double> GetNChg(Config &conf)
{
    return conf.get<std::vector<double> >("NCharge");
}

void prt_initial_cond(std::vector<boost::shared_ptr<Machine> > &sim, std::vector<double> ChgState,
                      std::vector<boost::shared_ptr<StateBase> > &ST)
{
    int     k;
    state_t *StatePtr;

    for (k = 0; k < ChgState.size(); k++) {
        std::cout << "\nIon charge state:\n"
                  << "\nIonZ = " << std::fixed << std::setprecision(5) << std::setw(9) << ChgState[k] << "\n";
        // Propagate through first element (beam initial conditions).
        sim[k]->propagate(ST[k].get(), 0, 1);

        StatePtr = dynamic_cast<state_t*>(ST[k].get());

        std::cout << "\nBarycenter:\n";
        PrtVec(StatePtr->moment0);
        std::cout << "\nBeam envelope:\n";
        PrtMat(StatePtr->state);

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";
    }
}

void propagate(std::auto_ptr<Config> &conf)
{
    int                        k, nChgStates;
    boost::shared_ptr<Machine> sim;
    std::vector<double>        ChgState;
    std::vector<state_t*>      StatePtr;

    nChgStates = GetChgState(*conf).size();
    ChgState.resize(nChgStates);
    ChgState = GetChgState(*conf);

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim = boost::shared_ptr<Machine> (new Machine(*conf));
        sim->set_trace(NULL);

        std::auto_ptr<StateBase> state(sim->allocState());

        StatePtr.push_back(dynamic_cast<state_t*>(state.get()));
        if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr[k]->pos << "\n";

        // Propagate through first element (beam initial conditions).
        sim->propagate(state.get(), 0, 1);

        clock_t tStamp[2];
        tStamp[0] = clock();
        sim->propagate(state.get(), 1);
        tStamp[1] = clock();

        std::cout << std::fixed << std::setprecision(5)
                  << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";
    }

    PrtState(StatePtr);
}

void propagate1(std::auto_ptr<Config> &conf)
{
    // Propagate element-by-element for each charge state.
    int                                        k, nChgStates, elem_no;
    std::vector<double>                        ChgState;
    std::vector<boost::shared_ptr<Machine> >   sim;
    std::vector<boost::shared_ptr<StateBase> > state;
    std::vector<state_t*>                      StatePtr;
    std::vector<Machine::iterator>             it;

    nChgStates = GetChgState(*conf).size();
    ChgState.resize(nChgStates);
    ChgState = GetChgState(*conf);

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim.push_back(boost::shared_ptr<Machine> (new Machine(*conf)));
        sim[k]->set_trace(NULL);

        state.push_back(boost::shared_ptr<StateBase> (sim[k]->allocState()));

        StatePtr.push_back(dynamic_cast<state_t*>(state[k].get()));
        if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        it.push_back(sim[k]->begin());
    }

    prt_initial_cond(sim, ChgState, state);

    clock_t tStamp[2];

    tStamp[0] = clock();

    while (it[0] != sim[0]->end()) {
        ElementVoid* elem   = *it[0];
        std::string  t_name = elem->type_name(); // C string -> C++ string.

        if (t_name == "stripper") {
            elem_no = it[0] - sim[0]->begin();
            std::cout << "\nElement no: " << elem_no << "\n";
            std::cout << conf->get<Config::vector_t>("elements")[elem_no] << "\n";
            Stripper_GetMat(*conf, sim, state, ChgState);

            StatePtr.clear();
            it.clear();
            for (k = 0; k < state.size(); k++) {
                StatePtr.push_back(dynamic_cast<state_t*>(state[k].get()));
                if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

                it.push_back(sim[k]->begin()+elem_no+1);
            }

            while (it[0] != sim[0]->end()) {
                for (k = 0; k < state.size(); k++) {
                    (*it[k])->advance(*state[k]);
                    ++it[k];
                }
            }

            break;
        }

        for (k = 0; k < nChgStates; k++) {
            (*it[k])->advance(*state[k]);
            ++it[k];
        }
    }

    tStamp[1] = clock();

    PrtState(StatePtr);

    std::cout << std::fixed << std::setprecision(5)
              << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";
}

int main(int argc, char *argv[])
{
    try {
        std::auto_ptr<Config> conf;

        if(argc>2)

        glps_debug = 0; // 0 or 1.

        try {
            GLPSParser P;
            conf.reset(P.parse_file(argc>1 ? argv[1] : NULL));
            fprintf(stderr, "Parsing succeeds\n");
        } catch(std::exception& e) {
            fprintf(stderr, "Parse error: %s\n", e.what());
            return 1;
        }

//        std::cout<<"# Reduced lattice\n";
//        GLPSPrint(std::cout, *conf);
//        std::cout<<"\n";

        registerMoment2();

//        propagate(conf);
        propagate1(conf);

        return 0;
    } catch(std::exception& e) {
        std::cerr << "Main exception: " << e.what() << "\n";
        Machine::registeryCleanup();
        return 1;
    }
}
<commit_msg>print a lot more internal state<commit_after>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <ctime>

#include <boost/numeric/ublas/io.hpp>

#include <scsi/constants.h>
#include <scsi/base.h>
#include <scsi/moment2.h>
#include <scsi/chg_stripper.h>
#include <scsi/state/vector.h>
#include <scsi/state/matrix.h>

typedef Moment2State state_t;

typedef boost::numeric::ublas::vector<double> value_vec;
typedef boost::numeric::ublas::matrix<double> value_mat;

extern int glps_debug;

void PrtVec(const std::vector<double> &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtVec(const Moment2State::vector_t &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtMat(const value_mat &M)
{
    for (size_t j = 0; j < M.size1(); j++) {
        for (size_t k = 0; k < M.size2(); k++)
            std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << M(j, k);
        std::cout << "\n";
    }
}

static
void GetCenofChgx(const Config &conf, std::vector<state_t*> &ST,
                 Moment2State::vector_t &CenofChg, Moment2State::vector_t &BeamRMS)
{
    Moment2State::vector_t BeamVar;

    CenofChg = boost::numeric::ublas::zero_vector<double>(PS_Dim);
    BeamRMS  = boost::numeric::ublas::zero_vector<double>(PS_Dim);
    BeamVar  = boost::numeric::ublas::zero_vector<double>(PS_Dim);

    double Ntot = 0e0;
    for (size_t i = 0; i < ST.size(); i++) {
        state_t* StatePtr = ST[i];
        for (size_t j = 0; j < PS_Dim; j++) {
            CenofChg[j] += StatePtr->real.IonQ*StatePtr->moment0[j];
        }
        Ntot += StatePtr->real.IonQ;
    }

    for (size_t j = 0; j < PS_Dim; j++)
        CenofChg[j] /= Ntot;

    for (size_t i = 0; i < ST.size(); i++) {
        for (size_t j = 0; j < PS_Dim; j++) {
            state_t* StatePtr = ST[i];
            BeamVar[j]  +=
                    StatePtr->real.IonQ*(StatePtr->state(j, j)
                    +(StatePtr->moment0[j]-CenofChg[j])*(StatePtr->moment0[j]-CenofChg[j]));
        }
    }

    for (size_t j = 0; j < PS_Dim; j++)
        BeamRMS[j] = sqrt(BeamVar[j]/Ntot);
}

std::ostream& operator<<(std::ostream& strm, const Particle& P)
{
    strm <<std::setprecision(8)<<std::setw(14)
      <<"IonZ="<<P.IonZ
      <<" IonQ="<<P.IonQ
      <<" IonEs="<<P.IonEs
      <<" IonEk="<<P.IonEk
      <<" SampleIonK="<<P.SampleIonK
      <<" phis="<<P.phis
      <<" IonW="<<P.IonW
      <<" gamma="<<P.gamma
      <<" beta="<<P.beta
      <<" bg="<<P.bg
      ;
    return strm;
}

void PrtState(const Config &conf, std::vector<state_t*> StatePtr)
{
    size_t k;

    for (k = 0; k < StatePtr.size(); k++) {
        std::cout << "\nState: "<<k<<" s = "<<std::fixed << std::setprecision(3) << StatePtr[k]->pos << "\n"
                          <<"\n Ref:  "<<StatePtr[k]->ref
                          <<"\n Real: "<<StatePtr[k]->real
                          <<"\n moment0\n";
        PrtVec(StatePtr[k]->moment0);
        std::cout << " moment1\n";
        PrtMat(StatePtr[k]->state);
        std::cout << "\n";
    }

    Moment2State::vector_t cent, rms;

    GetCenofChgx(conf, StatePtr, cent, rms);

    std::cout<<"Center: "<< std::scientific << std::setprecision(10)
             << std::setw(18)<<cent<<"\n\n";
}

std::vector<double> GetChgState(Config &conf)
{
    return conf.get<std::vector<double> >("IonChargeStates");
}

std::vector<double> GetNChg(Config &conf)
{
    return conf.get<std::vector<double> >("NCharge");
}

void prt_initial_cond(std::vector<boost::shared_ptr<Machine> > &sim, std::vector<double> ChgState,
                      std::vector<boost::shared_ptr<StateBase> > &ST)
{
    size_t  k;
    state_t *StatePtr;

    for (k = 0; k < ChgState.size(); k++) {
        std::cout << "\nIon charge state:\n"
                  << "\nIonZ = " << std::fixed << std::setprecision(5) << std::setw(9) << ChgState[k] << "\n";
        // Propagate through first element (beam initial conditions).
        sim[k]->propagate(ST[k].get(), 0, 1);

        StatePtr = dynamic_cast<state_t*>(ST[k].get());

        std::cout << "\nBarycenter:\n";
        PrtVec(StatePtr->moment0);
        std::cout << "\nBeam envelope:\n";
        PrtMat(StatePtr->state);

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";
    }
}

void propagate(std::auto_ptr<Config> &conf)
{
    int                        k, nChgStates;
    boost::shared_ptr<Machine> sim;
    std::vector<double>        ChgState;
    std::vector<state_t*>      StatePtr;

    nChgStates = GetChgState(*conf).size();
    ChgState.resize(nChgStates);
    ChgState = GetChgState(*conf);

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim = boost::shared_ptr<Machine> (new Machine(*conf));
        sim->set_trace(NULL);

        std::auto_ptr<StateBase> state(sim->allocState());

        StatePtr.push_back(dynamic_cast<state_t*>(state.get()));
        if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr[k]->pos << "\n";

        // Propagate through first element (beam initial conditions).
        sim->propagate(state.get(), 0, 1);

        clock_t tStamp[2];
        tStamp[0] = clock();
        sim->propagate(state.get(), 1);
        tStamp[1] = clock();

        std::cout << std::fixed << std::setprecision(5)
                  << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";
    }

    PrtState(*conf, StatePtr);
}

void propagate1(std::auto_ptr<Config> &conf)
{
    // Propagate element-by-element for each charge state.
    size_t                                     k, nChgStates, elem_no;
    std::vector<double>                        ChgState;
    std::vector<boost::shared_ptr<Machine> >   sim;
    std::vector<boost::shared_ptr<StateBase> > state;
    std::vector<state_t*>                      StatePtr;
    std::vector<Machine::iterator>             it;

    nChgStates = GetChgState(*conf).size();
    ChgState.resize(nChgStates);
    ChgState = GetChgState(*conf);

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim.push_back(boost::shared_ptr<Machine> (new Machine(*conf)));
        sim[k]->set_trace(NULL);

        state.push_back(boost::shared_ptr<StateBase> (sim[k]->allocState()));

        StatePtr.push_back(dynamic_cast<state_t*>(state[k].get()));
        if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        it.push_back(sim[k]->begin());
    }

    prt_initial_cond(sim, ChgState, state);

    clock_t tStamp[2];

    tStamp[0] = clock();

    while (it[0] != sim[0]->end()) {
        ElementVoid* elem   = *it[0];
        std::string  t_name = elem->type_name(); // C string -> C++ string.
        std::cout<<"At element "<<elem->index<<" "<<elem->name<<"\n";

        if (t_name == "stripper") {
            elem_no = it[0] - sim[0]->begin();
            std::cout << "\nElement no: " << elem_no << "\n";
            std::cout << conf->get<Config::vector_t>("elements")[elem_no] << "\n";
            Stripper_GetMat(*conf, sim, state, ChgState);

            StatePtr.clear();
            it.clear();
            for (k = 0; k < state.size(); k++) {
                StatePtr.push_back(dynamic_cast<state_t*>(state[k].get()));
                if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

                it.push_back(sim[k]->begin()+elem_no+1);
            }

            while (it[0] != sim[0]->end()) {
                unsigned idx = (*it[0])->index;
                std::cout<<"At element "<<(*it[0])->index<<" "<<(*it[0])->name<<"\n";

                for (k = 0; k < state.size(); k++) {
                    (*it[k])->advance(*state[k]);
                    std::cout<<"Transfer "<<k<<"\n";
                    PrtMat(static_cast<Moment2ElementBase*>(*it[k])->transfer);
                    ++it[k];
                }
                std::cout<<"After element "<<idx<<"\n";
                PrtState(*conf, StatePtr);
            }

            break;
        }

        unsigned idx = (*it[0])->index;
        for (k = 0; k < nChgStates; k++) {
            (*it[k])->advance(*state[k]);
            std::cout<<"Transfer "<<k<<"\n";
            PrtMat(static_cast<Moment2ElementBase*>(*it[k])->transfer);
            ++it[k];
        }
        std::cout<<"After element "<<idx<<"\n\n";
        PrtState(*conf, StatePtr);
    }

    tStamp[1] = clock();

    PrtState(*conf, StatePtr);

    std::cout << std::fixed << std::setprecision(5)
              << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";
}

int main(int argc, char *argv[])
{
    try {
        std::auto_ptr<Config> conf;

        if(argc>2)

        glps_debug = 0; // 0 or 1.

        try {
            GLPSParser P;
            conf.reset(P.parse_file(argc>1 ? argv[1] : NULL));
            fprintf(stderr, "Parsing succeeds\n");
        } catch(std::exception& e) {
            fprintf(stderr, "Parse error: %s\n", e.what());
            return 1;
        }

//        std::cout<<"# Reduced lattice\n";
//        GLPSPrint(std::cout, *conf);
//        std::cout<<"\n";

        registerMoment2();

//        propagate(conf);
        propagate1(conf);

        return 0;
    } catch(std::exception& e) {
        std::cerr << "Main exception: " << e.what() << "\n";
        Machine::registeryCleanup();
        return 1;
    }
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <iostream>

struct DebugBuffer
{
	DWORD   processId;
	char    debugText[4096-sizeof(DWORD)];
};

class IDebugEventHandler
{
public:
	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) = 0;
};

class DebugMonitor
{
public:
	DebugMonitor (IDebugEventHandler* eventHandler) :
		eventHandler (eventHandler),
		mutexHandle (NULL),
		bufferReadyEventHandle (NULL),
		dataReadyEventHandle (NULL),
		fileMappingHandle (NULL),
		mapViewOfFileHandle (NULL),
		threadHandle (NULL),
		running (false)
	{
	}

	~DebugMonitor ()
	{
	}

	bool Start ()
	{
		mutexHandle = OpenMutex (SYNCHRONIZE, FALSE, L"DBWinMutex");
		if (mutexHandle == NULL) {
			int error = GetLastError ();
			return false;
		}

		bufferReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
		if (bufferReadyEventHandle == NULL) {
			bufferReadyEventHandle = CreateEvent (NULL, FALSE, TRUE, L"DBWIN_BUFFER_READY");
			if (bufferReadyEventHandle == NULL) {
				return false;
			}
		}

		dataReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_DATA_READY");
		if (dataReadyEventHandle == NULL) {
			dataReadyEventHandle = CreateEvent (NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
			if (dataReadyEventHandle == NULL) {
				return false;
			}
		}

		fileMappingHandle = OpenFileMapping (FILE_MAP_READ, FALSE, L"DBWIN_BUFFER");
		if (fileMappingHandle == NULL) {
			fileMappingHandle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof (DebugBuffer), L"DBWIN_BUFFER");
			if (fileMappingHandle == NULL) {
				return false;
			}
		}

		mapViewOfFileHandle = MapViewOfFile (fileMappingHandle, SECTION_MAP_READ, 0, 0, 0);
		if (mapViewOfFileHandle == NULL) {
			return false;
		}

		threadHandle = CreateThread (NULL, 0, DebugMonitorThread, this, 0, NULL);
		if (threadHandle == NULL) {
			return false;
		}

		running = true;
		return true;
	}

	void Stop ()
	{
		running = false;

		if (threadHandle != NULL) {
			WaitForSingleObject (threadHandle, INFINITE);
		}

		if (mutexHandle != NULL) {
			CloseHandle (mutexHandle);
			mutexHandle = NULL;
		}

		if (fileMappingHandle != NULL) {
			UnmapViewOfFile (fileMappingHandle);
			CloseHandle (fileMappingHandle);
			fileMappingHandle = NULL;
		}

		if (bufferReadyEventHandle != NULL) {
			CloseHandle (bufferReadyEventHandle);
			bufferReadyEventHandle = NULL;
		}

		if (dataReadyEventHandle != NULL) {
			CloseHandle (dataReadyEventHandle);
			dataReadyEventHandle = NULL;
		}
	}

private:
	static DWORD WINAPI DebugMonitorThread (void *userData)
	{
		DebugMonitor* debugMonitor = (DebugMonitor*) userData;
		if (debugMonitor != NULL) {
			debugMonitor->ProcessEvents ();
		}
		return 0;
	}

	DWORD ProcessEvents ()
	{
		while (running) {
			DWORD result = WaitForSingleObject (dataReadyEventHandle, 100);
			if (result == WAIT_OBJECT_0) {
				DebugBuffer* debugBuffer = (DebugBuffer*) mapViewOfFileHandle;
				if (eventHandler != NULL) {
					eventHandler->OnDebugEvent (debugBuffer);
				}
				SetEvent (bufferReadyEventHandle);
			}
		}
		return 0;
	}

	IDebugEventHandler* eventHandler;

	HANDLE mutexHandle;
	HANDLE bufferReadyEventHandle;
	HANDLE dataReadyEventHandle;
	HANDLE fileMappingHandle;
	HANDLE mapViewOfFileHandle;
	HANDLE threadHandle;

	bool running;
};

class DebugFileWriter : public IDebugEventHandler
{
public:
	DebugFileWriter (const std::wstring& logFileName, DWORD processIdentifier)
	{
		fileHandle = CreateFile (logFileName.c_str (), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		processId = processIdentifier;
	}

	~DebugFileWriter ()
	{
		CloseHandle (fileHandle);
	}

	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) override
	{
		if (processId == debugBuffer->processId) {
			DWORD bytesWritten = 0;
			WriteFile (fileHandle, debugBuffer->debugText, (DWORD) strlen (debugBuffer->debugText), &bytesWritten, NULL);
		}
	}

private:
	HANDLE	fileHandle;
	DWORD	processId;
};

int wmain (int argc, wchar_t* argv[])
{
	if (argc < 3) {
		std::cout << "Usage: DebugToFile.exe [DebugLogFileName] [ApplicationName] <ApplicationArguments>" << std::endl;
		return 1;
	}

	std::wstring debugLogfileName = argv[1];
	std::wstring commandArguments = argv[2];
	for (int i = 3; i < argc; i++) {
		commandArguments += L" \"";
		commandArguments += argv[i];
		commandArguments += L"\"";
	}

	wchar_t commandArgumentsString[4096];
	wcscpy_s (commandArgumentsString, 4096, commandArguments.c_str ());

	STARTUPINFO startupInfo;
	ZeroMemory (&startupInfo, sizeof (STARTUPINFO));

	PROCESS_INFORMATION processInfo;
	ZeroMemory (&processInfo, sizeof (PROCESS_INFORMATION));

	BOOL processCreated = CreateProcess (NULL, commandArgumentsString, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
	if (!processCreated) {
		std::cout << "Error: Failed to start application" << std::endl;
		return 1;
	}

	DWORD exitCode = 0;
	if (processCreated) {
		DebugFileWriter debugFileWriter (debugLogfileName, processInfo.dwProcessId);
		DebugMonitor debugMonitor (&debugFileWriter);

		debugMonitor.Start ();
		WaitForSingleObject (processInfo.hProcess, INFINITE);
		debugMonitor.Stop ();

		GetExitCodeProcess (processInfo.hProcess, &exitCode);
		CloseHandle (processInfo.hProcess);
		CloseHandle (processInfo.hThread);
	}
	return exitCode;
}
<commit_msg>Minor modification.<commit_after>#include <windows.h>
#include <iostream>

struct DebugBuffer
{
	DWORD   processId;
	char    debugText[4096-sizeof(DWORD)];
};

class IDebugEventHandler
{
public:
	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) = 0;
};

class DebugMonitor
{
public:
	DebugMonitor (IDebugEventHandler* eventHandler) :
		eventHandler (eventHandler),
		mutexHandle (NULL),
		bufferReadyEventHandle (NULL),
		dataReadyEventHandle (NULL),
		fileMappingHandle (NULL),
		mapViewOfFileHandle (NULL),
		threadHandle (NULL),
		running (false)
	{
	}

	~DebugMonitor ()
	{
	}

	bool Start ()
	{
		mutexHandle = OpenMutex (SYNCHRONIZE, FALSE, L"DBWinMutex");
		if (mutexHandle == NULL) {
			int error = GetLastError ();
			return false;
		}

		bufferReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
		if (bufferReadyEventHandle == NULL) {
			bufferReadyEventHandle = CreateEvent (NULL, FALSE, TRUE, L"DBWIN_BUFFER_READY");
			if (bufferReadyEventHandle == NULL) {
				return false;
			}
		}

		dataReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_DATA_READY");
		if (dataReadyEventHandle == NULL) {
			dataReadyEventHandle = CreateEvent (NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
			if (dataReadyEventHandle == NULL) {
				return false;
			}
		}

		fileMappingHandle = OpenFileMapping (FILE_MAP_READ, FALSE, L"DBWIN_BUFFER");
		if (fileMappingHandle == NULL) {
			fileMappingHandle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof (DebugBuffer), L"DBWIN_BUFFER");
			if (fileMappingHandle == NULL) {
				return false;
			}
		}

		mapViewOfFileHandle = MapViewOfFile (fileMappingHandle, SECTION_MAP_READ, 0, 0, 0);
		if (mapViewOfFileHandle == NULL) {
			return false;
		}

		threadHandle = CreateThread (NULL, 0, DebugMonitorThread, this, 0, NULL);
		if (threadHandle == NULL) {
			return false;
		}

		running = true;
		return true;
	}

	void Stop ()
	{
		running = false;

		if (threadHandle != NULL) {
			WaitForSingleObject (threadHandle, INFINITE);
		}

		if (mutexHandle != NULL) {
			CloseHandle (mutexHandle);
			mutexHandle = NULL;
		}

		if (fileMappingHandle != NULL) {
			UnmapViewOfFile (fileMappingHandle);
			CloseHandle (fileMappingHandle);
			fileMappingHandle = NULL;
		}

		if (bufferReadyEventHandle != NULL) {
			CloseHandle (bufferReadyEventHandle);
			bufferReadyEventHandle = NULL;
		}

		if (dataReadyEventHandle != NULL) {
			CloseHandle (dataReadyEventHandle);
			dataReadyEventHandle = NULL;
		}
	}

private:
	static DWORD WINAPI DebugMonitorThread (void *userData)
	{
		DebugMonitor* debugMonitor = (DebugMonitor*) userData;
		if (debugMonitor != NULL) {
			debugMonitor->ProcessEvents ();
		}
		return 0;
	}

	DWORD ProcessEvents ()
	{
		while (running) {
			DWORD result = WaitForSingleObject (dataReadyEventHandle, 100);
			if (result == WAIT_OBJECT_0) {
				DebugBuffer* debugBuffer = (DebugBuffer*) mapViewOfFileHandle;
				if (eventHandler != NULL) {
					eventHandler->OnDebugEvent (debugBuffer);
				}
				SetEvent (bufferReadyEventHandle);
			}
		}
		return 0;
	}

	IDebugEventHandler* eventHandler;

	HANDLE mutexHandle;
	HANDLE bufferReadyEventHandle;
	HANDLE dataReadyEventHandle;
	HANDLE fileMappingHandle;
	HANDLE mapViewOfFileHandle;
	HANDLE threadHandle;

	bool running;
};

class DebugFileWriter : public IDebugEventHandler
{
public:
	DebugFileWriter (const std::wstring& logFileName, DWORD processIdentifier)
	{
		fileHandle = CreateFile (logFileName.c_str (), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		processId = processIdentifier;
	}

	~DebugFileWriter ()
	{
		CloseHandle (fileHandle);
	}

	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) override
	{
		if (processId == debugBuffer->processId) {
			DWORD bytesWritten = 0;
			WriteFile (fileHandle, debugBuffer->debugText, (DWORD) strlen (debugBuffer->debugText), &bytesWritten, NULL);
		}
	}

private:
	HANDLE	fileHandle;
	DWORD	processId;
};

int wmain (int argc, wchar_t* argv[])
{
	if (argc < 3) {
		std::cout << "Usage: DebugToFile.exe [DebugLogFileName] [ApplicationName] <ApplicationArguments>" << std::endl;
		return 1;
	}

	std::wstring debugLogfileName = argv[1];
	std::wstring commandArguments = argv[2];
	for (int i = 3; i < argc; i++) {
		commandArguments += L" \"";
		commandArguments += argv[i];
		commandArguments += L"\"";
	}

	wchar_t commandArgumentsString[4096];
	wcscpy_s (commandArgumentsString, 4096, commandArguments.c_str ());

	STARTUPINFO startupInfo;
	ZeroMemory (&startupInfo, sizeof (STARTUPINFO));

	PROCESS_INFORMATION processInfo;
	ZeroMemory (&processInfo, sizeof (PROCESS_INFORMATION));

	BOOL processCreated = CreateProcess (NULL, commandArgumentsString, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
	if (!processCreated) {
		std::cout << "Error: Failed to start application" << std::endl;
		return 1;
	}

	DebugFileWriter debugFileWriter (debugLogfileName, processInfo.dwProcessId);
	DebugMonitor debugMonitor (&debugFileWriter);

	debugMonitor.Start ();
	WaitForSingleObject (processInfo.hProcess, INFINITE);
	debugMonitor.Stop ();

	DWORD exitCode = 0;
	GetExitCodeProcess (processInfo.hProcess, &exitCode);

	CloseHandle (processInfo.hProcess);
	CloseHandle (processInfo.hThread);

	return exitCode;
}
<|endoftext|>