<commit_before>//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
#include <string>

namespace clang {
namespace tooling {

namespace {
/// Takes an ast consumer and returns it from CreateASTConsumer. This only
/// works with single translation unit compilations.
class TestAction : public clang::ASTFrontendAction {
 public:
  /// Takes ownership of TestConsumer.
  explicit TestAction(clang::ASTConsumer *TestConsumer)
      : TestConsumer(TestConsumer) {}

 protected:
  virtual clang::ASTConsumer* CreateASTConsumer(
      clang::CompilerInstance& compiler, StringRef dummy) {
    /// TestConsumer will be deleted by the framework calling us.
    return TestConsumer;
  }

 private:
  clang::ASTConsumer * const TestConsumer;
};

class FindTopLevelDeclConsumer : public clang::ASTConsumer {
 public:
  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
      : FoundTopLevelDecl(FoundTopLevelDecl) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
    *FoundTopLevelDecl = true;
    return true;
  }
 private:
  bool * const FoundTopLevelDecl;
};
} // end namespace

TEST(runToolOnCode, FindsTopLevelDeclOnEmptyCode) {
  bool FoundTopLevelDecl = false;
  EXPECT_TRUE(runToolOnCode(
      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
  EXPECT_TRUE(FoundTopLevelDecl);
}

namespace {
class FindClassDeclXConsumer : public clang::ASTConsumer {
 public:
  FindClassDeclXConsumer(bool *FoundClassDeclX)
      : FoundClassDeclX(FoundClassDeclX) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
            *GroupRef.begin())) {
      if (Record->getName() == "X") {
        *FoundClassDeclX = true;
      }
    }
    return true;
  }
 private:
  bool *FoundClassDeclX;
};
} // end namespace

TEST(runToolOnCode, FindsClassDecl) {
  bool FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
  EXPECT_TRUE(FoundClassDeclX);

  FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
  EXPECT_FALSE(FoundClassDeclX);
}

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory<SyntaxOnlyAction>());
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

struct IndependentFrontendActionCreator {
  FrontendAction *newFrontendAction() { return new SyntaxOnlyAction; }
};

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
  IndependentFrontendActionCreator Creator;
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory(&Creator));
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

TEST(ToolInvocation, TestMapVirtualFile) {
  clang::FileManager Files((clang::FileSystemOptions()));
  std::vector<std::string> Args;
  Args.push_back("tool-executable");
  Args.push_back("-Idef");
  Args.push_back("-fsyntax-only");
  Args.push_back("test.cpp");
  clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);
  Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
  Invocation.mapVirtualFile("def/abc", "\n");
  EXPECT_TRUE(Invocation.run());
}

} // end namespace tooling
} // end namespace clang
<commit_msg>#ifdef out a broken test on win32<commit_after>//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
#include <string>

namespace clang {
namespace tooling {

namespace {
/// Takes an ast consumer and returns it from CreateASTConsumer. This only
/// works with single translation unit compilations.
class TestAction : public clang::ASTFrontendAction {
 public:
  /// Takes ownership of TestConsumer.
  explicit TestAction(clang::ASTConsumer *TestConsumer)
      : TestConsumer(TestConsumer) {}

 protected:
  virtual clang::ASTConsumer* CreateASTConsumer(
      clang::CompilerInstance& compiler, StringRef dummy) {
    /// TestConsumer will be deleted by the framework calling us.
    return TestConsumer;
  }

 private:
  clang::ASTConsumer * const TestConsumer;
};

class FindTopLevelDeclConsumer : public clang::ASTConsumer {
 public:
  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
      : FoundTopLevelDecl(FoundTopLevelDecl) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
    *FoundTopLevelDecl = true;
    return true;
  }
 private:
  bool * const FoundTopLevelDecl;
};
} // end namespace

TEST(runToolOnCode, FindsTopLevelDeclOnEmptyCode) {
  bool FoundTopLevelDecl = false;
  EXPECT_TRUE(runToolOnCode(
      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
  EXPECT_TRUE(FoundTopLevelDecl);
}

namespace {
class FindClassDeclXConsumer : public clang::ASTConsumer {
 public:
  FindClassDeclXConsumer(bool *FoundClassDeclX)
      : FoundClassDeclX(FoundClassDeclX) {}
  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
            *GroupRef.begin())) {
      if (Record->getName() == "X") {
        *FoundClassDeclX = true;
      }
    }
    return true;
  }
 private:
  bool *FoundClassDeclX;
};
} // end namespace

TEST(runToolOnCode, FindsClassDecl) {
  bool FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
  EXPECT_TRUE(FoundClassDeclX);

  FoundClassDeclX = false;
  EXPECT_TRUE(runToolOnCode(new TestAction(
      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
  EXPECT_FALSE(FoundClassDeclX);
}

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory<SyntaxOnlyAction>());
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

struct IndependentFrontendActionCreator {
  FrontendAction *newFrontendAction() { return new SyntaxOnlyAction; }
};

TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
  IndependentFrontendActionCreator Creator;
  llvm::OwningPtr<FrontendActionFactory> Factory(
    newFrontendActionFactory(&Creator));
  llvm::OwningPtr<FrontendAction> Action(Factory->create());
  EXPECT_TRUE(Action.get() != NULL);
}

#ifndef LLVM_ON_WIN32
// This test breaks on Windows.

TEST(ToolInvocation, TestMapVirtualFile) {
  clang::FileManager Files((clang::FileSystemOptions()));
  std::vector<std::string> Args;
  Args.push_back("tool-executable");
  Args.push_back("-Idef");
  Args.push_back("-fsyntax-only");
  Args.push_back("test.cpp");
  clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);
  Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
  Invocation.mapVirtualFile("def/abc", "\n");
  EXPECT_TRUE(Invocation.run());
}

#endif

} // end namespace tooling
} // end namespace clang
<|endoftext|>


<commit_before>#include <stan/prob/distributions/univariate/discrete/neg_binomial.hpp>
#include <gtest/gtest.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/math/distributions.hpp>

TEST(ProbDistributionsNegBinomial, error_check) {
  boost::random::mt19937 rng;
  EXPECT_NO_THROW(stan::prob::neg_binomial_rng(6, 2, rng));
  EXPECT_NO_THROW(stan::prob::neg_binomial_rng(0.5,1,rng));

  EXPECT_THROW(stan::prob::neg_binomial_rng(0, 2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(-6, 2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(6, -2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(stan::math::positive_infinity(), 2,
                                            rng),
               std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(6,stan::math::positive_infinity(),
                                            rng),
               std::domain_error);
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (5,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(5, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest2) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (2.4,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(2.4, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest3) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (0.4,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(0.4, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}
<commit_msg>fully specifying call to boost::math::pdf<commit_after>#include <stan/prob/distributions/univariate/discrete/neg_binomial.hpp>
#include <gtest/gtest.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/math/distributions.hpp>

TEST(ProbDistributionsNegBinomial, error_check) {
  boost::random::mt19937 rng;
  EXPECT_NO_THROW(stan::prob::neg_binomial_rng(6, 2, rng));
  EXPECT_NO_THROW(stan::prob::neg_binomial_rng(0.5,1,rng));

  EXPECT_THROW(stan::prob::neg_binomial_rng(0, 2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(-6, 2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(6, -2, rng),std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(stan::math::positive_infinity(), 2,
                                            rng),
               std::domain_error);
  EXPECT_THROW(stan::prob::neg_binomial_rng(6,stan::math::positive_infinity(),
                                            rng),
               std::domain_error);
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (5,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * boost::math::pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(5, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest2) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (2.4,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(2.4, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial, chiSquareGoodnessFitTest3) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = boost::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<>dist (0.4,0.6);
  boost::math::chi_squared mydist(K-1);

  int loc[K - 1];
  for(int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin [K];
  double expect [K];
  for(int i = 0 ; i < K; i++)  {
    bin[i] = 0;
    expect[i] = N * boost::math::pdf(dist, i);
  }
  expect[K-1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::prob::neg_binomial_rng(0.4, 0.6/(1-0.6), rng);
    int i = 0;
    while (i < K-1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
   }

  double chi = 0;

  for(int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}
<|endoftext|>


<commit_before>/*
 *  ThreadPool.cpp
 *  OpenLieroX
 *
 *  Created by Albert Zeyer on 08.02.09.
 *  code under LGPL
 *
 */

#include <SDL_thread.h>
#include "ThreadPool.h"
#include "Debug.h"

static const unsigned int THREADNUM = 20;

ThreadPool::ThreadPool() {
	nextFunc = NULL; nextParam = NULL; nextData = NULL;
	mutex = SDL_CreateMutex();
	awakeThread = SDL_CreateCond();
	threadStartedWork = SDL_CreateCond();
	threadFinishedWork = SDL_CreateCond();

	notes << "ThreadPool: creating " << THREADNUM << " threads ..." << endl;
	while(availableThreads.size() < THREADNUM)
		prepareNewThread();
}

ThreadPool::~ThreadPool() {
	SDL_mutexP(mutex);
	while(usedThreads.size() > 0) {
		warnings << "ThreadPool: waiting for " << usedThreads.size() << " threads to finish:" << endl;
		for(std::set<ThreadPoolItem*>::iterator i = usedThreads.begin(); i != usedThreads.end(); ++i) {
			if((*i)->working && (*i)->finished) {
				warnings << "thread " << (*i)->name << " is ready but was not cleaned up" << endl;
				SDL_CondSignal((*i)->readyForNewWork);
			}
			else if((*i)->working && !(*i)->finished) {
				warnings << "thread " << (*i)->name << " is still working" << endl;
			}
			else {
				warnings << "thread " << (*i)->name << " is in an invalid state" << endl;
			}
		}
		SDL_CondWait(threadFinishedWork, mutex);
	}
	SDL_mutexV(mutex);

	nextFunc = NULL;
	SDL_CondBroadcast(awakeThread);
	for(std::set<ThreadPoolItem*>::iterator i = availableThreads.begin(); i != availableThreads.end(); ++i) {
		SDL_WaitThread((*i)->thread, NULL);
		SDL_DestroyCond((*i)->finishedSignal);
		SDL_DestroyCond((*i)->readyForNewWork);
		delete *i;
	}
	availableThreads.clear();

	SDL_DestroyCond(threadStartedWork);
	SDL_DestroyCond(threadFinishedWork);
	SDL_DestroyCond(awakeThread);
	SDL_DestroyMutex(mutex);
}

void ThreadPool::prepareNewThread() {
	ThreadPoolItem* t = new ThreadPoolItem();
	t->pool = this;
	t->finishedSignal = SDL_CreateCond();
	t->readyForNewWork = SDL_CreateCond();
	t->finished = false;
	t->working = false;
	availableThreads.insert(t);
	t->thread = SDL_CreateThread(threadWrapper, t);
}

int ThreadPool::threadWrapper(void* param) {
	ThreadPoolItem* data = (ThreadPoolItem*)param;

	SDL_mutexP(data->pool->mutex);
	while(true) {
		SDL_CondWait(data->pool->awakeThread, data->pool->mutex);
		if(data->pool->nextFunc == NULL) break;
		data->pool->usedThreads.insert(data);
		data->pool->availableThreads.erase(data);

		ThreadFunc func = data->pool->nextFunc; data->pool->nextFunc = NULL;
		void* param = data->pool->nextParam; data->pool->nextParam = NULL;
		data->name = data->pool->nextName;
		data->finished = false;
		data->working = true;
		data->pool->nextData = data;
		SDL_mutexV(data->pool->mutex);

		SDL_CondSignal(data->pool->threadStartedWork);
		data->ret = (*func) (param);
		data->finished = true;
		SDL_CondSignal(data->finishedSignal);
		SDL_CondSignal(data->pool->threadFinishedWork);

		SDL_mutexP(data->pool->mutex);
		while(data->working) SDL_CondWait(data->readyForNewWork, data->pool->mutex);
		data->pool->usedThreads.erase(data);
		data->pool->availableThreads.insert(data);
	}
	SDL_mutexV(data->pool->mutex);

	return 0;
}

ThreadPoolItem* ThreadPool::start(ThreadFunc fct, void* param, const std::string& name) {
	SDL_mutexP(mutex);
	if(availableThreads.size() == 0) {
		warnings << "no available thread in ThreadPool for " << name << ", creating new one..." << endl;
		prepareNewThread();
	}
	assert(nextFunc == NULL);
	nextFunc = fct;
	nextParam = param;
	nextName = name;
	assert(nextData == NULL);
	SDL_mutexV(mutex);

	SDL_CondSignal(awakeThread);
	SDL_mutexP(mutex);
	while(nextData == NULL) SDL_CondWait(threadStartedWork, mutex);
	ThreadPoolItem* data = nextData; nextData = NULL;
	SDL_mutexV(mutex);

	return data;
}

bool ThreadPool::wait(ThreadPoolItem* thread, int* status) {
	if(!thread) return false;
	SDL_mutexP(mutex);
	if(!thread->working) {
		warnings << "given thread " << thread->name << " is not working anymore" << endl;
		SDL_mutexV(mutex);
		return false;
	}
	while(!thread->finished) SDL_CondWait(thread->finishedSignal, mutex);
	if(status) *status = thread->ret;
	thread->working = false;
	SDL_mutexV(mutex);

	SDL_CondSignal(thread->readyForNewWork);
	return true;
}

ThreadPool* threadPool = NULL;

void InitThreadPool() {
	threadPool = new ThreadPool();
}

void UnInitThreadPool() {
	delete threadPool;
	threadPool = NULL;
}

<commit_msg>fixed one possible thread block<commit_after>/*
 *  ThreadPool.cpp
 *  OpenLieroX
 *
 *  Created by Albert Zeyer on 08.02.09.
 *  code under LGPL
 *
 */

#include <SDL_thread.h>
#include "ThreadPool.h"
#include "Debug.h"

static const unsigned int THREADNUM = 20;

ThreadPool::ThreadPool() {
	nextFunc = NULL; nextParam = NULL; nextData = NULL;
	mutex = SDL_CreateMutex();
	awakeThread = SDL_CreateCond();
	threadStartedWork = SDL_CreateCond();
	threadFinishedWork = SDL_CreateCond();

	notes << "ThreadPool: creating " << THREADNUM << " threads ..." << endl;
	while(availableThreads.size() < THREADNUM)
		prepareNewThread();
}

ThreadPool::~ThreadPool() {
	SDL_mutexP(mutex);
	while(usedThreads.size() > 0) {
		warnings << "ThreadPool: waiting for " << usedThreads.size() << " threads to finish:" << endl;
		for(std::set<ThreadPoolItem*>::iterator i = usedThreads.begin(); i != usedThreads.end(); ++i) {
			if((*i)->working && (*i)->finished) {
				warnings << "thread " << (*i)->name << " is ready but was not cleaned up" << endl;
				SDL_CondSignal((*i)->readyForNewWork);
			}
			else if((*i)->working && !(*i)->finished) {
				warnings << "thread " << (*i)->name << " is still working" << endl;
			}
			else {
				warnings << "thread " << (*i)->name << " is in an invalid state" << endl;
			}
		}
		SDL_CondWait(threadFinishedWork, mutex);
	}
	SDL_mutexV(mutex);

	nextFunc = NULL;
	SDL_CondBroadcast(awakeThread);
	for(std::set<ThreadPoolItem*>::iterator i = availableThreads.begin(); i != availableThreads.end(); ++i) {
		SDL_WaitThread((*i)->thread, NULL);
		SDL_DestroyCond((*i)->finishedSignal);
		SDL_DestroyCond((*i)->readyForNewWork);
		delete *i;
	}
	availableThreads.clear();

	SDL_DestroyCond(threadStartedWork);
	SDL_DestroyCond(threadFinishedWork);
	SDL_DestroyCond(awakeThread);
	SDL_DestroyMutex(mutex);
}

void ThreadPool::prepareNewThread() {
	ThreadPoolItem* t = new ThreadPoolItem();
	t->pool = this;
	t->finishedSignal = SDL_CreateCond();
	t->readyForNewWork = SDL_CreateCond();
	t->finished = false;
	t->working = false;
	availableThreads.insert(t);
	t->thread = SDL_CreateThread(threadWrapper, t);
}

int ThreadPool::threadWrapper(void* param) {
	ThreadPoolItem* data = (ThreadPoolItem*)param;

	SDL_mutexP(data->pool->mutex);
	while(true) {
		SDL_CondWait(data->pool->awakeThread, data->pool->mutex);
		if(data->pool->nextFunc == NULL) break;
		data->pool->usedThreads.insert(data);
		data->pool->availableThreads.erase(data);

		ThreadFunc func = data->pool->nextFunc; data->pool->nextFunc = NULL;
		void* param = data->pool->nextParam; data->pool->nextParam = NULL;
		data->name = data->pool->nextName;
		data->finished = false;
		data->working = true;
		data->pool->nextData = data;
		SDL_mutexV(data->pool->mutex);

		SDL_CondSignal(data->pool->threadStartedWork);
		data->ret = (*func) (param);
		SDL_mutexP(data->pool->mutex);
		data->finished = true;
		SDL_mutexV(data->pool->mutex);
		SDL_CondSignal(data->finishedSignal);
		SDL_CondSignal(data->pool->threadFinishedWork);

		SDL_mutexP(data->pool->mutex);
		while(data->working) SDL_CondWait(data->readyForNewWork, data->pool->mutex);
		data->pool->usedThreads.erase(data);
		data->pool->availableThreads.insert(data);
	}
	SDL_mutexV(data->pool->mutex);

	return 0;
}

ThreadPoolItem* ThreadPool::start(ThreadFunc fct, void* param, const std::string& name) {
	SDL_mutexP(mutex);
	if(availableThreads.size() == 0) {
		warnings << "no available thread in ThreadPool for " << name << ", creating new one..." << endl;
		prepareNewThread();
	}
	assert(nextFunc == NULL);
	nextFunc = fct;
	nextParam = param;
	nextName = name;
	assert(nextData == NULL);
	SDL_mutexV(mutex);

	SDL_CondSignal(awakeThread);
	SDL_mutexP(mutex);
	while(nextData == NULL) SDL_CondWait(threadStartedWork, mutex);
	ThreadPoolItem* data = nextData; nextData = NULL;
	SDL_mutexV(mutex);

	return data;
}

bool ThreadPool::wait(ThreadPoolItem* thread, int* status) {
	if(!thread) return false;
	SDL_mutexP(mutex);
	if(!thread->working) {
		warnings << "given thread " << thread->name << " is not working anymore" << endl;
		SDL_mutexV(mutex);
		return false;
	}
	while(!thread->finished) SDL_CondWait(thread->finishedSignal, mutex);
	if(status) *status = thread->ret;
	thread->working = false;
	SDL_mutexV(mutex);

	SDL_CondSignal(thread->readyForNewWork);
	return true;
}

ThreadPool* threadPool = NULL;

void InitThreadPool() {
	threadPool = new ThreadPool();
}

void UnInitThreadPool() {
	delete threadPool;
	threadPool = NULL;
}

<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file PositionControl.hpp
 *
 * A cascaded position controller for position/velocity control only.
 */

#include <matrix/matrix/math.hpp>

#include <uORB/topics/vehicle_local_position.h>
#include <uORB/topics/vehicle_local_position_setpoint.h>
#include <parameters/param.h>

#pragma once

namespace Controller
{
/** Constraints that depends on mode and are lower
 * 	than the global limits.
 * 	tilt_max: Cannot exceed PI/2 radians
 * 	vel_max_z_up: Cannot exceed maximum global velocity upwards
 * @see MPC_TILTMAX_AIR
 * @see MPC_Z_VEL_MAX_DN
 */
struct Constraints {
	float tilt_max; /**< maximum tilt always below Pi/2 */
	float vel_max_z_up; /**< maximum speed upwards always smaller than MPC_VEL_Z_MAX_UP */
};
}
/**
 * 	Core Position-Control for MC.
 * 	This class contains P-controller for position and
 * 	PID-controller for velocity.
 * 	Inputs:
 * 		vehicle position/velocity/yaw
 * 		desired set-point position/velocity/thrust/yaw/yaw-speed
 * 		constraints that are stricter than global limits
 * 	Output
 * 		thrust vector and a yaw-setpoint
 *
 * 	If there is a position and a velocity set-point present, then
 * 	the velocity set-point is used as feed-forward. If feed-forward is
 * 	active, then the velocity component of the P-controller output has
 * 	priority over the feed-forward component.
 *
 * 	A setpoint that is NAN is considered as not set.
 */
class PositionControl
{
public:

	PositionControl();
	~PositionControl() {};

	/**
	 * Update the current vehicle state.
	 * @param state a vehicle_local_position_s structure
	 * @param vel_dot the derivative of the vehicle velocity
	 */
	void updateState(const vehicle_local_position_s &state, const matrix::Vector3f &vel_dot);

	/**
	 * Update the desired setpoints.
	 * @param setpoint a vehicle_local_position_setpoint_s structure
	 */
	void updateSetpoint(const vehicle_local_position_setpoint_s &setpoint);

	/**
	 * Set constraints that are stricter than the global limits.
	 * @param constraints a PositionControl structure with supported constraints
	 */
	void updateConstraints(const Controller::Constraints &constraints);

	/**
	 * Apply P-position and PID-velocity controller that updates the member
	 * thrust, yaw- and yawspeed-setpoints.
	 * @see _thr_sp
	 * @see _yaw_sp
	 * @see _yawspeed_sp
	 * @param dt the delta-time
	 */
	void generateThrustYawSetpoint(const float &dt);

	/**
	 * 	Set the integral term in xy to 0.
	 * 	@see _thr_int
	 */
	void resetIntegralXY() {_thr_int(0) = _thr_int(1) = 0.0f;};

	/**
	 * 	Set the integral term in z to 0.
	 * 	@see _thr_int
	 */
	void resetIntegralZ() {_thr_int(2) = 0.0f;};

	/**
	 * 	Get the
	 * 	@see _thr_sp
	 * 	@return The thrust set-point member.
	 */
	matrix::Vector3f getThrustSetpoint() {return _thr_sp;}

	/**
	 * 	Get the
	 * 	@see _yaw_sp
	 * 	@return The yaw set-point member.
	 */
	float getYawSetpoint() { return _yaw_sp;}

	/**
	 * 	Get the
	 * 	@see _yawspeed_sp
	 * 	@return The yawspeed set-point member.
	 */
	float getYawspeedSetpoint() {return _yawspeed_sp;}

	/**
	 * 	Get the
	 * 	@see _vel_sp
	 * 	@return The velocity set-point member.
	 */
	matrix::Vector3f getVelSp() {return _vel_sp;}

	/**
	 * 	Get the
	 * 	@see _pos_sp
	 * 	@return The position set-point member.
	 */
	matrix::Vector3f getPosSp() {return _pos_sp;}

private:
	void _interfaceMapping(); /** maps set-points to internal member set-points */
	void _positionController(); /** applies the P-position-controller */
	void _velocityController(const float &dt); /** applies the PID-velocity-controller */
	void _updateParams(); /** updates parameters */
	void _setParams(); /** sets parameters to internal member */

	matrix::Vector3f _pos{}; /**< MC position */
	matrix::Vector3f _vel{}; /**< MC velocity */
	matrix::Vector3f _vel_dot{}; /**< MC velocity derivative */
	matrix::Vector3f _acc{}; /**< MC acceleration */
	float _yaw{0.0f}; /**< MC yaw */
	matrix::Vector3f _pos_sp{}; /**< desired position */
	matrix::Vector3f _vel_sp{}; /**< desired velocity */
	matrix::Vector3f _acc_sp{}; /**< desired acceleration: not supported yet */
	matrix::Vector3f _thr_sp{}; /**< desired thrust */
	float _yaw_sp{}; /**< desired yaw */
	float _yawspeed_sp{}; /** desired yaw-speed */
	matrix::Vector3f _thr_int{}; /**< thrust integral term */
	Controller::Constraints _constraints{}; /**< variable constraints */
	bool _skip_controller{false}; /**< skips position/velocity controller. true for stabilized mode */

	/**
	 * Position Gains.
	 * Pp: P-controller gain for position-controller
	 * Pv: P-controller gain for velocity-controller
	 * Iv: I-controller gain for velocity-controller
	 * Dv: D-controller gain for velocity-controller
	 */
	matrix::Vector3f _Pp, _Pv, _Iv, _Dv = matrix::Vector3f{0.0f, 0.0f, 0.0f};

	float MPC_THR_MAX{1.0f}; /**< maximum thrust */
	float MPC_THR_HOVER{0.5f}; /** equilibrium point for the velocity controller */
	float MPC_THR_MIN{0.0f}; /**< minimum throttle for any position controlled mode */
	float MPC_MANTHR_MIN{0.0f}; /**< minimum throttle for stabilized mode */
	float MPC_XY_VEL_MAX{1.0f}; /**< maximum speed in the horizontal direction */
	float MPC_Z_VEL_MAX_DN{1.0f}; /**< maximum speed in downwards direction */
	float MPC_Z_VEL_MAX_UP{1.0f}; /**< maximum speed in upwards direction */
	float MPC_TILTMAX_AIR{1.5}; /**< maximum tilt for any position/velocity controlled mode in radians */
	float MPC_MAN_TILT_MAX{3.1}; /**< maximum tilt for manual/altitude mode in radians */

	// Parameter handles
	int _parameter_sub { -1 };
	param_t MPC_Z_P_h { PARAM_INVALID };
	param_t MPC_Z_VEL_P_h { PARAM_INVALID };
	param_t MPC_Z_VEL_I_h { PARAM_INVALID };
	param_t MPC_Z_VEL_D_h { PARAM_INVALID };
	param_t MPC_XY_P_h { PARAM_INVALID };
	param_t MPC_XY_VEL_P_h { PARAM_INVALID };
	param_t MPC_XY_VEL_I_h { PARAM_INVALID };
	param_t MPC_XY_VEL_D_h { PARAM_INVALID };
	param_t MPC_XY_VEL_MAX_h { PARAM_INVALID };
	param_t MPC_Z_VEL_MAX_DN_h { PARAM_INVALID };
	param_t MPC_Z_VEL_MAX_UP_h { PARAM_INVALID };
	param_t MPC_THR_HOVER_h { PARAM_INVALID };
	param_t MPC_THR_MAX_h { PARAM_INVALID };
	param_t MPC_THR_MIN_h { PARAM_INVALID };
	param_t MPC_MANTHR_MIN_h { PARAM_INVALID };
	param_t MPC_TILTMAX_AIR_h { PARAM_INVALID };
	param_t MPC_MAN_TILT_MAX_h { PARAM_INVALID };
};
<commit_msg>PositionControl.hpp: inherit from ModuleParams and replace params with ModuleParams type<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file PositionControl.hpp
 *
 * A cascaded position controller for position/velocity control only.
 */

#include <matrix/matrix/math.hpp>

#include <uORB/topics/vehicle_local_position.h>
#include <uORB/topics/vehicle_local_position_setpoint.h>
#include <px4_module_params.h>
#pragma once

namespace Controller
{
/** Constraints that depends on mode and are lower
 * 	than the global limits.
 * 	tilt_max: Cannot exceed PI/2 radians
 * 	vel_max_z_up: Cannot exceed maximum global velocity upwards
 * @see MPC_TILTMAX_AIR
 * @see MPC_Z_VEL_MAX_DN
 */
struct Constraints {
	float tilt_max; /**< maximum tilt always below Pi/2 */
	float vel_max_z_up; /**< maximum speed upwards always smaller than MPC_VEL_Z_MAX_UP */
};
}
/**
 * 	Core Position-Control for MC.
 * 	This class contains P-controller for position and
 * 	PID-controller for velocity.
 * 	Inputs:
 * 		vehicle position/velocity/yaw
 * 		desired set-point position/velocity/thrust/yaw/yaw-speed
 * 		constraints that are stricter than global limits
 * 	Output
 * 		thrust vector and a yaw-setpoint
 *
 * 	If there is a position and a velocity set-point present, then
 * 	the velocity set-point is used as feed-forward. If feed-forward is
 * 	active, then the velocity component of the P-controller output has
 * 	priority over the feed-forward component.
 *
 * 	A setpoint that is NAN is considered as not set.
 */
class PositionControl : public ModuleParams
{
public:

	PositionControl(ModuleParams *parent);
	~PositionControl() = default;

	/**
	 *	Overwrites certain parameters.
	 *	Overwrites are required for unit-conversion.
	 *	This method should only be called if parameters
	 *	have been updated.
	 */
	void overwriteParams();

	/**
	 * Update the current vehicle state.
	 * @param state a vehicle_local_position_s structure
	 * @param vel_dot the derivative of the vehicle velocity
	 */
	void updateState(const vehicle_local_position_s &state, const matrix::Vector3f &vel_dot);

	/**
	 * Update the desired setpoints.
	 * @param setpoint a vehicle_local_position_setpoint_s structure
	 */
	void updateSetpoint(const vehicle_local_position_setpoint_s &setpoint);

	/**
	 * Set constraints that are stricter than the global limits.
	 * @param constraints a PositionControl structure with supported constraints
	 */
	void updateConstraints(const Controller::Constraints &constraints);

	/**
	 * Apply P-position and PID-velocity controller that updates the member
	 * thrust, yaw- and yawspeed-setpoints.
	 * @see _thr_sp
	 * @see _yaw_sp
	 * @see _yawspeed_sp
	 * @param dt the delta-time
	 */
	void generateThrustYawSetpoint(const float &dt);

	/**
	 * 	Set the integral term in xy to 0.
	 * 	@see _thr_int
	 */
	void resetIntegralXY() {_thr_int(0) = _thr_int(1) = 0.0f;};

	/**
	 * 	Set the integral term in z to 0.
	 * 	@see _thr_int
	 */
	void resetIntegralZ() {_thr_int(2) = 0.0f;};

	/**
	 * 	Get the
	 * 	@see _thr_sp
	 * 	@return The thrust set-point member.
	 */
	matrix::Vector3f getThrustSetpoint() {return _thr_sp;}

	/**
	 * 	Get the
	 * 	@see _yaw_sp
	 * 	@return The yaw set-point member.
	 */
	float getYawSetpoint() { return _yaw_sp;}

	/**
	 * 	Get the
	 * 	@see _yawspeed_sp
	 * 	@return The yawspeed set-point member.
	 */
	float getYawspeedSetpoint() {return _yawspeed_sp;}

	/**
	 * 	Get the
	 * 	@see _vel_sp
	 * 	@return The velocity set-point member.
	 */
	matrix::Vector3f getVelSp() {return _vel_sp;}

	/**
	 * 	Get the
	 * 	@see _pos_sp
	 * 	@return The position set-point member.
	 */
	matrix::Vector3f getPosSp() {return _pos_sp;}

private:
	void _interfaceMapping(); /** maps set-points to internal member set-points */
	void _positionController(); /** applies the P-position-controller */
	void _velocityController(const float &dt); /** applies the PID-velocity-controller */

	matrix::Vector3f _pos{}; /**< MC position */
	matrix::Vector3f _vel{}; /**< MC velocity */
	matrix::Vector3f _vel_dot{}; /**< MC velocity derivative */
	matrix::Vector3f _acc{}; /**< MC acceleration */
	float _yaw{0.0f}; /**< MC yaw */
	matrix::Vector3f _pos_sp{}; /**< desired position */
	matrix::Vector3f _vel_sp{}; /**< desired velocity */
	matrix::Vector3f _acc_sp{}; /**< desired acceleration: not supported yet */
	matrix::Vector3f _thr_sp{}; /**< desired thrust */
	float _yaw_sp{}; /**< desired yaw */
	float _yawspeed_sp{}; /** desired yaw-speed */
	matrix::Vector3f _thr_int{}; /**< thrust integral term */
	Controller::Constraints _constraints{}; /**< variable constraints */
	bool _skip_controller{false}; /**< skips position/velocity controller. true for stabilized mode */

	DEFINE_PARAMETERS(
	        (ParamFloat<px4::params::MPC_THR_MAX>) MPC_THR_MAX,
			(ParamFloat<px4::params::MPC_THR_HOVER>) MPC_THR_HOVER,
			(ParamFloat<px4::params::MPC_THR_MIN>) MPC_THR_MIN,
			(ParamFloat<px4::params::MPC_MANTHR_MIN>) MPC_MANTHR_MIN,
			(ParamFloat<px4::params::MPC_XY_VEL_MAX>) MPC_XY_VEL_MAX,
			(ParamFloat<px4::params::MPC_Z_VEL_MAX_DN>) MPC_Z_VEL_MAX_DN,
			(ParamFloat<px4::params::MPC_Z_VEL_MAX_UP>) MPC_Z_VEL_MAX_UP,
			(ParamFloat<px4::params::MPC_TILTMAX_AIR>) MPC_TILTMAX_AIR,
			(ParamFloat<px4::params::MPC_MAN_TILT_MAX>) MPC_MAN_TILT_MAX,
			(ParamFloat<px4::params::MPC_Z_P>) MPC_Z_P,
			(ParamFloat<px4::params::MPC_Z_VEL_P>) MPC_Z_VEL_P,
			(ParamFloat<px4::params::MPC_Z_VEL_I>) MPC_Z_VEL_I,
			(ParamFloat<px4::params::MPC_Z_VEL_D>) MPC_Z_VEL_D,
			(ParamFloat<px4::params::MPC_XY_P>) MPC_XY_P,
			(ParamFloat<px4::params::MPC_XY_VEL_P>) MPC_XY_VEL_P,
			(ParamFloat<px4::params::MPC_XY_VEL_I>) MPC_XY_VEL_I,
			(ParamFloat<px4::params::MPC_XY_VEL_D>) MPC_XY_VEL_D
	)
};
<|endoftext|>


<commit_before>#ifndef INCLUDE_AL_GRAPHICS_BUFFEROBJECT_HPP
#define INCLUDE_AL_GRAPHICS_BUFFEROBJECT_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2012. The Regents of the University of California.
	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 University of California nor the names of its
		contributors may be used to endorse or promote products derived from
		this software without specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.

	File description:
	GPU buffer object helper

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include "allocore/graphics/al_GPUObject.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

/// Generic buffer object

/**
Vertex Buffer Objects (VBOs) create buffer memory for vertex attributes in
high-performance memory (in contrast, Vertex Arrays store buffer memory in the
client CPU, incurring the overhead of data transfer). If the buffer object is
used to store pixel data, it is called Pixel Buffer Object (PBO).

VBOs provide an interface to access these buffers in a similar fashion to vertex
arrays. Hints of 'target' and 'mode' help the implementation determine whether
to use system, AGP or video memory.

Unlike display lists, the data in vertex buffer object can be read and updated
by mapping the buffer into client's memory space.

Another important advantage of VBO is sharing the buffer objects with many
clients, like display lists and textures. Since VBO is on the server's side,
multiple clients will be able to access the same buffer with the corresponding
identifier.
*/
class BufferObject : public GPUObject {
public:

	/// Buffer access mode
	enum AccessMode{
		READ_ONLY				= GL_READ_ONLY,
		WRITE_ONLY				= GL_WRITE_ONLY,
		READ_WRITE				= GL_READ_WRITE
	};

	/// Array type
	enum ArrayType{
		VERTEX_ARRAY			= GL_VERTEX_ARRAY,
		NORMAL_ARRAY			= GL_NORMAL_ARRAY,
		COLOR_ARRAY				= GL_COLOR_ARRAY,
		INDEX_ARRAY				= GL_INDEX_ARRAY,
		TEXTURE_COORD_ARRAY		= GL_TEXTURE_COORD_ARRAY,
		EDGE_FLAG_ARRAY			= GL_EDGE_FLAG_ARRAY
	};

	/// Buffer type
	enum BufferType{
		ARRAY_BUFFER			= GL_ARRAY_BUFFER,
		ELEMENT_ARRAY_BUFFER	= GL_ELEMENT_ARRAY_BUFFER,
		PIXEL_PACK_BUFFER		= GL_PIXEL_PACK_BUFFER,			/**< Transfer to PBO */
		PIXEL_UNPACK_BUFFER		= GL_PIXEL_UNPACK_BUFFER		/**< Transfer from PBO */
	};

	/*
	"Static" means the data in VBO will not be changed, "Dynamic" means the data
	will be changed frequently, and "Stream" means the data will be changed every
	frame. "Draw" means the data will be sent to the GPU from the application,
	"Read" means the data will be read by the application from the GPU, and "Copy"
	means the data will be copied internally on the GPU.
	*/
	enum BufferUsage{
		STREAM_DRAW		= GL_STREAM_DRAW,
//		STREAM_READ		= GL_STREAM_READ,
//		STREAM_COPY		= GL_STREAM_COPY,
		STATIC_DRAW		= GL_STATIC_DRAW,
//		STATIC_READ		= GL_STATIC_READ,
//		STATIC_COPY		= GL_STATIC_COPY,
		DYNAMIC_DRAW	= GL_DYNAMIC_DRAW,
//		DYNAMIC_READ	= GL_DYNAMIC_READ,
//		DYNAMIC_COPY	= GL_DYNAMIC_COPY
	};

	BufferObject(BufferType bufType, BufferUsage bufUsage)
	:	mMapMode(READ_WRITE), mType(bufType), mUsage(bufUsage),
		mDataType(Graphics::FLOAT), mNumComps(0), mNumElems(0), mData(0)
	{}

	virtual ~BufferObject(){ destroy(); }

	void bufferType(BufferType v){ mType=v; }
	void mapMode(AccessMode v){ mMapMode=v; }

	void operator()(){
		//data(); onPointerFunc(); unbind();
		bind(); onPointerFunc();
	}
	void send() { (*this)(); }

	void bind(){ validate(); glBindBuffer(mType, id()); }
	void unbind() const { glBindBuffer(mType, 0); }

#ifdef AL_GRAPHICS_USE_OPENGL
	/* Warning: these are not supported in OpenGL ES */

	/// Map data store to client address space

	/// If successful, returns a valid pointer to the data, otherwise, it returns
	/// NULL.
	/// After using the pointer, call unmap() as soon as possible
	void * map(){ bind(); return glMapBuffer(mType, mMapMode); }

	/// Map data store to client address space.

	/// If successful, returns true and sets argument to address of data,
	/// otherwise, returns false and leaves argument unaffected.
	/// After using the pointer, call unmap() as soon as possible
	template <class T>
	bool map(T *& buf){
		if(Graphics::toDataType<T>() == mDataType){
			void * r = map();
			if(r){ buf=(T *)r; return true; }
		}
		return false;
	}

	/// Unmaps data store from client address
	/// After unmap(), the mapped pointer is invalid
	bool unmap(){ return glUnmapBuffer(mType)==GL_TRUE; }
#endif

	/// Set buffer data store and copy over client data
	void data(const void * src, Graphics::DataType dataType, int numElems, int numComps=1){
		mData = (void *)src;
		mDataType = dataType;
		mNumElems = numElems;
		mNumComps = numComps;
		data();
	}

	/// Set buffer data store and copy over client data
	template <class T>
	void data(const T * src, int numElems, int numComps=1){
		data(src, Graphics::toDataType<T>(), numElems, numComps);
	}

	/// Set buffer data store without copying client data
	void data(Graphics::DataType dataType, int numElems, int numComps=1){
		data(0, dataType, numElems, numComps);
	}

	/// Set buffer data store using cached values
	void data(){
		bind();
		glBufferData(mType, Graphics::numBytes(mDataType)*mNumElems*mNumComps, mData, mUsage);
		unbind();
	}

protected:
	AccessMode mMapMode;
	BufferType mType;
	BufferUsage mUsage;
	Graphics::DataType mDataType;
	int mNumComps;
	int mNumElems;
	void * mData;

	virtual void onCreate(){ glGenBuffers(1, (GLuint*)&mID); }
	virtual void onDestroy(){ glDeleteBuffers(1, (GLuint*)&mID); }
	virtual void onPointerFunc() = 0;
};

/// Vertex buffer object
class VBO : public BufferObject {
public:
	VBO(BufferUsage usage=STREAM_DRAW)
	:	BufferObject(ARRAY_BUFFER, usage){}

	static void enable(){ glEnableClientState(VERTEX_ARRAY); }
	static void disable(){ glDisableClientState(VERTEX_ARRAY); }

protected:
	virtual void onPointerFunc(){ glVertexPointer(mNumComps, mDataType, 0, 0); }
};

/// Color buffer object
class CBO : public BufferObject {
public:
	CBO(BufferUsage usage=STREAM_DRAW)
	:	BufferObject(ARRAY_BUFFER, usage){}

	static void enable(){ glEnableClientState(COLOR_ARRAY); }
	static void disable(){ glDisableClientState(COLOR_ARRAY); }

protected:
	virtual void onPointerFunc(){ glColorPointer(mNumComps, mDataType, 0, 0); }
};

/// Pixel buffer object
class PBO : public BufferObject {
public:
	PBO(bool packMode, BufferUsage usage=STREAM_DRAW)
	:	BufferObject(packMode ? PIXEL_PACK_BUFFER : PIXEL_UNPACK_BUFFER, usage){}

//	static void enable(){ glEnableClientState(ArrayType::Vertex); }
//	static void disable(){ glDisableClientState(ArrayType::Vertex); }

protected:
	virtual void onPointerFunc(){ glVertexPointer(mNumComps, mDataType, 0, 0); }
};

/// Element object buffer
class EBO : public BufferObject {
public:
	EBO(Graphics::Primitive prim=Graphics::POINTS, BufferUsage usage=STATIC_DRAW)
	:	BufferObject(ELEMENT_ARRAY_BUFFER, usage), mPrim(prim), mStart(0), mEnd(0)
	{}

	EBO& prim(Graphics::Primitive v){ mPrim=v; return *this; }
	EBO& range(int start, int end){ mStart=start; mEnd=end; return *this; }

protected:
	Graphics::Primitive mPrim;
	int mStart, mEnd;

	virtual void onPointerFunc(){
		if(mEnd)	glDrawRangeElements(mPrim, mStart, mEnd, mNumElems, mDataType, 0);
		else		glDrawRangeElements(mPrim, 0, mNumElems, mNumElems, mDataType, 0);
	}
};

/*
class BufferObjects : public GPUObject, public Drawable {
public:

	BufferObjects() {};

	virtual ~BufferObjects() {};
	virtual void draw(Graphics& gl);

	Mesh& data() { return *mData; }

protected:

	virtual void onCreate() {};
	virtual void onDestroy() {};

	Mesh mData;

	VBO mVBO;
	CBO mCBO;
	EBO mEBO;
};
*/

} // al::
#endif
<commit_msg>BufferObject: add support for sub-data<commit_after>#ifndef INCLUDE_AL_GRAPHICS_BUFFEROBJECT_HPP
#define INCLUDE_AL_GRAPHICS_BUFFEROBJECT_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2012. The Regents of the University of California.
	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 University of California nor the names of its
		contributors may be used to endorse or promote products derived from
		this software without specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.

	File description:
	GPU buffer object helper

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include "allocore/graphics/al_GPUObject.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

/// Generic buffer object

/**
Vertex Buffer Objects (VBOs) create buffer memory for vertex attributes in
high-performance memory (in contrast, Vertex Arrays store buffer memory in the
client CPU, incurring the overhead of data transfer). If the buffer object is
used to store pixel data, it is called Pixel Buffer Object (PBO).

VBOs provide an interface to access these buffers in a similar fashion to vertex
arrays. Hints of 'target' and 'mode' help the implementation determine whether
to use system, AGP or video memory.

Unlike display lists, the data in vertex buffer object can be read and updated
by mapping the buffer into client's memory space.

Another important advantage of VBO is sharing the buffer objects with many
clients, like display lists and textures. Since VBO is on the server's side,
multiple clients will be able to access the same buffer with the corresponding
identifier.
*/
class BufferObject : public GPUObject {
public:

	/// Buffer access mode
	enum AccessMode{
		READ_ONLY				= GL_READ_ONLY,
		WRITE_ONLY				= GL_WRITE_ONLY,
		READ_WRITE				= GL_READ_WRITE
	};

	/// Array type
	enum ArrayType{
		VERTEX_ARRAY			= GL_VERTEX_ARRAY,
		NORMAL_ARRAY			= GL_NORMAL_ARRAY,
		COLOR_ARRAY				= GL_COLOR_ARRAY,
		INDEX_ARRAY				= GL_INDEX_ARRAY,
		TEXTURE_COORD_ARRAY		= GL_TEXTURE_COORD_ARRAY,
		EDGE_FLAG_ARRAY			= GL_EDGE_FLAG_ARRAY
	};

	/// Buffer type
	enum BufferType{
		ARRAY_BUFFER			= GL_ARRAY_BUFFER,
		ELEMENT_ARRAY_BUFFER	= GL_ELEMENT_ARRAY_BUFFER,
		PIXEL_PACK_BUFFER		= GL_PIXEL_PACK_BUFFER,			/**< Transfer to PBO */
		PIXEL_UNPACK_BUFFER		= GL_PIXEL_UNPACK_BUFFER		/**< Transfer from PBO */
	};

	/*
	"Static" means the data in VBO will not be changed, "Dynamic" means the data
	will be changed frequently, and "Stream" means the data will be changed every
	frame. "Draw" means the data will be sent to the GPU from the application,
	"Read" means the data will be read by the application from the GPU, and "Copy"
	means the data will be copied internally on the GPU.
	*/
	enum BufferUsage{
		STREAM_DRAW		= GL_STREAM_DRAW,
		//STREAM_READ		= GL_STREAM_READ,
		//STREAM_COPY		= GL_STREAM_COPY,
		STATIC_DRAW		= GL_STATIC_DRAW,
		//STATIC_READ		= GL_STATIC_READ,
		//STATIC_COPY		= GL_STATIC_COPY,
		DYNAMIC_DRAW	= GL_DYNAMIC_DRAW,
		//DYNAMIC_READ	= GL_DYNAMIC_READ,
		//DYNAMIC_COPY	= GL_DYNAMIC_COPY
	};

	BufferObject(BufferType bufType, BufferUsage bufUsage)
	:	mMapMode(READ_WRITE), mType(bufType), mUsage(bufUsage),
		mDataType(Graphics::FLOAT), mNumComps(0), mNumElems(0), mData(0)
	{}

	virtual ~BufferObject(){ destroy(); }

	void bufferType(BufferType v){ mType=v; }

	void usage(BufferUsage v){ mUsage=v; }

	void mapMode(AccessMode v){ mMapMode=v; }

	void operator()(){
		//data(); onPointerFunc(); unbind();
		bind(); onPointerFunc();
	}
	void send() { (*this)(); }

	void bind(){ validate(); glBindBuffer(mType, id()); }
	void unbind() const { glBindBuffer(mType, 0); }

#ifdef AL_GRAPHICS_USE_OPENGL
	/* Warning: these are not supported in OpenGL ES */

	/// Map data store to client address space

	/// If successful, returns a valid pointer to the data, otherwise, it returns
	/// NULL.
	/// After using the pointer, call unmap() as soon as possible
	void * map(){ bind(); return glMapBuffer(mType, mMapMode); }

	/// Map data store to client address space.

	/// If successful, returns true and sets argument to address of data,
	/// otherwise, returns false and leaves argument unaffected.
	/// After using the pointer, call unmap() as soon as possible
	template <class T>
	bool map(T *& buf){
		if(Graphics::toDataType<T>() == mDataType){
			void * r = map();
			if(r){ buf=(T *)r; return true; }
		}
		return false;
	}

	/// Unmaps data store from client address
	/// After unmap(), the mapped pointer is invalid
	bool unmap(){ return glUnmapBuffer(mType)==GL_TRUE; }
#endif

	/// Set size, in bytes, of buffer without sending data
	void resize(int numBytes){
		mData = NULL;
		mDataType = Graphics::BYTE;
		mNumElems = numBytes;
		mNumComps = 1;
		data();
	}

	/// Set buffer data store and copy over client data
	void data(const void * src, Graphics::DataType dataType, int numElems, int numComps=1){
		mData = (void *)src;
		mDataType = dataType;
		mNumElems = numElems;
		mNumComps = numComps;
		data();
	}

	/// Set buffer data store and copy over client data
	template <class T>
	void data(const T * src, int numElems, int numComps=1){
		data(src, Graphics::toDataType<T>(), numElems, numComps);
	}

	/// Set buffer data store without copying client data
	void data(Graphics::DataType dataType, int numElems, int numComps=1){
		data(0, dataType, numElems, numComps);
	}

	/// Set buffer data store using cached values
	void data(){
		bind();
		glBufferData(mType, Graphics::numBytes(mDataType)*mNumElems*mNumComps, mData, mUsage);
		unbind();
	}

	/// Set subregion of buffer store
	template <class T>
	int subData(const T * src, int numElems, int byteOffset=0){
		if(numElems){
			bind();
			glBufferSubData(mType, byteOffset, numElems*sizeof(T), src);
			unbind();
		}
		return numElems*sizeof(T) + byteOffset;
	}

protected:
	AccessMode mMapMode;
	BufferType mType;
	BufferUsage mUsage;
	Graphics::DataType mDataType;
	int mNumComps;
	int mNumElems;
	void * mData;

	virtual void onCreate(){ glGenBuffers(1, (GLuint*)&mID); }
	virtual void onDestroy(){ glDeleteBuffers(1, (GLuint*)&mID); }
	virtual void onPointerFunc() = 0;
};

/// Vertex buffer object
class VBO : public BufferObject {
public:
	VBO(BufferUsage usage=STREAM_DRAW)
	:	BufferObject(ARRAY_BUFFER, usage){}

	static void enable(){ glEnableClientState(VERTEX_ARRAY); }
	static void disable(){ glDisableClientState(VERTEX_ARRAY); }

protected:
	virtual void onPointerFunc(){ glVertexPointer(mNumComps, mDataType, 0, 0); }
};

/// Color buffer object
class CBO : public BufferObject {
public:
	CBO(BufferUsage usage=STREAM_DRAW)
	:	BufferObject(ARRAY_BUFFER, usage){}

	static void enable(){ glEnableClientState(COLOR_ARRAY); }
	static void disable(){ glDisableClientState(COLOR_ARRAY); }

protected:
	virtual void onPointerFunc(){ glColorPointer(mNumComps, mDataType, 0, 0); }
};

/// Pixel buffer object
class PBO : public BufferObject {
public:
	PBO(bool packMode, BufferUsage usage=STREAM_DRAW)
	:	BufferObject(packMode ? PIXEL_PACK_BUFFER : PIXEL_UNPACK_BUFFER, usage){}

//	static void enable(){ glEnableClientState(ArrayType::Vertex); }
//	static void disable(){ glDisableClientState(ArrayType::Vertex); }

protected:
	virtual void onPointerFunc(){ glVertexPointer(mNumComps, mDataType, 0, 0); }
};

/// Element object buffer
class EBO : public BufferObject {
public:
	EBO(Graphics::Primitive prim=Graphics::POINTS, BufferUsage usage=STATIC_DRAW)
	:	BufferObject(ELEMENT_ARRAY_BUFFER, usage), mPrim(prim), mStart(0), mEnd(0)
	{}

	EBO& primitive(Graphics::Primitive v){ mPrim=v; return *this; }
	EBO& range(int start, int end){ mStart=start; mEnd=end; return *this; }

protected:
	Graphics::Primitive mPrim;
	int mStart, mEnd;

	virtual void onPointerFunc(){
		if(mEnd)	glDrawRangeElements(mPrim, mStart, mEnd, mNumElems, mDataType, 0);
		else		glDrawRangeElements(mPrim, 0, mNumElems, mNumElems, mDataType, 0);
	}
};

/*
class BufferObjects : public GPUObject, public Drawable {
public:

	BufferObjects() {};

	virtual ~BufferObjects() {};
	virtual void draw(Graphics& gl);

	Mesh& data() { return *mData; }

protected:

	virtual void onCreate() {};
	virtual void onDestroy() {};

	Mesh mData;

	VBO mVBO;
	CBO mCBO;
	EBO mEBO;
};
*/

} // al::
#endif
<|endoftext|>


<commit_before>#include "parallel.h"
#include <iostream>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "cmdLineOptions.h"
#include "h5test.h"

void printVersion(const char* execName)
{
  if (P.myProc == 0)
    std::cerr << execName << " Version: " << H5TEST_VERSION << std::endl;
}

void printUsage(const char* execName)
{
  printVersion(execName);

  if (P.myProc == 0)
    std::cerr << "\nUsage:\n"
              << execName << " [options]\n\n"
              << "Options:\n"
              << " -h, -?        : Print Usage\n"
              << " -v            : Print Version\n"
              << " -C            : use h5 chunk\n"
              << " -S            : use h5 slab (default)\n"
              << " -N            : no T3PIO\n"
              << " -O type       : output type (l: lua, t: table, b: both (default: table))\n"
              << " -n nvar       : nvar  (default=4)\n"
              << " -l num        : local size is num (default=10)\n"
              << " -g num        : global size is num\n"
              << " -f factor     : number of stripes per writer (default=2)\n"
              << " -s num        : maximum number of stripes\n"
              << " -z num        : maximum stripe size in MB\n"
              << " -p num        : maximum number of writers per node\n"
              << " -w num        : Total number of writers\n"
              << std::endl;
}

CmdLineOptions::CmdLineOptions(int argc, char* argv[])
  : m_state(iBAD)
{
  int  opt;
  bool version, help, illegal;
  char choice;

  maxWritersPer  = INT_MAX;

  useT3PIO         = true;
  maxWriters       = -1;
  version          = false;
  help             = false;
  localSz          = -1;
  globalSz         = -1;
  h5chunk          = false;
  h5slab           = false;
  factor           = 1;
  stripes          = -1;
  stripeSz         = -1;
  h5style          = "h5slab";
  luaStyleOutput   = false;
  tableStyleOutput = true;

  while ( (opt = getopt(argc, argv, "s:hCSLO:f:p:w:l:g:n:z:?v")) != -1)
    {
      switch (opt)
        {
        case 'v':
          version = true;
          break;
        case '?':
        case 'h':
          help = true;
          break;
        case 'C':
          h5chunk = true;
          break;
        case 'N':
          useT3PIO = false;
          break;
        case 'f':
          factor  = strtol(optarg, (char **) NULL, 10);
          break;
        case 's':
          stripes = strtol(optarg, (char **) NULL, 10);
          break;
        case 'z':
          stripeSz = strtol(optarg, (char **) NULL, 10);
          break;
        case 'g':
          globalSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'l':
          localSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'n':
          nvar =    strtol(optarg, (char **) NULL, 10);
          break;
        case 'O':
          choice         = tolower(optarg[0]);
          luaStyleOutput = ( choice == 'b' || choice == 'l')
          break;
        case 'p':
          maxWritersPer = strtol(optarg, (char **) NULL, 10);
          break;
        case 'w':
          maxWriters    = strtol(optarg, (char **) NULL, 10);
          break;
        case 'S':
          h5slab = true;
          break;
        default:
          illegal = true;
          ;
        }
    }

  if (version)
    {
      m_state = iHELP;
      printVersion(argv[0]);
      return;
    }

  if (help)
    {
      m_state = iHELP;
      printUsage(argv[0]);
      return;
    }

  if (! h5chunk && ! h5slab)
    h5slab = true;

  if ( h5chunk )
    h5style = "h5chunk";

  if (localSz < 0)
    {
      if (globalSz < 0)
        localSz = 10;
      else
        {
          int rem = globalSz % P.nProcs;
          localSz = globalSz/P.nProcs + (P.myProc < rem);
        }
    }

  if (globalSz < 0)
    globalSz = localSz * P.nProcs;

  m_state = iGOOD;
}

<commit_msg>better output report control with -O option<commit_after>#include "parallel.h"
#include <iostream>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "cmdLineOptions.h"
#include "h5test.h"

void printVersion(const char* execName)
{
  if (P.myProc == 0)
    std::cerr << execName << " Version: " << H5TEST_VERSION << std::endl;
}

void printUsage(const char* execName)
{
  printVersion(execName);

  if (P.myProc == 0)
    std::cerr << "\nUsage:\n"
              << execName << " [options]\n\n"
              << "Options:\n"
              << " -h, -?        : Print Usage\n"
              << " -v            : Print Version\n"
              << " -C            : use h5 chunk\n"
              << " -S            : use h5 slab (default)\n"
              << " -N            : no T3PIO\n"
              << " -O type       : output type (l: lua, t: table, b: both (default: table))\n"
              << " -n nvar       : nvar  (default=4)\n"
              << " -l num        : local size is num (default=10)\n"
              << " -g num        : global size is num\n"
              << " -f factor     : number of stripes per writer (default=2)\n"
              << " -s num        : maximum number of stripes\n"
              << " -z num        : maximum stripe size in MB\n"
              << " -p num        : maximum number of writers per node\n"
              << " -w num        : Total number of writers\n"
              << std::endl;
}

CmdLineOptions::CmdLineOptions(int argc, char* argv[])
  : m_state(iBAD)
{
  int  opt;
  bool version, help, illegal;
  char choice;

  maxWritersPer  = INT_MAX;

  useT3PIO         = true;
  maxWriters       = -1;
  version          = false;
  help             = false;
  localSz          = -1;
  globalSz         = -1;
  h5chunk          = false;
  h5slab           = false;
  factor           = 1;
  stripes          = -1;
  stripeSz         = -1;
  h5style          = "h5slab";
  luaStyleOutput   = false;
  tableStyleOutput = true;

  while ( (opt = getopt(argc, argv, "s:hCSLO:f:p:w:l:g:n:z:?v")) != -1)
    {
      switch (opt)
        {
        case 'v':
          version = true;
          break;
        case '?':
        case 'h':
          help = true;
          break;
        case 'C':
          h5chunk = true;
          break;
        case 'N':
          useT3PIO = false;
          break;
        case 'f':
          factor  = strtol(optarg, (char **) NULL, 10);
          break;
        case 's':
          stripes = strtol(optarg, (char **) NULL, 10);
          break;
        case 'z':
          stripeSz = strtol(optarg, (char **) NULL, 10);
          break;
        case 'g':
          globalSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'l':
          localSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'n':
          nvar =    strtol(optarg, (char **) NULL, 10);
          break;
        case 'O':
          choice         = tolower(optarg[0]);
          luaStyleOutput = ( choice == 'b' || choice == 'l');
          break;
        case 'p':
          maxWritersPer = strtol(optarg, (char **) NULL, 10);
          break;
        case 'w':
          maxWriters    = strtol(optarg, (char **) NULL, 10);
          break;
        case 'S':
          h5slab = true;
          break;
        default:
          illegal = true;
          ;
        }
    }

  if (version)
    {
      m_state = iHELP;
      printVersion(argv[0]);
      return;
    }

  if (help)
    {
      m_state = iHELP;
      printUsage(argv[0]);
      return;
    }

  if (! h5chunk && ! h5slab)
    h5slab = true;

  if ( h5chunk )
    h5style = "h5chunk";

  if (localSz < 0)
    {
      if (globalSz < 0)
        localSz = 10;
      else
        {
          int rem = globalSz % P.nProcs;
          localSz = globalSz/P.nProcs + (P.myProc < rem);
        }
    }

  if (globalSz < 0)
    globalSz = localSz * P.nProcs;

  m_state = iGOOD;
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// interface header
#include "TimeKeeper.h"

// system implementation headers
#include <time.h>
#include <string>
#include <string.h>
#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif
#ifdef __BEOS__
#  include <OS.h>
#endif
#if !defined(_WIN32)
#  include <sys/time.h>
#  include <sys/types.h>
static int64_t lastTime = 0;
#  ifdef HAVE_SCHED_H
#    include <sched.h>
#  endif
#else // !defined(_WIN32)
#  include <mmsystem.h>
static unsigned long int lastTime = 0;
static LARGE_INTEGER     qpcLastTime;
static LONGLONG          qpcFrequency = 0;
static LONGLONG          qpcLastCalibration;
static DWORD             timeLastCalibration;
#endif // !defined(_WIN32)

// common implementation headers
#include "TextUtils.h"
#include "bzfio.h"

static TimeKeeper currentTime;
static TimeKeeper tickTime;
static TimeKeeper sunExplodeTime;
static TimeKeeper sunGenesisTime;
static TimeKeeper nullTime;
static TimeKeeper startTime = TimeKeeper::getCurrent();

#if !defined(_WIN32)
static inline int64_t getEpochMicroseconds()
{
  struct timeval nowTime;
  gettimeofday(&nowTime, NULL);
  return (int64_t(nowTime.tv_sec) * int64_t(1000000))
        + int64_t(nowTime.tv_usec);
}
#endif

const TimeKeeper& TimeKeeper::getCurrent(void)
{
  // if not first call then update current time, else use default initial time
#if !defined(_WIN32)
  if (lastTime == 0) {
    // time starts at 0 seconds from the first call to getCurrent()
    lastTime = getEpochMicroseconds();
  }
  else {
    const int64_t nowTime = getEpochMicroseconds();

    int64_t diff = (nowTime - lastTime);
    if (diff < 0) {
      logDebugMessage(5, "WARNING: went back in time %li microseconds\n",
                      (long int)diff);
      diff = 0; // eh, how'd we go back in time?
    }

    currentTime += double(diff) * 1.0e-6;;

    lastTime = nowTime;
  }
#else /* !defined(_WIN32) */
  if (qpcFrequency != 0) {

    // main timer is qpc
    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);

    LONGLONG diff     = now.QuadPart - qpcLastTime.QuadPart;
    LONGLONG clkSpent = now.QuadPart - qpcLastCalibration;
    qpcLastTime = now;

    if (clkSpent > qpcFrequency) {
      // Recalibrate Frequency
      DWORD tgt	   = timeGetTime();
      DWORD deltaTgt      = tgt - timeLastCalibration;
      timeLastCalibration = tgt;
      qpcLastCalibration  = now.QuadPart;
      if (deltaTgt > 0) {
	LONGLONG oldqpcfreq = qpcFrequency;
	qpcFrequency	= (clkSpent * 1000) / deltaTgt;
	if (qpcFrequency != oldqpcfreq)
	  logDebugMessage(4, "Recalibrated QPC frequency.  Old: %f ; New: %f\n",
			  (double)oldqpcfreq, (double)qpcFrequency);
      }
    }

    currentTime += (double) diff / (double) qpcFrequency;
  } else if (lastTime != 0) {
    unsigned long int now = (unsigned long int)timeGetTime();
    unsigned long int diff;
    if (now < lastTime) {
      // eh, how'd we go back in time?
      diff = 0;
    } else {
      diff = now - lastTime;
    }
    currentTime += 1.0e-3 * (double)diff;
    lastTime = now;
  } else {
    static bool sane = true;

    // should only get into here once on app start
    if (!sane) {
      logDebugMessage(1,"Sanity check failure in TimeKeeper::getCurrent()\n");
    }
    sane = false;

    // make sure we're at our best timer resolution possible
    timeBeginPeriod(1);

    LARGE_INTEGER freq;
    if (QueryPerformanceFrequency(&freq)) {
      QueryPerformanceCounter(&qpcLastTime);
      qpcFrequency	= freq.QuadPart;
      logDebugMessage(4,"Actual reported QPC Frequency: %f\n", (double)qpcFrequency);
      qpcLastCalibration  = qpcLastTime.QuadPart;
      timeLastCalibration = timeGetTime();
    } else {
      logDebugMessage(1,"QueryPerformanceFrequency failed with error %d\n", GetLastError());

      lastTime = (unsigned long int)timeGetTime();
    }
  }
#endif /* !defined(_WIN32) */
  return currentTime;
}

const TimeKeeper& TimeKeeper::getStartTime(void) // const
{
  return startTime;
}

const TimeKeeper& TimeKeeper::getTick(void) // const
{
  return tickTime;
}

void TimeKeeper::setTick(void)
{
  tickTime = getCurrent();
}

const TimeKeeper& TimeKeeper::getSunExplodeTime(void)
{
  sunExplodeTime.seconds = 10000.0 * 365 * 24 * 60 * 60;
  return sunExplodeTime;
}

const TimeKeeper& TimeKeeper::getSunGenesisTime(void)
{
  sunGenesisTime.seconds = -10000.0 * 365 * 24 * 60 * 60;
  return sunGenesisTime;
}

const TimeKeeper& TimeKeeper::getNullTime(void)
{
  nullTime.seconds = 0;
  return nullTime;
}

const char *TimeKeeper::timestamp(void) // const
{
  static char buffer[256]; // static, so that it doesn't vanish
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  strncpy (buffer, TextUtils::format("%04d-%02d-%02d %02d:%02d:%02d",
				     now->tm_year, now->tm_mon, now->tm_mday,
				     now->tm_hour, now->tm_min, now->tm_sec).c_str(), 256);
  buffer[255] = '\0'; // safety

  return buffer;
}

/** returns a short string of the local time */
//static
std::string TimeKeeper::shortTimeStamp(void) {
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);

  std::string result( TextUtils::format("%02d:%02d", now->tm_hour, now->tm_min) );
  return result;
}

void TimeKeeper::localTime(int *year, int *month, int* day,
                           int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::localTimeDOW(int *year, int *month, int* day, int* wday,
                              int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::UTCTime(int *year, int *month, int* day, int* wday,
                         int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = gmtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

// function for converting a float time (e.g. difference of two TimeKeepers)
// into an array of ints
void TimeKeeper::convertTime(double raw, long int convertedTimes[]) // const
{
  long int day, hour, min, sec, remainder;
  static const int secondsInDay = 86400;

  sec = (long int)raw;
  day = sec / secondsInDay;
  remainder = sec - (day * secondsInDay);
  hour = remainder / 3600;
  remainder = sec - ((hour * 3600) + (day * secondsInDay));
  min = remainder / 60;
  remainder = sec - ((hour * 3600) + (day * secondsInDay) + (min * 60));
  sec = remainder;

  convertedTimes[0] = day;
  convertedTimes[1] = hour;
  convertedTimes[2] = min;
  convertedTimes[3] = sec;

  return;
}

// function for printing an array of ints representing a time
// as a human-readable string
const std::string TimeKeeper::printTime(long int timeValue[])
{
  std::string valueNames;
  char temp[20];

  if (timeValue[0] > 0) {
    snprintf(temp, 20, "%ld day%s", timeValue[0], timeValue[0] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[1] > 0) {
    if (timeValue[0] > 0) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld hour%s", timeValue[1], timeValue[1] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[2] > 0) {
    if ((timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld min%s", timeValue[2], timeValue[2] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[3] > 0) {
    if ((timeValue[2] > 0) || (timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld sec%s", timeValue[3], timeValue[3] == 1 ? "" : "s");
    valueNames.append(temp);
  }

  return valueNames;
}

// function for printing a float time difference as a human-readable string
const std::string TimeKeeper::printTime(double diff)
{
  long int temp[4];
  convertTime(diff, temp);
  return printTime(temp);
}

void TimeKeeper::sleep(double seconds)
{
  if (seconds <= 0.0) {
    return;
  }

#ifdef HAVE_USLEEP
  usleep((unsigned int)(1.0e6 * seconds));
  return;
#endif
#if defined(HAVE_SLEEP) && !defined(__APPLE__)
  // equivalent to _sleep() on win32 (not sleep(3))
  Sleep((DWORD)(seconds * 1000.0));
  return;
#endif
#ifdef HAVE_SNOOZE
  snooze((bigtime_t)(1.0e6 * seconds));
  return;
#endif
#ifdef HAVE_SELECT
  struct timeval tv;
  tv.tv_sec = (long)seconds;
  tv.tv_usec = (long)(1.0e6 * (seconds - tv.tv_sec));
  select(0, NULL, NULL, NULL, &tv);
  return;
#endif
#ifdef HAVE_WAITFORSINGLEOBJECT
  HANDLE dummyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  WaitForSingleObject(dummyEvent, (DWORD)(1000.0 * seconds));
  CloseHandle(dummyEvent);
  return;
#endif

  // fall-back case is fugly manual timekeeping
  TimeKeeper now = TimeKeeper::getCurrent();
  while ((TimeKeeper::getCurrent() - now) < seconds) {
    continue;
  }
  return;
}

void TimeKeeper::setProcessorAffinity(int processor)
{
#ifdef HAVE_SCHED_SETAFFINITY
  /* linuxy fix for time travel */
  cpu_set_t mask;
  CPU_ZERO(&mask);
  CPU_SET(processor, &mask);
  sched_setaffinity(0, sizeof(mask), &mask);
#elif defined(WIN32)
  /* windowsy fix for time travel */
  HANDLE hThread = GetCurrentThread();
  DWORD_PTR dwMask = 1 << processor;
  DWORD_PTR dwProcs = 0;
  GetProcessAffinityMask(NULL, NULL, &dwProcs);
  if (dwMask < dwProcs) {
    logDebugMessage(1, "Unable to set process affinity mask (specified processor does not exist).\n");
    return;
  }
  SetThreadAffinityMask(hThread, dwMask);
#else
  logDebugMessage(1, "Unable to set processor affinity to %d - function not implemented on this platform.\n", processor);
#endif
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>* added a mutex lock around getCurrent() to protect against the sound thread   (needs to be tested on windows, should probably add the debug message there    as well)<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// interface header
#include "TimeKeeper.h"

// system headers
#include <time.h>
#include <string>
#include <string.h>
#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif
#ifdef __BEOS__
#  include <OS.h>
#endif
#if !defined(_WIN32)
#  include <sys/time.h>
#  include <sys/types.h>
static int64_t lastTime = 0;
#  ifdef HAVE_SCHED_H
#    include <sched.h>
#  endif
#else // !defined(_WIN32)
#  include <mmsystem.h>
static unsigned long int lastTime = 0;
static LARGE_INTEGER     qpcLastTime;
static LONGLONG          qpcFrequency = 0;
static LONGLONG          qpcLastCalibration;
static DWORD             timeLastCalibration;
#endif // !defined(_WIN32)

// system threading headers
#ifndef _WIN32
#  include <sys/types.h>
#  include <dirent.h>
#endif
#ifdef HAVE_PTHREADS
#  include <pthread.h>
#endif

// common headers
#include "TextUtils.h"
#include "bzfio.h"

//============================================================================//

#if defined(HAVE_PTHREADS)
  static pthread_mutex_t    timer_mutex;
# define LOCK_TIMER_MUTEX   pthread_mutex_lock(&timer_mutex);
# define UNLOCK_TIMER_MUTEX pthread_mutex_unlock(&timer_mutex);
#elif defined(_WIN32)
  static CRITICAL_SECTION   timer_critical;
# define LOCK_TIMER_MUTEX   EnterCriticalSection(&timer_critical);
# define UNLOCK_TIMER_MUTEX LeaveCriticalSection(&timer_critical);
#else
# define LOCK_TIMER_MUTEX
# define UNLOCK_TIMER_MUTEX
#endif

//============================================================================//

static TimeKeeper currentTime;
static TimeKeeper tickTime;
static TimeKeeper sunExplodeTime;
static TimeKeeper sunGenesisTime;
static TimeKeeper nullTime;
static TimeKeeper startTime = TimeKeeper::getCurrent();

//============================================================================//

#if !defined(_WIN32)
static inline int64_t getEpochMicroseconds()
{
  struct timeval nowTime;
  gettimeofday(&nowTime, NULL);
  return (int64_t(nowTime.tv_sec) * int64_t(1000000))
        + int64_t(nowTime.tv_usec);
}
#endif

const TimeKeeper& TimeKeeper::getCurrent(void)
{
  LOCK_TIMER_MUTEX

  // if not first call then update current time, else use default initial time
#if !defined(_WIN32)
  if (lastTime == 0) {
    // time starts at 0 seconds from the first call to getCurrent()
    lastTime = getEpochMicroseconds();
  }
  else {
    const int64_t nowTime = getEpochMicroseconds();

    int64_t diff = (nowTime - lastTime);
    if (diff < 0) {
      logDebugMessage(5, "WARNING: went back in time %li microseconds\n",
                      (long int)diff);
      diff = 0; // eh, how'd we go back in time?
    }

    currentTime += double(diff) * 1.0e-6;;

    lastTime = nowTime;
  }
#else /* !defined(_WIN32) */
  if (qpcFrequency != 0) {

    // main timer is qpc
    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);

    LONGLONG diff     = now.QuadPart - qpcLastTime.QuadPart;
    LONGLONG clkSpent = now.QuadPart - qpcLastCalibration;
    qpcLastTime = now;

    if (clkSpent > qpcFrequency) {
      // Recalibrate Frequency
      DWORD tgt	   = timeGetTime();
      DWORD deltaTgt      = tgt - timeLastCalibration;
      timeLastCalibration = tgt;
      qpcLastCalibration  = now.QuadPart;
      if (deltaTgt > 0) {
	LONGLONG oldqpcfreq = qpcFrequency;
	qpcFrequency	= (clkSpent * 1000) / deltaTgt;
	if (qpcFrequency != oldqpcfreq)
	  logDebugMessage(4, "Recalibrated QPC frequency.  Old: %f ; New: %f\n",
			  (double)oldqpcfreq, (double)qpcFrequency);
      }
    }

    currentTime += (double) diff / (double) qpcFrequency;
  } else if (lastTime != 0) {
    unsigned long int now = (unsigned long int)timeGetTime();
    unsigned long int diff;
    if (now < lastTime) {
      // eh, how'd we go back in time?
      diff = 0;
    } else {
      diff = now - lastTime;
    }
    currentTime += 1.0e-3 * (double)diff;
    lastTime = now;
  } else {
    static bool sane = true;

    // should only get into here once on app start
    if (!sane) {
      logDebugMessage(1,"Sanity check failure in TimeKeeper::getCurrent()\n");
    }
    sane = false;

    // make sure we're at our best timer resolution possible
    timeBeginPeriod(1);

    LARGE_INTEGER freq;
    if (QueryPerformanceFrequency(&freq)) {
      QueryPerformanceCounter(&qpcLastTime);
      qpcFrequency	= freq.QuadPart;
      logDebugMessage(4,"Actual reported QPC Frequency: %f\n", (double)qpcFrequency);
      qpcLastCalibration  = qpcLastTime.QuadPart;
      timeLastCalibration = timeGetTime();
    } else {
      logDebugMessage(1,"QueryPerformanceFrequency failed with error %d\n", GetLastError());

      lastTime = (unsigned long int)timeGetTime();
    }
  }
#endif /* !defined(_WIN32) */

  UNLOCK_TIMER_MUTEX

  return currentTime;
}

const TimeKeeper& TimeKeeper::getStartTime(void) // const
{
  return startTime;
}

const TimeKeeper& TimeKeeper::getTick(void) // const
{
  return tickTime;
}

void TimeKeeper::setTick(void)
{
  tickTime = getCurrent();
}

const TimeKeeper& TimeKeeper::getSunExplodeTime(void)
{
  sunExplodeTime.seconds = 10000.0 * 365 * 24 * 60 * 60;
  return sunExplodeTime;
}

const TimeKeeper& TimeKeeper::getSunGenesisTime(void)
{
  sunGenesisTime.seconds = -10000.0 * 365 * 24 * 60 * 60;
  return sunGenesisTime;
}

const TimeKeeper& TimeKeeper::getNullTime(void)
{
  nullTime.seconds = 0;
  return nullTime;
}

const char *TimeKeeper::timestamp(void) // const
{
  static char buffer[256]; // static, so that it doesn't vanish
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  strncpy (buffer, TextUtils::format("%04d-%02d-%02d %02d:%02d:%02d",
				     now->tm_year, now->tm_mon, now->tm_mday,
				     now->tm_hour, now->tm_min, now->tm_sec).c_str(), 256);
  buffer[255] = '\0'; // safety

  return buffer;
}

/** returns a short string of the local time */
//static
std::string TimeKeeper::shortTimeStamp(void) {
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);

  std::string result( TextUtils::format("%02d:%02d", now->tm_hour, now->tm_min) );
  return result;
}

void TimeKeeper::localTime(int *year, int *month, int* day,
                           int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::localTimeDOW(int *year, int *month, int* day, int* wday,
                              int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::UTCTime(int *year, int *month, int* day, int* wday,
                         int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = gmtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

// function for converting a float time (e.g. difference of two TimeKeepers)
// into an array of ints
void TimeKeeper::convertTime(double raw, long int convertedTimes[]) // const
{
  long int day, hour, min, sec, remainder;
  static const int secondsInDay = 86400;

  sec = (long int)raw;
  day = sec / secondsInDay;
  remainder = sec - (day * secondsInDay);
  hour = remainder / 3600;
  remainder = sec - ((hour * 3600) + (day * secondsInDay));
  min = remainder / 60;
  remainder = sec - ((hour * 3600) + (day * secondsInDay) + (min * 60));
  sec = remainder;

  convertedTimes[0] = day;
  convertedTimes[1] = hour;
  convertedTimes[2] = min;
  convertedTimes[3] = sec;

  return;
}

// function for printing an array of ints representing a time
// as a human-readable string
const std::string TimeKeeper::printTime(long int timeValue[])
{
  std::string valueNames;
  char temp[20];

  if (timeValue[0] > 0) {
    snprintf(temp, 20, "%ld day%s", timeValue[0], timeValue[0] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[1] > 0) {
    if (timeValue[0] > 0) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld hour%s", timeValue[1], timeValue[1] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[2] > 0) {
    if ((timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld min%s", timeValue[2], timeValue[2] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[3] > 0) {
    if ((timeValue[2] > 0) || (timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld sec%s", timeValue[3], timeValue[3] == 1 ? "" : "s");
    valueNames.append(temp);
  }

  return valueNames;
}

// function for printing a float time difference as a human-readable string
const std::string TimeKeeper::printTime(double diff)
{
  long int temp[4];
  convertTime(diff, temp);
  return printTime(temp);
}

void TimeKeeper::sleep(double seconds)
{
  if (seconds <= 0.0) {
    return;
  }

#ifdef HAVE_USLEEP
  usleep((unsigned int)(1.0e6 * seconds));
  return;
#endif
#if defined(HAVE_SLEEP) && !defined(__APPLE__)
  // equivalent to _sleep() on win32 (not sleep(3))
  Sleep((DWORD)(seconds * 1000.0));
  return;
#endif
#ifdef HAVE_SNOOZE
  snooze((bigtime_t)(1.0e6 * seconds));
  return;
#endif
#ifdef HAVE_SELECT
  struct timeval tv;
  tv.tv_sec = (long)seconds;
  tv.tv_usec = (long)(1.0e6 * (seconds - tv.tv_sec));
  select(0, NULL, NULL, NULL, &tv);
  return;
#endif
#ifdef HAVE_WAITFORSINGLEOBJECT
  HANDLE dummyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  WaitForSingleObject(dummyEvent, (DWORD)(1000.0 * seconds));
  CloseHandle(dummyEvent);
  return;
#endif

  // fall-back case is fugly manual timekeeping
  TimeKeeper now = TimeKeeper::getCurrent();
  while ((TimeKeeper::getCurrent() - now) < seconds) {
    continue;
  }
  return;
}

void TimeKeeper::setProcessorAffinity(int processor)
{
#ifdef HAVE_SCHED_SETAFFINITY
  /* linuxy fix for time travel */
  cpu_set_t mask;
  CPU_ZERO(&mask);
  CPU_SET(processor, &mask);
  sched_setaffinity(0, sizeof(mask), &mask);
#elif defined(WIN32)
  /* windowsy fix for time travel */
  HANDLE hThread = GetCurrentThread();
  DWORD_PTR dwMask = 1 << processor;
  DWORD_PTR dwProcs = 0;
  GetProcessAffinityMask(NULL, NULL, &dwProcs);
  if (dwMask < dwProcs) {
    logDebugMessage(1, "Unable to set process affinity mask (specified processor does not exist).\n");
    return;
  }
  SetThreadAffinityMask(hThread, dwMask);
#else
  logDebugMessage(1, "Unable to set processor affinity to %d - function not implemented on this platform.\n", processor);
#endif
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdQuicklookViewRenderer.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
#include <QtOpenGL>

//
// System includes (sorted by alphabetic order)
// necessary for the opengl variables and methods

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdDatasetModel.h"
#include "Core/mvdTypes.h"
#include "Core/mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::QuicklookViewRenderer

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*****************************************************************************/
QuicklookViewRenderer
::QuicklookViewRenderer( QObject* parent ) :
  ImageViewRenderer( parent ),
  m_GlRoiActor( otb::GlROIActor::New() )
{
  assert( !m_GlRoiActor.IsNull() );
  this->SetReferenceActorShaderMode("STANDARD");
}

/*****************************************************************************/
QuicklookViewRenderer
::~QuicklookViewRenderer()
{
}

/*****************************************************************************/
AbstractImageViewRenderer::RenderingContext*
QuicklookViewRenderer
::NewRenderingContext() const
{
  RenderingContext* context = new QuicklookViewRenderer::RenderingContext();

#if USE_VIEW_SETTINGS_SIDE_EFFECT
#else
  assert( !m_GlView.IsNull() );

  //
  // Share otb::GlViewRendering settings with manipulator using
  // RenderingContext. Manipulator can then setup otb::ViewSettings
  // directly by side-effect.
  context->m_ViewSettings = m_GlView->GetSettings();
#endif

  return context;
}

/*******************************************************************************/
void
QuicklookViewRenderer
::virtual_FinishScene()
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_FinishScene()";

  otb::GlImageActor::Pointer referenceGlImageActor( GetReferenceGlImageActor() );

  if( referenceGlImageActor.IsNull() )
    return;

  std::string key( m_GlView->AddActor( m_GlRoiActor ) );

  m_GlRoiActor->SetVisible( true );

  m_GlRoiActor->SetKwl( referenceGlImageActor->GetKwl() );
  m_GlRoiActor->SetWkt( referenceGlImageActor->GetWkt() );

  /*
  ColorType color;

  color.Fill( 1.0 );

  m_GlRoiActor->SetColor( color );
  */
  m_GlRoiActor->SetFill( true );
  m_GlRoiActor->SetAlpha( 0.2 );

  m_GlView->MoveActorToEndOfRenderingOrder( key, true );
}

/*****************************************************************************/
void
QuicklookViewRenderer
::UpdateActors( const AbstractImageViewRenderer::RenderingContext* c )
{
  assert( c!=NULL );

  ImageViewRenderer::UpdateActors( c );

  assert(
    c==dynamic_cast< const QuicklookViewRenderer::RenderingContext * >( c )
  );

  const QuicklookViewRenderer::RenderingContext * context =
    dynamic_cast< const QuicklookViewRenderer::RenderingContext * >( c );

  /*
  qDebug()
    << "ROI-origin:"
    << context->m_RoiOrigin[ 0 ] << "," << context->m_RoiOrigin[ 1 ]
    << "ROI-extent:"
    << context->m_RoiExtent[ 0 ] << "," << context->m_RoiExtent[ 1 ];
  */

  m_GlRoiActor->SetUL( context->m_RoiOrigin );
  m_GlRoiActor->SetLR( context->m_RoiExtent );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/

} // end namespace 'mvd'
<commit_msg>ENH: ROI should not be filled (odd when viewing large regions)<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdQuicklookViewRenderer.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
#include <QtOpenGL>

//
// System includes (sorted by alphabetic order)
// necessary for the opengl variables and methods

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdDatasetModel.h"
#include "Core/mvdTypes.h"
#include "Core/mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::QuicklookViewRenderer

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*****************************************************************************/
QuicklookViewRenderer
::QuicklookViewRenderer( QObject* parent ) :
  ImageViewRenderer( parent ),
  m_GlRoiActor( otb::GlROIActor::New() )
{
  assert( !m_GlRoiActor.IsNull() );
  this->SetReferenceActorShaderMode("STANDARD");
}

/*****************************************************************************/
QuicklookViewRenderer
::~QuicklookViewRenderer()
{
}

/*****************************************************************************/
AbstractImageViewRenderer::RenderingContext*
QuicklookViewRenderer
::NewRenderingContext() const
{
  RenderingContext* context = new QuicklookViewRenderer::RenderingContext();

#if USE_VIEW_SETTINGS_SIDE_EFFECT
#else
  assert( !m_GlView.IsNull() );

  //
  // Share otb::GlViewRendering settings with manipulator using
  // RenderingContext. Manipulator can then setup otb::ViewSettings
  // directly by side-effect.
  context->m_ViewSettings = m_GlView->GetSettings();
#endif

  return context;
}

/*******************************************************************************/
void
QuicklookViewRenderer
::virtual_FinishScene()
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_FinishScene()";

  otb::GlImageActor::Pointer referenceGlImageActor( GetReferenceGlImageActor() );

  if( referenceGlImageActor.IsNull() )
    return;

  std::string key( m_GlView->AddActor( m_GlRoiActor ) );

  m_GlRoiActor->SetVisible( true );

  m_GlRoiActor->SetKwl( referenceGlImageActor->GetKwl() );
  m_GlRoiActor->SetWkt( referenceGlImageActor->GetWkt() );

  /*
  ColorType color;

  color.Fill( 1.0 );

  m_GlRoiActor->SetColor( color );
  */
  m_GlRoiActor->SetFill( false );
  m_GlRoiActor->SetAlpha( 0.2 );

  m_GlView->MoveActorToEndOfRenderingOrder( key, true );
}

/*****************************************************************************/
void
QuicklookViewRenderer
::UpdateActors( const AbstractImageViewRenderer::RenderingContext* c )
{
  assert( c!=NULL );

  ImageViewRenderer::UpdateActors( c );

  assert(
    c==dynamic_cast< const QuicklookViewRenderer::RenderingContext * >( c )
  );

  const QuicklookViewRenderer::RenderingContext * context =
    dynamic_cast< const QuicklookViewRenderer::RenderingContext * >( c );

  /*
  qDebug()
    << "ROI-origin:"
    << context->m_RoiOrigin[ 0 ] << "," << context->m_RoiOrigin[ 1 ]
    << "ROI-extent:"
    << context->m_RoiExtent[ 0 ] << "," << context->m_RoiExtent[ 1 ];
  */

  m_GlRoiActor->SetUL( context->m_RoiOrigin );
  m_GlRoiActor->SetLR( context->m_RoiExtent );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/

} // end namespace 'mvd'
<|endoftext|>