<commit_before>#define _GNU_SOURCE
#include "cfg.h"
#include "multicron.h"
#include "commands.h"
#include <string>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#ifdef BSD
#else
#include <linux/unistd.h>
#include <sys/syscall.h>
#endif

/* Copy from linux/ioprio.h*/
enum {
	IOPRIO_CLASS_NONE,
	IOPRIO_CLASS_RT,
	IOPRIO_CLASS_BE,
	IOPRIO_CLASS_IDLE,
};

enum {
	IOPRIO_WHO_PROCESS = 1,
	IOPRIO_WHO_PGRP,
	IOPRIO_WHO_USER,
};

struct cmd *Cmds::cmds=NULL;

#define IOPRIO_BITS             (16)
#define IOPRIO_CLASS_SHIFT      (13)
#define IOPRIO_PRIO_MASK        ((1UL << IOPRIO_CLASS_SHIFT) - 1)

#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
#define IOPRIO_PRIO_DATA(mask)  ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(clas, data)  (((clas) << IOPRIO_CLASS_SHIFT) | data)

void fill_context(context_t &ctx) {
	if(ctx.pid==0)
		ctx.pid=getpid();
}

void Cmds::Call(const cfgNode& arg, context_t context) {
	fill_context(context);
	int i;
	cfgNode t(arg);
	t=t.getChild();
	while(!!t) {
		for(i=0;cmds[i].name!=NULL;++i) {
			if(strcmp(cmds[i].name, t.getName())==0) {

				cmds[i].callback(t, context);
				break;
			}
		}
		++t;
	}
}

void ioniceCall(const cfgNode& arg, const context_t& context) {
	printf("ionice called\n");
#ifndef BSD
	const char *nice_class=arg["class"];
	int ioprio;
	if(!nice_class)
		ioprio=IOPRIO_CLASS_BE;
	else if(strcmp(nice_class, "realtime")==0)
		ioprio=IOPRIO_CLASS_RT;
	else if(strcmp(nice_class, "idle")==0)
		ioprio=IOPRIO_CLASS_IDLE;
	else
		ioprio=IOPRIO_CLASS_BE;
	const char *prio=arg["priority"];
	if(prio) {
		int a=atoi(prio);
		if(a<0 || a>7)
			a=4;
		ioprio=IOPRIO_PRIO_VALUE(ioprio, a);
	} else
		ioprio=IOPRIO_PRIO_VALUE(ioprio, 4);

	syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, context.pid, ioprio);
#else
	printf("ionice not supported on bsd\n");
#endif
}

void cpuniceCall(const cfgNode& arg, const context_t& context) {
	printf("cpunice called\n");
}

void killCall(const cfgNode& arg, const context_t& context) {
	printf("kill called\n");
	const char *sig=arg["signal"];
	int sigid;
	if(sig!=NULL)
		sigid=atoi(sig);
	else
		sigid=10;//SIGUSR1
	const char *pid=arg["pid"];
	int p;
	if(pid)
		p=atoi(pid);
	else
		p=context.pid;
	printf("kill(%d,%d)\n", p, sigid);
	if(kill(p, sigid)!=0) {
		perror("kill");
	}
}

void cmdCall(const cfgNode& arg, const context_t& context) {
	if(arg()) {
		int pid=fork();
		if(pid>0)
			return;
		if(pid<0)
			throw "Couldn't fork!";
		char *p;
		asprintf(&p, "%d", context.pid);
		setenv("M_PID", p, 1);
		if(context.file)
			setenv("M_FILE", p, 1);
		else
			setenv("M_FILE", "(null)", 1);
		exit(system(arg()));
	}
}

extern bool reload;
void reloadCall(const cfgNode& arg, const context_t &ctx) {
	reload=true;
}

void logCall(const cfgNode& arg, const context_t& context) {
	if(!arg())
		return;
	fprintf(stderr, "%s\n", arg());
}

void loadCall(const cfgNode& arg, const context_t& context) {
	cfgNode conf(arg);
	char *str;
	asprintf(&str, "%d", context.pid);
	conf.addAttr("pid", str);
	free(str);
	conf.addAttr("file", context.file);
	conf.addAttr("devpath", context.devpath);
	if(arg["mod"]) {
		EventManager *ev=MainLoop::GetEM(arg["mod"]);
		if(!ev)
			throw "Unsupported module";
		else
			ev->AddCfg(arg);
	} else
		throw "Hum, don't want to load any module ? What's wrong with you ?";
}

void Cmds::Update() {
	if(cmds) {
		int i;
		for(i=0;cmds[i].name;i++)
			free(cmds[i].name);
		free(cmds);
	}
	cmds=(struct cmd*)malloc(sizeof(*cmds)*10);
	memset(cmds, 0, sizeof(*cmds)*10);
	cmds[0].name=strdup("ionice");
	cmds[0].callback=ioniceCall;
	cmds[1].name=strdup("cpunice");
	cmds[1].callback=cpuniceCall;
	cmds[2].name=strdup("kill");
	cmds[2].callback=killCall;
	cmds[3].name=strdup("cmd");
	cmds[3].callback=cmdCall;
	cmds[4].name=strdup("reload");
	cmds[4].callback=reloadCall;
	cmds[5].name=strdup("log");
	cmds[5].callback=logCall;
	cmds[6].name=strdup("load");//Has to be renamed
	cmds[6].callback=loadCall;
}

<commit_msg>Fix the load command arguments<commit_after>#define _GNU_SOURCE
#include "cfg.h"
#include "multicron.h"
#include "commands.h"
#include <string>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#ifdef BSD
#else
#include <linux/unistd.h>
#include <sys/syscall.h>
#endif

/* Copy from linux/ioprio.h*/
enum {
	IOPRIO_CLASS_NONE,
	IOPRIO_CLASS_RT,
	IOPRIO_CLASS_BE,
	IOPRIO_CLASS_IDLE,
};

enum {
	IOPRIO_WHO_PROCESS = 1,
	IOPRIO_WHO_PGRP,
	IOPRIO_WHO_USER,
};

struct cmd *Cmds::cmds=NULL;

#define IOPRIO_BITS             (16)
#define IOPRIO_CLASS_SHIFT      (13)
#define IOPRIO_PRIO_MASK        ((1UL << IOPRIO_CLASS_SHIFT) - 1)

#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
#define IOPRIO_PRIO_DATA(mask)  ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(clas, data)  (((clas) << IOPRIO_CLASS_SHIFT) | data)

void fill_context(context_t &ctx) {
	if(ctx.pid==0)
		ctx.pid=getpid();
}

void Cmds::Call(const cfgNode& arg, context_t context) {
	fill_context(context);
	int i;
	cfgNode t(arg);
	t=t.getChild();
	while(!!t) {
		for(i=0;cmds[i].name!=NULL;++i) {
			if(strcmp(cmds[i].name, t.getName())==0) {

				cmds[i].callback(t, context);
				break;
			}
		}
		++t;
	}
}

void ioniceCall(const cfgNode& arg, const context_t& context) {
	printf("ionice called\n");
#ifndef BSD
	const char *nice_class=arg["class"];
	int ioprio;
	if(!nice_class)
		ioprio=IOPRIO_CLASS_BE;
	else if(strcmp(nice_class, "realtime")==0)
		ioprio=IOPRIO_CLASS_RT;
	else if(strcmp(nice_class, "idle")==0)
		ioprio=IOPRIO_CLASS_IDLE;
	else
		ioprio=IOPRIO_CLASS_BE;
	const char *prio=arg["priority"];
	if(prio) {
		int a=atoi(prio);
		if(a<0 || a>7)
			a=4;
		ioprio=IOPRIO_PRIO_VALUE(ioprio, a);
	} else
		ioprio=IOPRIO_PRIO_VALUE(ioprio, 4);

	syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, context.pid, ioprio);
#else
	printf("ionice not supported on bsd\n");
#endif
}

void cpuniceCall(const cfgNode& arg, const context_t& context) {
	printf("cpunice called\n");
}

void killCall(const cfgNode& arg, const context_t& context) {
	printf("kill called\n");
	const char *sig=arg["signal"];
	int sigid;
	if(sig!=NULL)
		sigid=atoi(sig);
	else
		sigid=10;//SIGUSR1
	const char *pid=arg["pid"];
	int p;
	if(pid)
		p=atoi(pid);
	else
		p=context.pid;
	printf("kill(%d,%d)\n", p, sigid);
	if(kill(p, sigid)!=0) {
		perror("kill");
	}
}

void cmdCall(const cfgNode& arg, const context_t& context) {
	if(arg()) {
		int pid=fork();
		if(pid>0)
			return;
		if(pid<0)
			throw "Couldn't fork!";
		char *p;
		asprintf(&p, "%d", context.pid);
		setenv("M_PID", p, 1);
		if(context.file)
			setenv("M_FILE", p, 1);
		else
			setenv("M_FILE", "(null)", 1);
		exit(system(arg()));
	}
}

extern bool reload;
void reloadCall(const cfgNode& arg, const context_t &ctx) {
	reload=true;
}

void logCall(const cfgNode& arg, const context_t& context) {
	if(!arg())
		return;
	fprintf(stderr, "%s\n", arg());
}

void loadCall(const cfgNode& arg, const context_t& context) {
	cfgNode conf(arg);
	char *str;
	asprintf(&str, "%d", context.pid);
	conf.addAttr("pid", str);
	free(str);
	conf.addAttr("file", context.file);
	conf.addAttr("devpath", context.devpath);
	if(arg["mod"]) {
		EventManager *ev=MainLoop::GetEM(arg["mod"]);
		if(!ev)
			throw "Unsupported module";
		else
			ev->AddCfg(conf);
	} else
		throw "Hum, don't want to load any module ? What's wrong with you ?";
}

void Cmds::Update() {
	if(cmds) {
		int i;
		for(i=0;cmds[i].name;i++)
			free(cmds[i].name);
		free(cmds);
	}
	cmds=(struct cmd*)malloc(sizeof(*cmds)*10);
	memset(cmds, 0, sizeof(*cmds)*10);
	cmds[0].name=strdup("ionice");
	cmds[0].callback=ioniceCall;
	cmds[1].name=strdup("cpunice");
	cmds[1].callback=cpuniceCall;
	cmds[2].name=strdup("kill");
	cmds[2].callback=killCall;
	cmds[3].name=strdup("cmd");
	cmds[3].callback=cmdCall;
	cmds[4].name=strdup("reload");
	cmds[4].callback=reloadCall;
	cmds[5].name=strdup("log");
	cmds[5].callback=logCall;
	cmds[6].name=strdup("load");//Has to be renamed
	cmds[6].callback=loadCall;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2014-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/Benchmark.h>
#include <folly/executors/InlineExecutor.h>
#include <folly/futures/Future.h>
#include <folly/futures/Promise.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/Semaphore.h>
#include <folly/synchronization/Baton.h>

#include <vector>

using namespace folly;

namespace {

template <class T>
T incr(Try<T>&& t) {
  return t.value() + 1;
}

void someThens(size_t n) {
  auto f = makeFuture<int>(42);
  for (size_t i = 0; i < n; i++) {
    f = f.then(incr<int>);
  }
}

} // namespace

BENCHMARK(constantFuture) {
  makeFuture(42);
}

BENCHMARK_RELATIVE(promiseAndFuture) {
  Promise<int> p;
  Future<int> f = p.getFuture();
  p.setValue(42);
  f.value();
}

BENCHMARK_RELATIVE(withThen) {
  Promise<int> p;
  Future<int> f = p.getFuture().then(incr<int>);
  p.setValue(42);
  f.value();
}

// thens
BENCHMARK_DRAW_LINE();

BENCHMARK(oneThen) {
  someThens(1);
}

// look for >= 50% relative
BENCHMARK_RELATIVE(twoThens) {
  someThens(2);
}

// look for >= 25% relative
BENCHMARK_RELATIVE(fourThens) {
  someThens(4);
}

// look for >= 1% relative
BENCHMARK_RELATIVE(hundredThens) {
  someThens(100);
}

// Lock contention. Although in practice fulfills tend to be temporally
// separate from then()s, still sometimes they will be concurrent. So the
// higher this number is, the better.
BENCHMARK_DRAW_LINE();

BENCHMARK(no_contention) {
  std::vector<Promise<int>> promises(10000);
  std::vector<Future<int>> futures;
  std::thread producer, consumer;

  BENCHMARK_SUSPEND {
    folly::Baton<> b1, b2;
    for (auto& p : promises) {
      futures.push_back(p.getFuture());
    }

    consumer = std::thread([&]{
      b1.post();
      for (auto& f : futures) {
        f.then(incr<int>);
      }
    });
    consumer.join();

    producer = std::thread([&]{
      b2.post();
      for (auto& p : promises) {
        p.setValue(42);
      }
    });

    b1.wait();
    b2.wait();
  }

  // The only thing we are measuring is how long fulfill + callbacks take
  producer.join();
}

BENCHMARK_RELATIVE(contention) {
  std::vector<Promise<int>> promises(10000);
  std::vector<Future<int>> futures;
  std::thread producer, consumer;
  sem_t sem;
  sem_init(&sem, 0, 0);

  BENCHMARK_SUSPEND {
    folly::Baton<> b1, b2;
    for (auto& p : promises) {
      futures.push_back(p.getFuture());
    }

    consumer = std::thread([&]{
      b1.post();
      for (auto& f : futures) {
        sem_wait(&sem);
        f.then(incr<int>);
      }
    });

    producer = std::thread([&]{
      b2.post();
      for (auto& p : promises) {
        sem_post(&sem);
        p.setValue(42);
      }
    });

    b1.wait();
    b2.wait();
  }

  // The astute reader will notice that we're not *precisely* comparing apples
  // to apples here. Well, maybe it's like comparing Granny Smith to
  // Braeburn or something. In the serial version, we waited for the futures
  // to be all set up, but here we are probably still doing that work
  // (although in parallel). But even though there is more work (on the order
  // of 2x), it is being done by two threads. Hopefully most of the difference
  // we see is due to lock contention and not false parallelism.
  //
  // Be warned that if the box is under heavy load, this will greatly skew
  // these results (scheduling overhead will begin to dwarf lock contention).
  // I'm not sure but I'd guess in Windtunnel this will mean large variance,
  // because I expect they load the boxes as much as they can?
  consumer.join();
  producer.join();
}

BENCHMARK_DRAW_LINE();

// The old way. Throw an exception, and rethrow to access it upstream.
void throwAndCatchImpl() {
  makeFuture()
      .then([](Try<Unit>&&){ throw std::runtime_error("oh no"); })
      .then([](Try<Unit>&& t) {
        try {
          t.value();
        } catch(const std::runtime_error& e) {
          // ...
          return;
        }
        CHECK(false);
      });
}

// Not much better. Throw an exception, and access it via the wrapper upstream.
// Actually a little worse due to wrapper overhead. then() won't know that the
// exception is a runtime_error, so will have to store it as an exception_ptr
// anyways. withException will therefore have to rethrow. Note that if we threw
// std::exception instead, we would see some wins, as that's the type then()
// will try to wrap, so no exception_ptrs/rethrows are necessary.
void throwAndCatchWrappedImpl() {
  makeFuture()
      .then([](Try<Unit>&&) { throw std::runtime_error("oh no"); })
      .then([](Try<Unit>&& t) {
        auto caught = t.withException<std::runtime_error>(
            [](const std::runtime_error& /* e */) {
              // ...
            });
        CHECK(caught);
      });
}

// Better. Wrap an exception, and rethrow to access it upstream.
void throwWrappedAndCatchImpl() {
  makeFuture()
      .then([](Try<Unit>&&){
        return makeFuture<Unit>(std::runtime_error("oh no"));
      })
      .then([](Try<Unit>&& t) {
        try {
          t.value();
        } catch(const std::runtime_error& e) {
          // ...
          return;
        }
        CHECK(false);
      });
}

// The new way. Wrap an exception, and access it via the wrapper upstream
void throwWrappedAndCatchWrappedImpl() {
  makeFuture()
      .then([](Try<Unit>&&) {
        return makeFuture<Unit>(std::runtime_error("oh no"));
      })
      .then([](Try<Unit>&& t) {
        auto caught = t.withException<std::runtime_error>(
            [](const std::runtime_error& /* e */) {
              // ...
            });
        CHECK(caught);
      });
}

// Simulate heavy contention on func
void contend(void(*func)()) {
  folly::BenchmarkSuspender s;
  const int N = 100;
  const int iters = 1000;
  pthread_barrier_t barrier;
  pthread_barrier_init(&barrier, nullptr, N+1);
  std::vector<std::thread> threads;
  for (int i = 0; i < N; i++) {
    threads.push_back(std::thread([&](){
      pthread_barrier_wait(&barrier);
      for (int j = 0; j < iters; j++) {
        func();
      }
    }));
  }
  pthread_barrier_wait(&barrier);
  s.dismiss();
  for (auto& t : threads) {
    t.join();
  }
  s.rehire();
  pthread_barrier_destroy(&barrier);
}

BENCHMARK(throwAndCatch) {
  throwAndCatchImpl();
}

BENCHMARK_RELATIVE(throwAndCatchWrapped) {
  throwAndCatchWrappedImpl();
}

BENCHMARK_RELATIVE(throwWrappedAndCatch) {
  throwWrappedAndCatchImpl();
}

BENCHMARK_RELATIVE(throwWrappedAndCatchWrapped) {
  throwWrappedAndCatchWrappedImpl();
}

BENCHMARK_DRAW_LINE();

BENCHMARK(throwAndCatchContended) {
  contend(throwAndCatchImpl);
}

BENCHMARK_RELATIVE(throwAndCatchWrappedContended) {
  contend(throwAndCatchWrappedImpl);
}

BENCHMARK_RELATIVE(throwWrappedAndCatchContended) {
  contend(throwWrappedAndCatchImpl);
}

BENCHMARK_RELATIVE(throwWrappedAndCatchWrappedContended) {
  contend(throwWrappedAndCatchWrappedImpl);
}

BENCHMARK_DRAW_LINE();

namespace {
struct Bulky {
  explicit Bulky(std::string message) : message_(message) {}
  std::string message() & {
    return message_;
  }
  std::string&& message() && {
    return std::move(message_);
  }

 private:
  std::string message_;
  std::array<int, 1024> ints_;
};
} // anonymous namespace

BENCHMARK(lvalue_get) {
  BenchmarkSuspender suspender;
  Optional<Future<Bulky>> future;
  future = makeFuture(Bulky("Hello"));
  suspender.dismissing([&] {
    std::string message = std::move(future.value()).get().message();
    doNotOptimizeAway(message);
  });
}

BENCHMARK_RELATIVE(rvalue_get) {
  BenchmarkSuspender suspender;
  Optional<Future<Bulky>> future;
  future = makeFuture(Bulky("Hello"));
  suspender.dismissing([&] {
    std::string message = std::move(future.value()).get().message();
    doNotOptimizeAway(message);
  });
}

InlineExecutor exe;

template <class T>
Future<T> fGen() {
  Promise<T> p;
  auto f = p.getFuture()
    .then([] (T&& t) {
      return std::move(t);
    })
    .then([] (T&& t) {
      return makeFuture(std::move(t));
    })
    .via(&exe)
    .then([] (T&& t) {
      return std::move(t);
    })
    .then([] (T&& t) {
      return makeFuture(std::move(t));
    });
  p.setValue(T());
  return f;
}

template <class T>
std::vector<Future<T>> fsGen() {
  std::vector<Future<T>> fs;
  for (auto i = 0; i < 10; i++) {
    fs.push_back(fGen<T>());
  }
  return fs;
}

template <class T>
void complexBenchmark() {
  collect(fsGen<T>());
  collectAll(fsGen<T>());
  collectAny(fsGen<T>());
  futures::map(fsGen<T>(), [] (const T& t) {
    return t;
  });
  futures::map(fsGen<T>(), [] (const T& t) {
    return makeFuture(T(t));
  });
}

BENCHMARK_DRAW_LINE();

template <size_t S>
struct Blob {
  char buf[S];
};

BENCHMARK(complexUnit) {
  complexBenchmark<Unit>();
}

BENCHMARK_RELATIVE(complexBlob4) {
  complexBenchmark<Blob<4>>();
}

BENCHMARK_RELATIVE(complexBlob8) {
  complexBenchmark<Blob<8>>();
}

BENCHMARK_RELATIVE(complexBlob64) {
  complexBenchmark<Blob<64>>();
}

BENCHMARK_RELATIVE(complexBlob128) {
  complexBenchmark<Blob<128>>();
}

BENCHMARK_RELATIVE(complexBlob256) {
  complexBenchmark<Blob<256>>();
}

BENCHMARK_RELATIVE(complexBlob512) {
  complexBenchmark<Blob<512>>();
}

BENCHMARK_RELATIVE(complexBlob1024) {
  complexBenchmark<Blob<1024>>();
}

BENCHMARK_RELATIVE(complexBlob2048) {
  complexBenchmark<Blob<2048>>();
}

BENCHMARK_RELATIVE(complexBlob4096) {
  complexBenchmark<Blob<4096>>();
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  folly::runBenchmarks();
  return 0;
}
<commit_msg>Missed l-value calls to future::then in Benchmark.cpp<commit_after>/*
 * Copyright 2014-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/Benchmark.h>
#include <folly/executors/InlineExecutor.h>
#include <folly/futures/Future.h>
#include <folly/futures/Promise.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/Semaphore.h>
#include <folly/synchronization/Baton.h>

#include <vector>

using namespace folly;

namespace {

template <class T>
T incr(Try<T>&& t) {
  return t.value() + 1;
}

void someThens(size_t n) {
  auto f = makeFuture<int>(42);
  for (size_t i = 0; i < n; i++) {
    f = std::move(f).then(incr<int>);
  }
}

} // namespace

BENCHMARK(constantFuture) {
  makeFuture(42);
}

BENCHMARK_RELATIVE(promiseAndFuture) {
  Promise<int> p;
  Future<int> f = p.getFuture();
  p.setValue(42);
  f.value();
}

BENCHMARK_RELATIVE(withThen) {
  Promise<int> p;
  Future<int> f = p.getFuture().then(incr<int>);
  p.setValue(42);
  f.value();
}

// thens
BENCHMARK_DRAW_LINE();

BENCHMARK(oneThen) {
  someThens(1);
}

// look for >= 50% relative
BENCHMARK_RELATIVE(twoThens) {
  someThens(2);
}

// look for >= 25% relative
BENCHMARK_RELATIVE(fourThens) {
  someThens(4);
}

// look for >= 1% relative
BENCHMARK_RELATIVE(hundredThens) {
  someThens(100);
}

// Lock contention. Although in practice fulfills tend to be temporally
// separate from then()s, still sometimes they will be concurrent. So the
// higher this number is, the better.
BENCHMARK_DRAW_LINE();

BENCHMARK(no_contention) {
  std::vector<Promise<int>> promises(10000);
  std::vector<Future<int>> futures;
  std::thread producer, consumer;

  BENCHMARK_SUSPEND {
    folly::Baton<> b1, b2;
    for (auto& p : promises) {
      futures.push_back(p.getFuture());
    }

    consumer = std::thread([&]{
      b1.post();
      for (auto& f : futures) {
        std::move(f).then(incr<int>);
      }
    });
    consumer.join();

    producer = std::thread([&]{
      b2.post();
      for (auto& p : promises) {
        p.setValue(42);
      }
    });

    b1.wait();
    b2.wait();
  }

  // The only thing we are measuring is how long fulfill + callbacks take
  producer.join();
}

BENCHMARK_RELATIVE(contention) {
  std::vector<Promise<int>> promises(10000);
  std::vector<Future<int>> futures;
  std::thread producer, consumer;
  sem_t sem;
  sem_init(&sem, 0, 0);

  BENCHMARK_SUSPEND {
    folly::Baton<> b1, b2;
    for (auto& p : promises) {
      futures.push_back(p.getFuture());
    }

    consumer = std::thread([&]{
      b1.post();
      for (auto& f : futures) {
        sem_wait(&sem);
        std::move(f).then(incr<int>);
      }
    });

    producer = std::thread([&]{
      b2.post();
      for (auto& p : promises) {
        sem_post(&sem);
        p.setValue(42);
      }
    });

    b1.wait();
    b2.wait();
  }

  // The astute reader will notice that we're not *precisely* comparing apples
  // to apples here. Well, maybe it's like comparing Granny Smith to
  // Braeburn or something. In the serial version, we waited for the futures
  // to be all set up, but here we are probably still doing that work
  // (although in parallel). But even though there is more work (on the order
  // of 2x), it is being done by two threads. Hopefully most of the difference
  // we see is due to lock contention and not false parallelism.
  //
  // Be warned that if the box is under heavy load, this will greatly skew
  // these results (scheduling overhead will begin to dwarf lock contention).
  // I'm not sure but I'd guess in Windtunnel this will mean large variance,
  // because I expect they load the boxes as much as they can?
  consumer.join();
  producer.join();
}

BENCHMARK_DRAW_LINE();

// The old way. Throw an exception, and rethrow to access it upstream.
void throwAndCatchImpl() {
  makeFuture()
      .then([](Try<Unit>&&){ throw std::runtime_error("oh no"); })
      .then([](Try<Unit>&& t) {
        try {
          t.value();
        } catch(const std::runtime_error& e) {
          // ...
          return;
        }
        CHECK(false);
      });
}

// Not much better. Throw an exception, and access it via the wrapper upstream.
// Actually a little worse due to wrapper overhead. then() won't know that the
// exception is a runtime_error, so will have to store it as an exception_ptr
// anyways. withException will therefore have to rethrow. Note that if we threw
// std::exception instead, we would see some wins, as that's the type then()
// will try to wrap, so no exception_ptrs/rethrows are necessary.
void throwAndCatchWrappedImpl() {
  makeFuture()
      .then([](Try<Unit>&&) { throw std::runtime_error("oh no"); })
      .then([](Try<Unit>&& t) {
        auto caught = t.withException<std::runtime_error>(
            [](const std::runtime_error& /* e */) {
              // ...
            });
        CHECK(caught);
      });
}

// Better. Wrap an exception, and rethrow to access it upstream.
void throwWrappedAndCatchImpl() {
  makeFuture()
      .then([](Try<Unit>&&){
        return makeFuture<Unit>(std::runtime_error("oh no"));
      })
      .then([](Try<Unit>&& t) {
        try {
          t.value();
        } catch(const std::runtime_error& e) {
          // ...
          return;
        }
        CHECK(false);
      });
}

// The new way. Wrap an exception, and access it via the wrapper upstream
void throwWrappedAndCatchWrappedImpl() {
  makeFuture()
      .then([](Try<Unit>&&) {
        return makeFuture<Unit>(std::runtime_error("oh no"));
      })
      .then([](Try<Unit>&& t) {
        auto caught = t.withException<std::runtime_error>(
            [](const std::runtime_error& /* e */) {
              // ...
            });
        CHECK(caught);
      });
}

// Simulate heavy contention on func
void contend(void(*func)()) {
  folly::BenchmarkSuspender s;
  const int N = 100;
  const int iters = 1000;
  pthread_barrier_t barrier;
  pthread_barrier_init(&barrier, nullptr, N+1);
  std::vector<std::thread> threads;
  for (int i = 0; i < N; i++) {
    threads.push_back(std::thread([&](){
      pthread_barrier_wait(&barrier);
      for (int j = 0; j < iters; j++) {
        func();
      }
    }));
  }
  pthread_barrier_wait(&barrier);
  s.dismiss();
  for (auto& t : threads) {
    t.join();
  }
  s.rehire();
  pthread_barrier_destroy(&barrier);
}

BENCHMARK(throwAndCatch) {
  throwAndCatchImpl();
}

BENCHMARK_RELATIVE(throwAndCatchWrapped) {
  throwAndCatchWrappedImpl();
}

BENCHMARK_RELATIVE(throwWrappedAndCatch) {
  throwWrappedAndCatchImpl();
}

BENCHMARK_RELATIVE(throwWrappedAndCatchWrapped) {
  throwWrappedAndCatchWrappedImpl();
}

BENCHMARK_DRAW_LINE();

BENCHMARK(throwAndCatchContended) {
  contend(throwAndCatchImpl);
}

BENCHMARK_RELATIVE(throwAndCatchWrappedContended) {
  contend(throwAndCatchWrappedImpl);
}

BENCHMARK_RELATIVE(throwWrappedAndCatchContended) {
  contend(throwWrappedAndCatchImpl);
}

BENCHMARK_RELATIVE(throwWrappedAndCatchWrappedContended) {
  contend(throwWrappedAndCatchWrappedImpl);
}

BENCHMARK_DRAW_LINE();

namespace {
struct Bulky {
  explicit Bulky(std::string message) : message_(message) {}
  std::string message() & {
    return message_;
  }
  std::string&& message() && {
    return std::move(message_);
  }

 private:
  std::string message_;
  std::array<int, 1024> ints_;
};
} // anonymous namespace

BENCHMARK(lvalue_get) {
  BenchmarkSuspender suspender;
  Optional<Future<Bulky>> future;
  future = makeFuture(Bulky("Hello"));
  suspender.dismissing([&] {
    std::string message = std::move(future.value()).get().message();
    doNotOptimizeAway(message);
  });
}

BENCHMARK_RELATIVE(rvalue_get) {
  BenchmarkSuspender suspender;
  Optional<Future<Bulky>> future;
  future = makeFuture(Bulky("Hello"));
  suspender.dismissing([&] {
    std::string message = std::move(future.value()).get().message();
    doNotOptimizeAway(message);
  });
}

InlineExecutor exe;

template <class T>
Future<T> fGen() {
  Promise<T> p;
  auto f = p.getFuture()
    .then([] (T&& t) {
      return std::move(t);
    })
    .then([] (T&& t) {
      return makeFuture(std::move(t));
    })
    .via(&exe)
    .then([] (T&& t) {
      return std::move(t);
    })
    .then([] (T&& t) {
      return makeFuture(std::move(t));
    });
  p.setValue(T());
  return f;
}

template <class T>
std::vector<Future<T>> fsGen() {
  std::vector<Future<T>> fs;
  for (auto i = 0; i < 10; i++) {
    fs.push_back(fGen<T>());
  }
  return fs;
}

template <class T>
void complexBenchmark() {
  collect(fsGen<T>());
  collectAll(fsGen<T>());
  collectAny(fsGen<T>());
  futures::map(fsGen<T>(), [] (const T& t) {
    return t;
  });
  futures::map(fsGen<T>(), [] (const T& t) {
    return makeFuture(T(t));
  });
}

BENCHMARK_DRAW_LINE();

template <size_t S>
struct Blob {
  char buf[S];
};

BENCHMARK(complexUnit) {
  complexBenchmark<Unit>();
}

BENCHMARK_RELATIVE(complexBlob4) {
  complexBenchmark<Blob<4>>();
}

BENCHMARK_RELATIVE(complexBlob8) {
  complexBenchmark<Blob<8>>();
}

BENCHMARK_RELATIVE(complexBlob64) {
  complexBenchmark<Blob<64>>();
}

BENCHMARK_RELATIVE(complexBlob128) {
  complexBenchmark<Blob<128>>();
}

BENCHMARK_RELATIVE(complexBlob256) {
  complexBenchmark<Blob<256>>();
}

BENCHMARK_RELATIVE(complexBlob512) {
  complexBenchmark<Blob<512>>();
}

BENCHMARK_RELATIVE(complexBlob1024) {
  complexBenchmark<Blob<1024>>();
}

BENCHMARK_RELATIVE(complexBlob2048) {
  complexBenchmark<Blob<2048>>();
}

BENCHMARK_RELATIVE(complexBlob4096) {
  complexBenchmark<Blob<4096>>();
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  folly::runBenchmarks();
  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

// Moose includes
#include "RayTracing.h"
#include "LineSegment.h"

// libMesh includes
#include "libmesh/plane.h"
#include "libmesh/point.h"
#include "libmesh/mesh.h"
#include "libmesh/point_locator_base.h"
#include "libmesh/elem.h"

namespace Moose
{

/**
 * Figure out which (if any) side of an Elem is intersected by a line.
 *
 * @param elem The elem to search
 * @param not_side A side to _not_ search (Use -1 if you want to search all sides)
 * @return The side that is intersected by the line.  Will return -1 if it doesn't intersect any side
 */
int sideIntersectedByLine(const Elem * elem, int not_side, const LineSegment & line_segment)
{
  unsigned int n_sides = elem->n_sides();

  // A Point to pass to the intersection method
  Point intersection_point;

  // Whether or not they intersect
  bool intersect = false;

  unsigned int dim = elem->dim();

  for (unsigned int i=0; i<n_sides; i++)
  {
    if (i == not_side) // Don't search the "not_side"
      continue;

    // Get a simplified side element
    AutoPtr<Elem> side_elem = elem->side(i);

    if (dim == 3)
    {
      // Make a plane out of the first three nodes on the side
      Plane plane(side_elem->point(0), side_elem->point(1), side_elem->point(2));

      // See if they intersect
      intersect = line_segment.intersect(plane, intersection_point);
    }
    else if (dim == 2)
    {
      // Make a Line Segment out of the first two nodes on the side
      LineSegment side_segment(side_elem->point(0), side_elem->point(1));

      // See if they intersect
      intersect = line_segment.intersect(side_segment, intersection_point);
    }
    else // 1D
    {
      // See if the line segment contains the point
      intersect = line_segment.contains_point(side_elem->point(0));

      // If it does then save off that one point as the intersection point
      if (intersect)
        intersection_point = side_elem->point(0);
    }

    if (intersect)
      if (side_elem->contains_point(intersection_point))
        return i;
  }

  // Didn't find one
  return -1;
}

/**
 * Returns the side number for elem that neighbor is on
 *
 * Returns -1 if the neighbor can't be found to be a neighbor
 */
int sideNeighborIsOn(const Elem * elem, const Elem * neighbor)
{
  unsigned int n_sides = elem->n_sides();

  for (unsigned int i=0; i<n_sides; i++)
  {
    if (elem->neighbor(i) == neighbor)
      return i;
  }

  return -1;
}

/**
 * Recursively find all elements intersected by a line segment
 *
 * Works by moving from one element to the next _through_ the side of the current element.
 * This means that (other than for the first element) there is always an incoming_side
 * that is the reason we ended up in this element in the first place.  Search all the _other_
 * sides to see if there is a next element...
 *
 * @param line_segment the LineSegment to intersect
 * @param current_elem The current element that needs to be searched
 * @param incoming_side The side of the current element that was intersected by the LineSegment that brought us here
 * @param intersected_elems The output
 */
void recursivelyFindElementsIntersectedByLine(const LineSegment & line_segment, const Elem * current_elem, int incoming_side, std::vector<Elem *> & intersected_elems)
{
  // Find the side of this element that the LineSegment intersects... while ignoring the incoming side (we don't want to move backward!)
  int intersected_side = sideIntersectedByLine(current_elem, incoming_side, line_segment);

  if (intersected_side != -1) // -1 means that we didn't find any side
  {
    // Get the neighbor on that side
    Elem * neighbor = current_elem->neighbor(intersected_side);

    if (neighbor)
    {
      // Add it to the list
      intersected_elems.push_back(neighbor);

      // Note: This is finding the side the current_elem is on for the neighbor.  That's the "incoming_side" for the neighbor
      int incoming_side = sideNeighborIsOn(neighbor, current_elem);

      // Recurse
      recursivelyFindElementsIntersectedByLine(line_segment, neighbor, incoming_side, intersected_elems);

      return;
    }
  }

  // Finished... return out!
  return;
}

void elementsIntersectedByLine(const Point & p0, const Point & p1, const MeshBase & mesh, std::vector<Elem *> & intersected_elems)
{
  // Make sure our list is clear
  intersected_elems.clear();

  // Grab a PointLocator for finding the first element:
  const PointLocatorBase & pl = mesh.point_locator();

  // Find the starting element
  const Elem * first_elem = pl(p0);

  // Quick return if can't even locate the first element.
  if (!first_elem)
    return;

  // Make a LineSegment object out of our two points for ease:
  LineSegment line_segment = LineSegment(p0, p1);

  // Find 'em!
  recursivelyFindElementsIntersectedByLine(line_segment, first_elem, -1, intersected_elems);
}

}
<commit_msg>Silence compiler warning about comparison of integers with different sign.<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

// Moose includes
#include "RayTracing.h"
#include "LineSegment.h"

// libMesh includes
#include "libmesh/plane.h"
#include "libmesh/point.h"
#include "libmesh/mesh.h"
#include "libmesh/point_locator_base.h"
#include "libmesh/elem.h"

namespace Moose
{

/**
 * Figure out which (if any) side of an Elem is intersected by a line.
 *
 * @param elem The elem to search
 * @param not_side A side to _not_ search (Use -1 if you want to search all sides)
 * @return The side that is intersected by the line.  Will return -1 if it doesn't intersect any side
 */
int sideIntersectedByLine(const Elem * elem, int not_side, const LineSegment & line_segment)
{
  unsigned int n_sides = elem->n_sides();

  // A Point to pass to the intersection method
  Point intersection_point;

  // Whether or not they intersect
  bool intersect = false;

  unsigned int dim = elem->dim();

  for (unsigned int i=0; i<n_sides; i++)
  {
    if (static_cast<int>(i) == not_side) // Don't search the "not_side"
      continue;

    // Get a simplified side element
    AutoPtr<Elem> side_elem = elem->side(i);

    if (dim == 3)
    {
      // Make a plane out of the first three nodes on the side
      Plane plane(side_elem->point(0), side_elem->point(1), side_elem->point(2));

      // See if they intersect
      intersect = line_segment.intersect(plane, intersection_point);
    }
    else if (dim == 2)
    {
      // Make a Line Segment out of the first two nodes on the side
      LineSegment side_segment(side_elem->point(0), side_elem->point(1));

      // See if they intersect
      intersect = line_segment.intersect(side_segment, intersection_point);
    }
    else // 1D
    {
      // See if the line segment contains the point
      intersect = line_segment.contains_point(side_elem->point(0));

      // If it does then save off that one point as the intersection point
      if (intersect)
        intersection_point = side_elem->point(0);
    }

    if (intersect)
      if (side_elem->contains_point(intersection_point))
        return i;
  }

  // Didn't find one
  return -1;
}

/**
 * Returns the side number for elem that neighbor is on
 *
 * Returns -1 if the neighbor can't be found to be a neighbor
 */
int sideNeighborIsOn(const Elem * elem, const Elem * neighbor)
{
  unsigned int n_sides = elem->n_sides();

  for (unsigned int i=0; i<n_sides; i++)
  {
    if (elem->neighbor(i) == neighbor)
      return i;
  }

  return -1;
}

/**
 * Recursively find all elements intersected by a line segment
 *
 * Works by moving from one element to the next _through_ the side of the current element.
 * This means that (other than for the first element) there is always an incoming_side
 * that is the reason we ended up in this element in the first place.  Search all the _other_
 * sides to see if there is a next element...
 *
 * @param line_segment the LineSegment to intersect
 * @param current_elem The current element that needs to be searched
 * @param incoming_side The side of the current element that was intersected by the LineSegment that brought us here
 * @param intersected_elems The output
 */
void recursivelyFindElementsIntersectedByLine(const LineSegment & line_segment, const Elem * current_elem, int incoming_side, std::vector<Elem *> & intersected_elems)
{
  // Find the side of this element that the LineSegment intersects... while ignoring the incoming side (we don't want to move backward!)
  int intersected_side = sideIntersectedByLine(current_elem, incoming_side, line_segment);

  if (intersected_side != -1) // -1 means that we didn't find any side
  {
    // Get the neighbor on that side
    Elem * neighbor = current_elem->neighbor(intersected_side);

    if (neighbor)
    {
      // Add it to the list
      intersected_elems.push_back(neighbor);

      // Note: This is finding the side the current_elem is on for the neighbor.  That's the "incoming_side" for the neighbor
      int incoming_side = sideNeighborIsOn(neighbor, current_elem);

      // Recurse
      recursivelyFindElementsIntersectedByLine(line_segment, neighbor, incoming_side, intersected_elems);

      return;
    }
  }

  // Finished... return out!
  return;
}

void elementsIntersectedByLine(const Point & p0, const Point & p1, const MeshBase & mesh, std::vector<Elem *> & intersected_elems)
{
  // Make sure our list is clear
  intersected_elems.clear();

  // Grab a PointLocator for finding the first element:
  const PointLocatorBase & pl = mesh.point_locator();

  // Find the starting element
  const Elem * first_elem = pl(p0);

  // Quick return if can't even locate the first element.
  if (!first_elem)
    return;

  // Make a LineSegment object out of our two points for ease:
  LineSegment line_segment = LineSegment(p0, p1);

  // Find 'em!
  recursivelyFindElementsIntersectedByLine(line_segment, first_elem, -1, intersected_elems);
}

}
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 *  Created on: 23.03.2017 г.
 *      Author: trifon
 */

#include <iostream>
#include <cstring>
#include "player.h"

void anonymousPrint(Player p) {
	p.print();
	p.setName("Анонимен");
	p.print();
}

void testPlayer() {
	Player p1("Гандалф Сивия", 45);
	p1.print();
	Player p2 = p1;
	p2.print();
	p2.setName("Гандалф Белия");
	p1.print();
	p2.print();
	anonymousPrint(p2);
	p1.print();
	p2.print();
	// !!! strcpy(p1.getName(), "PWNED!!11!");
	// !!! p1.print();
	Player p3 = "Кетнис Евърдийн";
	// Player p3("Кетнис Евърдийн");
	p3.print();
	// !!! Player p4 = 5;
	anonymousPrint("Фродо");
}

void testDestructor() {
	for(int i = 0; i < 1E8; i++) {
		Player p("Гандалф Сивия", 45);
		p.setScore(50);
	}

}

int main() {
	// testPlayer();
	testDestructor();
	return 0;
}

<commit_msg>Примери за Memory leak При липса на деструктор<commit_after>/*
 * main.cpp
 *
 *  Created on: 23.03.2017 г.
 *      Author: trifon
 */

#include <iostream>
#include <cstring>
#include "player.h"

void anonymousPrint(Player p) {
	p.print();
	p.setName("Анонимен");
	p.print();
}

void testPlayer() {
	Player p1("Гандалф Сивия", 45);
	p1.print();
	Player p2 = p1;
	p2.print();
	p2.setName("Гандалф Белия");
	p1.print();
	p2.print();
	anonymousPrint(p2);
	p1.print();
	p2.print();
	// !!! strcpy(p1.getName(), "PWNED!!11!");
	// !!! p1.print();
	Player p3 = "Кетнис Евърдийн";
	// Player p3("Кетнис Евърдийн");
	p3.print();
	// !!! Player p4 = 5;
	anonymousPrint("Фродо");
}

void testDestructor() {
	for(int i = 0; i < 1E8; i++) {
		Player p("Гандалф Сивия", 45);
		p.setScore(50);
		// !!! delete p.getName();
	}

	for(int i = 0; i < 1E8; i++) {
		Player* p = new Player[10];
		delete[] p;
	}

	Player* pa[10];
	for(int i = 0; i < 10; i++) {
		pa[i] = new Player("Орк");
		pa[i]->print();
	}

	delete pa[2];
	delete pa[8];

	for(int i = 0; i < 10; i++)
		if (i != 2 && i != 8)
			delete pa[i];
}

int main() {
	// testPlayer();
	testDestructor();
	return 0;
}

<|endoftext|>


<commit_before>#include "fastlib/fastlib.h"

int main(int argc, char *argv[]) {
  fx_init(argc, argv);

  const char *data = fx_param_str(NULL, "data", NULL);

  Matrix X;
  data::Load(data, &X);

  index_t n_dims = X.n_rows();
  index_t n_points = X.n_cols();

  fx_done();

  return 0;
}
<commit_msg>updated niche/fastica<commit_after>#include "fastlib/fastlib.h"

void whiten(Matrix X, Matrix &X_whitened) {
  Matrix X_transpose, X_squared, D, E, E_transpose, X_temp, X_temp2;
  Vector D_vector;

  la::TransposeInit(X, &X_transpose);
  MulInit(X, X_transpose, &X_squared);

  la::EigenvectorsInit(X_squared, &D_vector, &E);
  la::TransposeInit(E, &E_transpose);
  D.InitDiagonal(D_vector);
  int n_dims = D.n_rows();
  for(int i = 0; i < n_dims; i++) {
    D.set(i, i, pow(D.get(i, i), -.5));
  }

  MulInit(E, D, &X_temp);
  MulInit(X_temp, E_transpose, &X_temp2);
  MulInit(X_temp2, X, &X_whitened);
}

int main(int argc, char *argv[]) {
  fx_init(argc, argv);

  const char *data = fx_param_str(NULL, "data", NULL);

  Matrix X, whitenedX;
  data::Load(data, &X);

  index_t n_dims = X.n_rows();
  index_t n_points = X.n_cols();

  whiten(X, &X_whitened);

  fx_done();

  return 0;
}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  timit_nn.cc
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  06/07/2007 02:05:14 PM EDT
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Nikolaos Vasiloglou (NV), nvasil@ieee.org
 *        Company:  Georgia Tech Fastlab-ESP Lab
 *
 * =====================================================================================
 */

#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include "fastlib/fastlib.h"
#include "u/nvasil/mmanager/memory_manager.h"
#include "u/nvasil/dataset/binary_dataset.h"
#include "u/nvasil/tree/binary_kd_tree_mmapmm.h"

struct Parameters {
  int32 dimension_;
	int64 num_of_points_;
	std::string train_file_;
	std::string test_file_;
	std::string out_file_;
	int32 knns_;
	std::string memory_file_;
  BinaryDataset<float32> train_data_;
  BinaryDataset<float32> test_data_;
	uint64 capacity_;
};

template<typename TREE>
void DuallTreeAllNearestNeighborsSpecializedForKnn(Parameters &args);

int main(int argc, char *argv[]) {
	Parameters args;
	// initialize command line parameter
	fx_init(argc, argv);
  args.train_file_=fx_param_str_req(NULL, "train_file");
  args.test_file_=fx_param_str_req(NULL, "test_file");
  args.knns_=fx_param_int(NULL, "knns",5);
	args.out_file_=fx_param_str_req(NULL, "out_file");
  args.memory_file_=fx_param_str_req(NULL, "memory_file");
	args.capacity_=fx_param_int(NULL, "capacity", 16777216);
 	if (sizeof(index_t)==sizeof(int32)) {
	  NONFATAL("index_t is int32, good for small scale problems");
	} else {
		if (sizeof(index_t)==sizeof(int64)) {
	    NONFATAL("index_t is int64, good for large scale problems");
		}
	}

	NONFATAL("Creating swap file...\n");
	mmapmm::MemoryManager<false>::allocator_ =
		    new mmapmm::MemoryManager<false>();
    mmapmm::MemoryManager<false>::
			  allocator_->set_capacity(args.capacity_);
		mmapmm::MemoryManager<false>::
			  allocator_->set_pool_name(args.memory_file_);
		mmapmm::MemoryManager<false>::allocator_->Init();
    DuallTreeAllNearestNeighborsSpecializedForKnn<
			    BinaryKdTreeMMAPMMKnnNode_t>(args);
	fx_format_result(fx_root, "success", "%d", 1);
	fx_done();
}

template<typename TREE>
void DuallTreeAllNearestNeighborsSpecializedForKnn(Parameters &args) {
  TREE train_tree;
	TREE test_tree;
	NONFATAL("Procceding with the specialized method for knn node..\n");
  if (args.train_file_!=args.test_file_) {
	  args.train_data_.Init(args.train_file_);
	  train_tree.Init(&args.train_data_);
	  fx_timer_start(fx_root, "train_tree_build");
    NONFATAL("Building the training (reference) tree...\n");
	  fflush(stdout);
	  train_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "train_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Training (Reference) tree \n %s\n", train_tree.Statistics().c_str());
	  args.train_data_.Destruct();
	  args.test_data_.Init(args.test_file_);
	  test_tree.Init(&args.test_data_);
	  test_tree.set_knns(args.knns_);
	  NONFATAL("Building the test (query) tree...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "test_tree_build");
	  test_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "test_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Test (Query) tree \n %s\n", test_tree.Statistics().c_str());
	  args.test_data_.Destruct();
    if (train_tree.get_dimension()!=test_tree.get_dimension()) {
	    FATAL("Train set has different dimension %i than Test set %i\n",
			  	  args.train_data_.get_dimension(),
			      args.test_data_.get_dimension());
		}
	  NONFATAL("Computing all nearest neighbors...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "dualltree");
	  train_tree.AllNearestNeighbors(test_tree.get_parent(), args.knns_);
	  fx_timer_stop(fx_root, "dualltree");
	  NONFATAL("Collecting results....\n");
	  fx_timer_start(fx_root, "collecting_results");
	  test_tree.CollectKNearestNeighborWithFwriteText(args.out_file_.c_str());
	  fx_timer_stop(fx_root, "collecting_results");
	} else {
	  NONFATAL("Training and test tree are the same\n" );
		args.train_data_.Init(args.test_file_);
	  train_tree.Init(&args.train_data_);
    train_tree.set_knns(args.knns_);
	  fx_timer_start(fx_root, "train_tree_build");
    NONFATAL("Building the training (reference) tree...\n");
	  fflush(stdout);
	  train_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "train_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Training (Reference) tree \n %s\n", train_tree.Statistics().c_str());
	  args.train_data_.Destruct();
    NONFATAL("Computing all nearest neighbors...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "dualltree");
	  train_tree.AllNearestNeighbors(train_tree.get_parent(), args.knns_);
	  fx_timer_stop(fx_root, "dualltree");
	  NONFATAL("Collecting results....\n");
	  fx_timer_start(fx_root, "collecting_results");
	  train_tree.CollectKNearestNeighborWithFwriteText(args.out_file_.c_str());
	  fx_timer_stop(fx_root, "collecting_results");
	}
}

<commit_msg>Added documentation<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  timit_nn.cc
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  06/07/2007 02:05:14 PM EDT
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Nikolaos Vasiloglou (NV), nvasil@ieee.org
 *        Company:  Georgia Tech Fastlab-ESP Lab
 *
 * =====================================================================================
 */

#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include "fastlib/fastlib.h"
#include "u/nvasil/mmanager/memory_manager.h"
#include "u/nvasil/dataset/binary_dataset.h"
#include "u/nvasil/tree/binary_kd_tree_mmapmm.h"

struct Parameters {
	std::string train_file_;
	std::string test_file_;
	std::string out_file_;
	int32 knns_;
	std::string memory_file_;
  BinaryDataset<float32> train_data_;
  BinaryDataset<float32> test_data_;
	uint64 capacity_;
};
std::string Usage();
template<typename TREE>
void DuallTreeAllNearestNeighborsSpecializedForKnn(Parameters &args);

int main(int argc, char *argv[]) {
	Parameters args;
	// initialize command line parameter
	fx_init(argc, argv);
	if (fx_param_exists(NULL, "help")) {
	  printf("%s\n", Usage().c_str());
		return -1;
	}
  args.train_file_=fx_param_str(NULL, "train_file", "");
  args.test_file_=fx_param_str(NULL, "test_file", "");
  args.knns_=fx_param_int(NULL, "knns",5);
	args.out_file_=fx_param_str(NULL, "out_file", "allnn");
  args.memory_file_=fx_param_str(NULL, "memory_file", "temp_mem");
	args.capacity_=fx_param_int(NULL, "capacity", 16777216);
 	if (sizeof(index_t)==sizeof(int32)) {
	  NONFATAL("index_t is int32, good for small scale problems");
	} else {
		if (sizeof(index_t)==sizeof(int64)) {
	    NONFATAL("index_t is int64, good for large scale problems");
		}
	}

	NONFATAL("Creating swap file...\n");
	mmapmm::MemoryManager<false>::allocator_ =
		    new mmapmm::MemoryManager<false>();
    mmapmm::MemoryManager<false>::
			  allocator_->set_capacity(args.capacity_);
		mmapmm::MemoryManager<false>::
			  allocator_->set_pool_name(args.memory_file_);
		mmapmm::MemoryManager<false>::allocator_->Init();
    DuallTreeAllNearestNeighborsSpecializedForKnn<
			    BinaryKdTreeMMAPMMKnnNode_t>(args);
	fx_format_result(fx_root, "success", "%d", 1);
	fx_done();
}

template<typename TREE>
void DuallTreeAllNearestNeighborsSpecializedForKnn(Parameters &args) {
  TREE train_tree;
	TREE test_tree;
	NONFATAL("Procceding with the specialized method for knn node..\n");
  if (args.train_file_!=args.test_file_) {
	  args.train_data_.Init(args.train_file_);
	  train_tree.Init(&args.train_data_);
	  fx_timer_start(fx_root, "train_tree_build");
    NONFATAL("Building the training (reference) tree...\n");
	  fflush(stdout);
	  train_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "train_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Training (Reference) tree \n %s\n", train_tree.Statistics().c_str());
	  args.train_data_.Destruct();
	  args.test_data_.Init(args.test_file_);
	  test_tree.Init(&args.test_data_);
	  test_tree.set_knns(args.knns_);
	  NONFATAL("Building the test (query) tree...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "test_tree_build");
	  test_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "test_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Test (Query) tree \n %s\n", test_tree.Statistics().c_str());
	  args.test_data_.Destruct();
    if (train_tree.get_dimension()!=test_tree.get_dimension()) {
	    FATAL("Train set has different dimension %i than Test set %i\n",
			  	  args.train_data_.get_dimension(),
			      args.test_data_.get_dimension());
		}
	  NONFATAL("Computing all nearest neighbors...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "dualltree");
	  train_tree.AllNearestNeighbors(test_tree.get_parent(), args.knns_);
	  fx_timer_stop(fx_root, "dualltree");
	  NONFATAL("Collecting results....\n");
	  fx_timer_start(fx_root, "collecting_results");
	  test_tree.CollectKNearestNeighborWithFwriteText(args.out_file_.c_str());
	  fx_timer_stop(fx_root, "collecting_results");
	} else {
	  NONFATAL("Training and test tree are the same\n" );
		args.train_data_.Init(args.test_file_);
	  train_tree.Init(&args.train_data_);
    train_tree.set_knns(args.knns_);
	  fx_timer_start(fx_root, "train_tree_build");
    NONFATAL("Building the training (reference) tree...\n");
	  fflush(stdout);
	  train_tree.BuildDepthFirst();
	  fx_timer_stop(fx_root, "train_tree_build");
    NONFATAL("Memory usage: %llu\n",
	          (unsigned long long)TREE::Allocator_t::allocator_->get_usage());
	  NONFATAL("Training (Reference) tree \n %s\n", train_tree.Statistics().c_str());
	  args.train_data_.Destruct();
    NONFATAL("Computing all nearest neighbors...\n");
	  fflush(stdout);
	  fx_timer_start(fx_root, "dualltree");
	  train_tree.AllNearestNeighbors(train_tree.get_parent(), args.knns_);
	  fx_timer_stop(fx_root, "dualltree");
	  NONFATAL("Collecting results....\n");
	  fx_timer_start(fx_root, "collecting_results");
	  train_tree.CollectKNearestNeighborWithFwriteText(args.out_file_.c_str());
	  fx_timer_stop(fx_root, "collecting_results");
	}
}
std::string Usage() {
  std::string ret =
		string("Computing all k-nearest neighbors with dual tree method...\n") +
		string("timit_nn --option=value\n")+
	  string("--train_file :  the dataset that contains the training data (reference)\n")+
	  string("--test_file  :  the dataset that contains the test data (query)\n")+
		string("--out_file   :  stores the results in a text file, usually big\n")+
		string("--memory_file:  the file wher the tree will be stored\n")+
		string("--knns       :  number of neighbors default is 5\n")+
		string("--capacity   :  the capacity of the memory file, keep it big enough\n");
	 return ret;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "CppUTest/TestHarness.h"
#include "CppUTest/TestMemoryAllocator.h"
#include "CppUTest/PlatformSpecificFunctions.h"
#include "CppUTest/MemoryLeakDetector.h"

static char* checkedMalloc(size_t size)
{
    char* mem = (char*) PlatformSpecificMalloc(size);
    if (mem == 0)
    FAIL("malloc returned null pointer");
    return mem;
}

static TestMemoryAllocator* currentNewAllocator = 0;
static TestMemoryAllocator* currentNewArrayAllocator = 0;
static TestMemoryAllocator* currentMallocAllocator = 0;

void setCurrentNewAllocator(TestMemoryAllocator* allocator)
{
    currentNewAllocator = allocator;
}

TestMemoryAllocator* getCurrentNewAllocator()
{
    if (currentNewAllocator == 0) setCurrentNewAllocatorToDefault();
    return currentNewAllocator;
}

void setCurrentNewAllocatorToDefault()
{
    currentNewAllocator = defaultNewAllocator();
}

TestMemoryAllocator* defaultNewAllocator()
{
    static TestMemoryAllocator allocator("Standard New Allocator", "new", "delete");
    return &allocator;
}

void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator)
{
    currentNewArrayAllocator = allocator;
}

TestMemoryAllocator* getCurrentNewArrayAllocator()
{
    if (currentNewArrayAllocator == 0) setCurrentNewArrayAllocatorToDefault();
    return currentNewArrayAllocator;
}

void setCurrentNewArrayAllocatorToDefault()
{
    currentNewArrayAllocator = defaultNewArrayAllocator();
}

TestMemoryAllocator* defaultNewArrayAllocator()
{
    static TestMemoryAllocator allocator("Standard New [] Allocator", "new []", "delete []");
    return &allocator;
}

void setCurrentMallocAllocator(TestMemoryAllocator* allocator)
{
    currentMallocAllocator = allocator;
}

TestMemoryAllocator* getCurrentMallocAllocator()
{
    if (currentMallocAllocator == 0) setCurrentMallocAllocatorToDefault();
    return currentMallocAllocator;
}

void setCurrentMallocAllocatorToDefault()
{
    currentMallocAllocator = defaultMallocAllocator();
}

TestMemoryAllocator* defaultMallocAllocator()
{
    static TestMemoryAllocator allocator("Standard Malloc Allocator", "malloc", "free");
    return &allocator;
}

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

TestMemoryAllocator::TestMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
    : name_(name_str), alloc_name_(alloc_name_str), free_name_(free_name_str), hasBeenDestroyed_(false)
{
}

TestMemoryAllocator::~TestMemoryAllocator()
{
    hasBeenDestroyed_ = true;
}

bool TestMemoryAllocator::hasBeenDestroyed()
{
    return hasBeenDestroyed_;
}

bool TestMemoryAllocator::isOfEqualType(TestMemoryAllocator* allocator)
{
    return SimpleString::StrCmp(this->name(), allocator->name()) == 0;
}

char* TestMemoryAllocator::allocMemoryLeakNode(size_t size)
{
    return alloc_memory(size, "MemoryLeakNode", 1);
}

void TestMemoryAllocator::freeMemoryLeakNode(char* memory)
{
    free_memory(memory, "MemoryLeakNode", 1);
}

char* TestMemoryAllocator::alloc_memory(size_t size, const char*, int)
{
    return checkedMalloc(size);
}

void TestMemoryAllocator::free_memory(char* memory, const char*, int)
{
    PlatformSpecificFree(memory);
}
const char* TestMemoryAllocator::name()
{
    return name_;
}

const char* TestMemoryAllocator::alloc_name()
{
    return alloc_name_;
}

const char* TestMemoryAllocator::free_name()
{
    return free_name_;
}

CrashOnAllocationAllocator::CrashOnAllocationAllocator() : allocationToCrashOn_(0)
{
}

void CrashOnAllocationAllocator::setNumberToCrashOn(unsigned allocationToCrashOn)
{
    allocationToCrashOn_ = allocationToCrashOn;
}

char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, int line)
{
    if (MemoryLeakWarningPlugin::getGlobalDetector()->getCurrentAllocationNumber() == allocationToCrashOn_)
        UT_CRASH();

    return TestMemoryAllocator::alloc_memory(size, file, line);
}

char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, int)
{
    return 0;
}

void NullUnknownAllocator::free_memory(char* /*memory*/, const char*, int)
{
}

NullUnknownAllocator::NullUnknownAllocator()
    : TestMemoryAllocator("Null Allocator", "unknown", "unknown")
{
}

TestMemoryAllocator* NullUnknownAllocator::defaultAllocator()
{
    static NullUnknownAllocator allocator;
    return &allocator;
}

FailableMemoryAllocator::FailableMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
: TestMemoryAllocator(name_str, alloc_name_str, free_name_str)
, toFailCount_(0), locationToFailCount_(0), currentAllocNumber_(0)
{
    PlatformSpecificMemset(allocsToFail_, 0, sizeof(allocsToFail_));
    PlatformSpecificMemset(locationAllocsToFail_, 0, sizeof(locationAllocsToFail_));

}

void FailableMemoryAllocator::failAllocNumber(int number)
{
    failIfMaximumNumberOfFailedAllocsExceeded(toFailCount_);
    allocsToFail_[toFailCount_++] = number;
}

void FailableMemoryAllocator::failNthAllocAt(int allocationNumber, const char* file, int line)
{
    failIfMaximumNumberOfFailedAllocsExceeded(locationToFailCount_);
    locationAllocsToFail_[locationToFailCount_].allocNumberToFail = allocationNumber;
    locationAllocsToFail_[locationToFailCount_].actualAllocNumber = 0;
    locationAllocsToFail_[locationToFailCount_].file = file;
    locationAllocsToFail_[locationToFailCount_].line = line;
    locationToFailCount_++;
}

void FailableMemoryAllocator::failIfMaximumNumberOfFailedAllocsExceeded(int toFailCount)
{
    if (toFailCount >= MAX_NUMBER_OF_FAILED_ALLOCS)
        FAIL("Maximum number of failed memory allocations exceeded");
}

char* FailableMemoryAllocator::alloc_memory(size_t size, const char* file, int line)
{
    if (shouldBeFailedAlloc() || shouldBeFailedLocationAlloc(file, line))
        return NULL;
    return TestMemoryAllocator::alloc_memory(size, file, line);
}

bool FailableMemoryAllocator::shouldBeFailedAlloc()
{
    currentAllocNumber_++;
    for (int i = 0; i < toFailCount_; i++)
        if (currentAllocNumber_ == allocsToFail_[i])
            return true;
    return false;
}

bool FailableMemoryAllocator::shouldBeFailedLocationAlloc(const char* file, int line)
{
    for (int i = 0; i < locationToFailCount_; i++) {
        if (isFailedLocation(&locationAllocsToFail_[i], file, line)) {
            locationAllocsToFail_[i].actualAllocNumber++;
            if (locationAllocsToFail_[i].allocNumberToFail == locationAllocsToFail_[i].actualAllocNumber) {
                locationAllocsToFail_[i].done = true;
                return true;
            }
        }
    }
    return false;
}

bool FailableMemoryAllocator::isFailedLocation(LocationToFailAlloc* locationFail, const char* allocFile, int allocLine)
{
    SimpleString allocBaseName = getBaseName(allocFile);
    SimpleString failBaseName = getBaseName(locationFail->file);
    return allocBaseName == failBaseName && allocLine == locationFail->line;
}

SimpleString FailableMemoryAllocator::getBaseName(const char* file)
{
    SimpleString fileFullPath(file);
    fileFullPath.replace('\\', '/');
    SimpleStringCollection pathElements;
    fileFullPath.split("/", pathElements);
    return pathElements[pathElements.size() - 1];
}

char* FailableMemoryAllocator::allocMemoryLeakNode(size_t size)
{
    return (char*)PlatformSpecificMalloc(size);
}

void FailableMemoryAllocator::checkFailedLocationAllocsWereDone()
{
    for (int i = 0; i < locationToFailCount_; i++)
        if (!locationAllocsToFail_[i].done)
        {
            UtestShell* currentTest = UtestShell::getCurrent();
            SimpleString failText = StringFromFormat("Expected failing alloc at %s:%d was never done",
                    locationAllocsToFail_[i].file,
                    locationAllocsToFail_[i].line);
            currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(),
                    currentTest->getLineNumber(), failText), TestTerminatorWithoutExceptions());
        }
}

void FailableMemoryAllocator::clearFailedAllocs()
{
    toFailCount_ = 0;
    locationToFailCount_ = 0;
    currentAllocNumber_ = 0;
    PlatformSpecificMemset(allocsToFail_, 0, sizeof(allocsToFail_));
    PlatformSpecificMemset(locationAllocsToFail_, 0, sizeof(locationAllocsToFail_));
}

<commit_msg>Report failure using UtestShell::failWith<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "CppUTest/TestHarness.h"
#include "CppUTest/TestMemoryAllocator.h"
#include "CppUTest/PlatformSpecificFunctions.h"
#include "CppUTest/MemoryLeakDetector.h"

static char* checkedMalloc(size_t size)
{
    char* mem = (char*) PlatformSpecificMalloc(size);
    if (mem == 0)
    FAIL("malloc returned null pointer");
    return mem;
}

static TestMemoryAllocator* currentNewAllocator = 0;
static TestMemoryAllocator* currentNewArrayAllocator = 0;
static TestMemoryAllocator* currentMallocAllocator = 0;

void setCurrentNewAllocator(TestMemoryAllocator* allocator)
{
    currentNewAllocator = allocator;
}

TestMemoryAllocator* getCurrentNewAllocator()
{
    if (currentNewAllocator == 0) setCurrentNewAllocatorToDefault();
    return currentNewAllocator;
}

void setCurrentNewAllocatorToDefault()
{
    currentNewAllocator = defaultNewAllocator();
}

TestMemoryAllocator* defaultNewAllocator()
{
    static TestMemoryAllocator allocator("Standard New Allocator", "new", "delete");
    return &allocator;
}

void setCurrentNewArrayAllocator(TestMemoryAllocator* allocator)
{
    currentNewArrayAllocator = allocator;
}

TestMemoryAllocator* getCurrentNewArrayAllocator()
{
    if (currentNewArrayAllocator == 0) setCurrentNewArrayAllocatorToDefault();
    return currentNewArrayAllocator;
}

void setCurrentNewArrayAllocatorToDefault()
{
    currentNewArrayAllocator = defaultNewArrayAllocator();
}

TestMemoryAllocator* defaultNewArrayAllocator()
{
    static TestMemoryAllocator allocator("Standard New [] Allocator", "new []", "delete []");
    return &allocator;
}

void setCurrentMallocAllocator(TestMemoryAllocator* allocator)
{
    currentMallocAllocator = allocator;
}

TestMemoryAllocator* getCurrentMallocAllocator()
{
    if (currentMallocAllocator == 0) setCurrentMallocAllocatorToDefault();
    return currentMallocAllocator;
}

void setCurrentMallocAllocatorToDefault()
{
    currentMallocAllocator = defaultMallocAllocator();
}

TestMemoryAllocator* defaultMallocAllocator()
{
    static TestMemoryAllocator allocator("Standard Malloc Allocator", "malloc", "free");
    return &allocator;
}

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

TestMemoryAllocator::TestMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
    : name_(name_str), alloc_name_(alloc_name_str), free_name_(free_name_str), hasBeenDestroyed_(false)
{
}

TestMemoryAllocator::~TestMemoryAllocator()
{
    hasBeenDestroyed_ = true;
}

bool TestMemoryAllocator::hasBeenDestroyed()
{
    return hasBeenDestroyed_;
}

bool TestMemoryAllocator::isOfEqualType(TestMemoryAllocator* allocator)
{
    return SimpleString::StrCmp(this->name(), allocator->name()) == 0;
}

char* TestMemoryAllocator::allocMemoryLeakNode(size_t size)
{
    return alloc_memory(size, "MemoryLeakNode", 1);
}

void TestMemoryAllocator::freeMemoryLeakNode(char* memory)
{
    free_memory(memory, "MemoryLeakNode", 1);
}

char* TestMemoryAllocator::alloc_memory(size_t size, const char*, int)
{
    return checkedMalloc(size);
}

void TestMemoryAllocator::free_memory(char* memory, const char*, int)
{
    PlatformSpecificFree(memory);
}
const char* TestMemoryAllocator::name()
{
    return name_;
}

const char* TestMemoryAllocator::alloc_name()
{
    return alloc_name_;
}

const char* TestMemoryAllocator::free_name()
{
    return free_name_;
}

CrashOnAllocationAllocator::CrashOnAllocationAllocator() : allocationToCrashOn_(0)
{
}

void CrashOnAllocationAllocator::setNumberToCrashOn(unsigned allocationToCrashOn)
{
    allocationToCrashOn_ = allocationToCrashOn;
}

char* CrashOnAllocationAllocator::alloc_memory(size_t size, const char* file, int line)
{
    if (MemoryLeakWarningPlugin::getGlobalDetector()->getCurrentAllocationNumber() == allocationToCrashOn_)
        UT_CRASH();

    return TestMemoryAllocator::alloc_memory(size, file, line);
}

char* NullUnknownAllocator::alloc_memory(size_t /*size*/, const char*, int)
{
    return 0;
}

void NullUnknownAllocator::free_memory(char* /*memory*/, const char*, int)
{
}

NullUnknownAllocator::NullUnknownAllocator()
    : TestMemoryAllocator("Null Allocator", "unknown", "unknown")
{
}

TestMemoryAllocator* NullUnknownAllocator::defaultAllocator()
{
    static NullUnknownAllocator allocator;
    return &allocator;
}

FailableMemoryAllocator::FailableMemoryAllocator(const char* name_str, const char* alloc_name_str, const char* free_name_str)
: TestMemoryAllocator(name_str, alloc_name_str, free_name_str)
, toFailCount_(0), locationToFailCount_(0), currentAllocNumber_(0)
{
    PlatformSpecificMemset(allocsToFail_, 0, sizeof(allocsToFail_));
    PlatformSpecificMemset(locationAllocsToFail_, 0, sizeof(locationAllocsToFail_));

}

void FailableMemoryAllocator::failAllocNumber(int number)
{
    failIfMaximumNumberOfFailedAllocsExceeded(toFailCount_);
    allocsToFail_[toFailCount_++] = number;
}

void FailableMemoryAllocator::failNthAllocAt(int allocationNumber, const char* file, int line)
{
    failIfMaximumNumberOfFailedAllocsExceeded(locationToFailCount_);
    locationAllocsToFail_[locationToFailCount_].allocNumberToFail = allocationNumber;
    locationAllocsToFail_[locationToFailCount_].actualAllocNumber = 0;
    locationAllocsToFail_[locationToFailCount_].file = file;
    locationAllocsToFail_[locationToFailCount_].line = line;
    locationToFailCount_++;
}

void FailableMemoryAllocator::failIfMaximumNumberOfFailedAllocsExceeded(int toFailCount)
{
    UtestShell* currentTest = UtestShell::getCurrent();

    if (toFailCount >= MAX_NUMBER_OF_FAILED_ALLOCS)
        currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(),
            currentTest->getLineNumber(), "Maximum number of failed memory allocations exceeded"),
            TestTerminatorWithoutExceptions());
}

char* FailableMemoryAllocator::alloc_memory(size_t size, const char* file, int line)
{
    if (shouldBeFailedAlloc() || shouldBeFailedLocationAlloc(file, line))
        return NULL;
    return TestMemoryAllocator::alloc_memory(size, file, line);
}

bool FailableMemoryAllocator::shouldBeFailedAlloc()
{
    currentAllocNumber_++;
    for (int i = 0; i < toFailCount_; i++)
        if (currentAllocNumber_ == allocsToFail_[i])
            return true;
    return false;
}

bool FailableMemoryAllocator::shouldBeFailedLocationAlloc(const char* file, int line)
{
    for (int i = 0; i < locationToFailCount_; i++) {
        if (isFailedLocation(&locationAllocsToFail_[i], file, line)) {
            locationAllocsToFail_[i].actualAllocNumber++;
            if (locationAllocsToFail_[i].allocNumberToFail == locationAllocsToFail_[i].actualAllocNumber) {
                locationAllocsToFail_[i].done = true;
                return true;
            }
        }
    }
    return false;
}

bool FailableMemoryAllocator::isFailedLocation(LocationToFailAlloc* locationFail, const char* allocFile, int allocLine)
{
    SimpleString allocBaseName = getBaseName(allocFile);
    SimpleString failBaseName = getBaseName(locationFail->file);
    return allocBaseName == failBaseName && allocLine == locationFail->line;
}

SimpleString FailableMemoryAllocator::getBaseName(const char* file)
{
    SimpleString fileFullPath(file);
    fileFullPath.replace('\\', '/');
    SimpleStringCollection pathElements;
    fileFullPath.split("/", pathElements);
    return pathElements[pathElements.size() - 1];
}

char* FailableMemoryAllocator::allocMemoryLeakNode(size_t size)
{
    return (char*)PlatformSpecificMalloc(size);
}

void FailableMemoryAllocator::checkFailedLocationAllocsWereDone()
{
    for (int i = 0; i < locationToFailCount_; i++)
        if (!locationAllocsToFail_[i].done)
        {
            UtestShell* currentTest = UtestShell::getCurrent();
            SimpleString failText = StringFromFormat("Expected failing alloc at %s:%d was never done",
                    locationAllocsToFail_[i].file,
                    locationAllocsToFail_[i].line);
            currentTest->failWith(FailFailure(currentTest, currentTest->getName().asCharString(),
                    currentTest->getLineNumber(), failText), TestTerminatorWithoutExceptions());
        }
}

void FailableMemoryAllocator::clearFailedAllocs()
{
    toFailCount_ = 0;
    locationToFailCount_ = 0;
    currentAllocNumber_ = 0;
    PlatformSpecificMemset(allocsToFail_, 0, sizeof(allocsToFail_));
    PlatformSpecificMemset(locationAllocsToFail_, 0, sizeof(locationAllocsToFail_));
}

<|endoftext|>


<commit_before>#include "analyzer_subsys_errors.h"

#include "util.h"
#include "analyzer_util.h"

void Analyzer_Subsys_Errors_Result::to_json(Json::Value &root) const
{
    Analyzer_Result_Period::to_json(root);
    root["subsystem"] = _subsys;
    root["subsystem-string"] = _subsys_string;
    root["ecode"] = _ecode;
    root["ecode-string"] = _ecode_string;
}

bool Analyzer_Subsys_Errors::configure(INIReader *config) {
    if (!Analyzer::configure(config)) {
	return false;
    }
    return true;
}

void Analyzer_Subsys_Errors::end_of_log(uint32_t packet_count UNUSED)
{
    auto subsys_errors = _vehicle->subsys_errors();

    for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
        // ::fprintf(stderr, "would evaluate (%s)\n", (*it).first.c_str());
        uint32_t subsys = (*it).first;
        if (_results[subsys] != NULL) {
            close_result(subsys);
        }
    }

    // if (!have) {
    //     Analyzer_Result_Summary *summary = new Analyzer_Result_Summary();
    //     summary->set_status(analyzer_status_warn);
    //     summary->set_reason("Sensor health never updated");
    //     summary->add_source(_data_sources.get("SENSORS_HEALTH"));
    //     add_result(summary);
    // }

}

void Analyzer_Subsys_Errors::close_result(const uint32_t subsys)
{
    Analyzer_Subsys_Errors_Result *result = _results[subsys];

    result->set_T_stop(_vehicle->T());
    add_result(result);
    _results[subsys] = NULL;
}

const std::map<const uint32_t, const std::string> _subsys_name = {
    { ERROR_SUBSYSTEM_MAIN, "MAIN" },
    { ERROR_SUBSYSTEM_RADIO, "RADIO" },
    { ERROR_SUBSYSTEM_COMPASS, "COMPASS" },
    { ERROR_SUBSYSTEM_OPTFLOW, "OPTFLOW" },
    { ERROR_SUBSYSTEM_FAILSAFE_RADIO, "FAILSAFE_RADIO" },
    { ERROR_SUBSYSTEM_FAILSAFE_BATT, "FAILSAFE_BATT" },
    { ERROR_SUBSYSTEM_FAILSAFE_GPS, "FAILSAFE_GPS" },   // not used
    { ERROR_SUBSYSTEM_FAILSAFE_GCS, "FAILSAFE_GCS" },
    { ERROR_SUBSYSTEM_FAILSAFE_FENCE, "FAILSAFE_FENCE" },
    { ERROR_SUBSYSTEM_FLIGHT_MODE, "FLIGHT_MODE" },
    { ERROR_SUBSYSTEM_GPS, "GPS" },
    { ERROR_SUBSYSTEM_CRASH_CHECK, "CRASH_CHECK" },
    { ERROR_SUBSYSTEM_FLIP, "FLIP" },
    { ERROR_SUBSYSTEM_AUTOTUNE, "AUTOTUNE" },
    { ERROR_SUBSYSTEM_PARACHUTE, "PARACHUTE" },
    { ERROR_SUBSYSTEM_EKFCHECK, "EKFCHECK" },
    { ERROR_SUBSYSTEM_FAILSAFE_EKFINAV, "FAILSAFE_EKFINAV" },
    { ERROR_SUBSYSTEM_BARO, "BARO" },
    { ERROR_SUBSYSTEM_CPU, "CPU" },
    { ERROR_SUBSYSTEM_FAILSAFE_ADSB, "FAILSAFE_ADSB" },
    { ERROR_SUBSYSTEM_TERRAIN, "TERRAIN" },
    { ERROR_SUBSYSTEM_NAVIGATION, "NAVIGATION" },
    { ERROR_SUBSYSTEM_FAILSAFE_TERRAIN, "FAILSAFE_TERRAIN" },
    { ERROR_SUBSYSTEM_EKF_PRIMARY, "EKF_PRIMARY" },
};

/// @brief Map from subsystem id to error code values
/// @note Correct only for ArduCopter ATM
/// @note taken from ArduCopter/defines.h
const std::map<const uint32_t, std::map<const uint32_t, const std::string>> _subsys_errors_strings = {
    { ERROR_SUBSYSTEM_RADIO, {
            { ERROR_CODE_RADIO_LATE_FRAME, "Late Frame" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_RADIO, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_BATT, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_GPS, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_GCS, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_FENCE, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_EKFCHECK, {
            { ERROR_CODE_EKFCHECK_BAD_VARIANCE, "Bad Variance" },
        }
    },
    { ERROR_SUBSYSTEM_BARO, {
            { ERROR_CODE_BARO_GLITCH, "Baro Glitch" },
        }
    },
    { ERROR_SUBSYSTEM_GPS, {
            { ERROR_CODE_GPS_GLITCH, "GPS Glitch" },
        }
    },
};

const std::string Analyzer_Subsys_Errors::subsys_string(const uint32_t subsys) const
{
    return _subsys_name.at(subsys);
}

const std::string Analyzer_Subsys_Errors::ecode_string(uint32_t subsys,
                                                       uint32_t ecode) const
{
    try {
        std::map<const uint32_t, const std::string> bob = _subsys_errors_strings.at(subsys);
        return bob.at(ecode);
    } catch (std::out_of_range) {
    }
    switch(ecode) {
    case ERROR_CODE_ERROR_RESOLVED:
        return "Resolved";
    case ERROR_CODE_FAILED_TO_INITIALISE:
        return "Failed to initialise";
    case ERROR_CODE_UNHEALTHY:
        return "Unhealthy";
    default:
        return "Unknown";
    }
}

void Analyzer_Subsys_Errors::open_result(const uint32_t subsys, const uint32_t ecode)
{
    _results[subsys] = new Analyzer_Subsys_Errors_Result(subsys,
                                                         subsys_string(subsys),
                                                         ecode,
                                                         ecode_string(subsys, ecode));
    _results[subsys]->set_reason("A subsystem failure has occured");
    _results[subsys]->set_T_start(_vehicle->T());
    _results[subsys]->set_status(analyzer_status_fail);
    _results[subsys]->add_source(_data_sources.get("SUBSYS_ERRORS"));
    _results[subsys]->increase_severity_score(10);
}

void Analyzer_Subsys_Errors::evaluate()
{
    auto subsys_errors = _vehicle->subsys_errors();

    for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
        uint32_t subsys = (*it).first;
        uint32_t new_ecode = (*it).second;
        // ::fprintf(stderr, "would evaluate (%s)\n", name.c_str());
        if (_results[subsys] != NULL) {
            if (_results[subsys]->ecode() != new_ecode) {
                close_result(subsys);
            }
        }
        if (_results[subsys] == NULL && new_ecode) {
            open_result(subsys, new_ecode);
        }
    }
}

<commit_msg>Update analyzer_subsys_errors.cpp<commit_after>#include "analyzer_subsys_errors.h"

#include "util.h"
#include "analyzer_util.h"

void Analyzer_Subsys_Errors_Result::to_json(Json::Value &root) const
{
    Analyzer_Result_Period::to_json(root);
    root["subsystem"] = _subsys;
    root["subsystem-string"] = _subsys_string;
    root["ecode"] = _ecode;
    root["ecode-string"] = _ecode_string;
}

bool Analyzer_Subsys_Errors::configure(INIReader *config) {
    if (!Analyzer::configure(config)) {
	return false;
    }
    return true;
}

void Analyzer_Subsys_Errors::end_of_log(uint32_t packet_count UNUSED)
{
    auto subsys_errors = _vehicle->subsys_errors();

    for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
        // ::fprintf(stderr, "would evaluate (%s)\n", (*it).first.c_str());
        uint32_t subsys = (*it).first;
        if (_results[subsys] != NULL) {
            close_result(subsys);
        }
    }

    // if (!have) {
    //     Analyzer_Result_Summary *summary = new Analyzer_Result_Summary();
    //     summary->set_status(analyzer_status_warn);
    //     summary->set_reason("Sensor health never updated");
    //     summary->add_source(_data_sources.get("SENSORS_HEALTH"));
    //     add_result(summary);
    // }

}

void Analyzer_Subsys_Errors::close_result(const uint32_t subsys)
{
    Analyzer_Subsys_Errors_Result *result = _results[subsys];

    result->set_T_stop(_vehicle->T());
    add_result(result);
    _results[subsys] = NULL;
}

const std::map<const uint32_t, const std::string> _subsys_name = {
    { ERROR_SUBSYSTEM_MAIN, "MAIN" },
    { ERROR_SUBSYSTEM_RADIO, "RADIO" },
    { ERROR_SUBSYSTEM_COMPASS, "COMPASS" },
    { ERROR_SUBSYSTEM_OPTFLOW, "OPTFLOW" },
    { ERROR_SUBSYSTEM_FAILSAFE_RADIO, "FAILSAFE_RADIO" },
    { ERROR_SUBSYSTEM_FAILSAFE_BATT, "FAILSAFE_BATT" },
    { ERROR_SUBSYSTEM_FAILSAFE_GPS, "FAILSAFE_GPS" },   // not used
    { ERROR_SUBSYSTEM_FAILSAFE_GCS, "FAILSAFE_GCS" },
    { ERROR_SUBSYSTEM_FAILSAFE_FENCE, "FAILSAFE_FENCE" },
    { ERROR_SUBSYSTEM_FLIGHT_MODE, "FLIGHT_MODE" },
    { ERROR_SUBSYSTEM_GPS, "GPS" },
    { ERROR_SUBSYSTEM_CRASH_CHECK, "CRASH_CHECK" },
    { ERROR_SUBSYSTEM_FLIP, "FLIP" },
    { ERROR_SUBSYSTEM_AUTOTUNE, "AUTOTUNE" },
    { ERROR_SUBSYSTEM_PARACHUTE, "PARACHUTE" },
    { ERROR_SUBSYSTEM_EKFCHECK, "EKFCHECK" },
    { ERROR_SUBSYSTEM_FAILSAFE_EKFINAV, "FAILSAFE_EKFINAV" },
    { ERROR_SUBSYSTEM_BARO, "BARO" },
    { ERROR_SUBSYSTEM_CPU, "CPU" },
    { ERROR_SUBSYSTEM_FAILSAFE_ADSB, "FAILSAFE_ADSB" },
    { ERROR_SUBSYSTEM_TERRAIN, "TERRAIN" },
    { ERROR_SUBSYSTEM_NAVIGATION, "NAVIGATION" },
    { ERROR_SUBSYSTEM_FAILSAFE_TERRAIN, "FAILSAFE_TERRAIN" },
    { ERROR_SUBSYSTEM_EKF_PRIMARY, "EKF_PRIMARY" },
};

/// @brief Map from subsystem id to error code values
/// @note Correct only for ArduCopter ATM
/// @note taken from ArduCopter/defines.h
const std::map<const uint32_t, std::map<const uint32_t, const std::string>> _subsys_errors_strings = {
    { ERROR_SUBSYSTEM_RADIO, {
            { ERROR_CODE_RADIO_LATE_FRAME, "Late Frame" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_RADIO, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_BATT, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_GPS, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_GCS, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_FAILSAFE_FENCE, {
            { ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
            { ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
        }
    },
    { ERROR_SUBSYSTEM_EKFCHECK, {
            { ERROR_CODE_EKFCHECK_BAD_VARIANCE, "Bad Variance" },
        }
    },
    { ERROR_SUBSYSTEM_BARO, {
            { ERROR_CODE_BARO_GLITCH, "Baro Glitch" },
        }
    },
    { ERROR_SUBSYSTEM_GPS, {
            { ERROR_CODE_GPS_GLITCH, "GPS Glitch" },
        }
    },
};

const std::string Analyzer_Subsys_Errors::subsys_string(const uint32_t subsys) const
{
    return _subsys_name.at(subsys);
}

const std::string Analyzer_Subsys_Errors::ecode_string(uint32_t subsys,
                                                       uint32_t ecode) const
{
    try {
        std::map<const uint32_t, const std::string> bob = _subsys_errors_strings.at(subsys);
        return bob.at(ecode);
    } catch (std::out_of_range&) {
    }
    switch(ecode) {
    case ERROR_CODE_ERROR_RESOLVED:
        return "Resolved";
    case ERROR_CODE_FAILED_TO_INITIALISE:
        return "Failed to initialise";
    case ERROR_CODE_UNHEALTHY:
        return "Unhealthy";
    default:
        return "Unknown";
    }
}

void Analyzer_Subsys_Errors::open_result(const uint32_t subsys, const uint32_t ecode)
{
    _results[subsys] = new Analyzer_Subsys_Errors_Result(subsys,
                                                         subsys_string(subsys),
                                                         ecode,
                                                         ecode_string(subsys, ecode));
    _results[subsys]->set_reason("A subsystem failure has occured");
    _results[subsys]->set_T_start(_vehicle->T());
    _results[subsys]->set_status(analyzer_status_fail);
    _results[subsys]->add_source(_data_sources.get("SUBSYS_ERRORS"));
    _results[subsys]->increase_severity_score(10);
}

void Analyzer_Subsys_Errors::evaluate()
{
    auto subsys_errors = _vehicle->subsys_errors();

    for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
        uint32_t subsys = (*it).first;
        uint32_t new_ecode = (*it).second;
        // ::fprintf(stderr, "would evaluate (%s)\n", name.c_str());
        if (_results[subsys] != NULL) {
            if (_results[subsys]->ecode() != new_ecode) {
                close_result(subsys);
            }
        }
        if (_results[subsys] == NULL && new_ecode) {
            open_result(subsys, new_ecode);
        }
    }
}

<|endoftext|>