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

#include <folly/io/async/Request.h>
#include <folly/tracing/StaticTracepoint.h>

#include <glog/logging.h>

#include <folly/MapUtil.h>
#include <folly/SingletonThreadLocal.h>

namespace folly {

RequestToken::RequestToken(const std::string& str) {
  auto& cache = getCache();
  {
    auto c = cache.rlock();
    auto res = c->find(str);
    if (res != c->end()) {
      token_ = res->second;
      return;
    }
  }
  auto c = cache.wlock();
  auto res = c->find(str);
  if (res != c->end()) {
    token_ = res->second;
    return;
  }
  static uint32_t nextToken{1};

  token_ = nextToken++;
  (*c)[str] = token_;
}

std::string RequestToken::getDebugString() const {
  auto& cache = getCache();
  auto c = cache.rlock();
  for (auto& v : *c) {
    if (v.second == token_) {
      return v.first;
    }
  }
  throw std::logic_error("Could not find debug string in RequestToken");
}

Synchronized<F14FastMap<std::string, uint32_t>>& RequestToken::getCache() {
  static Indestructible<Synchronized<F14FastMap<std::string, uint32_t>>> cache;
  return *cache;
}

void RequestData::DestructPtr::operator()(RequestData* ptr) {
  if (ptr) {
    auto keepAliveCounter =
        ptr->keepAliveCounter_.fetch_sub(1, std::memory_order_acq_rel);
    // Note: this is the value before decrement, hence == 1 check
    DCHECK(keepAliveCounter > 0);
    if (keepAliveCounter == 1) {
      delete ptr;
    }
  }
}

/* static */ RequestData::SharedPtr RequestData::constructPtr(
    RequestData* ptr) {
  if (ptr) {
    auto keepAliveCounter =
        ptr->keepAliveCounter_.fetch_add(1, std::memory_order_relaxed);
    DCHECK(keepAliveCounter >= 0);
  }
  return SharedPtr(ptr);
}

bool RequestContext::doSetContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData>& data,
    DoSetBehaviour behaviour) {
  auto ulock = state_.ulock();
  // Need non-const iterators to use under write lock.
  auto& state = ulock.asNonConstUnsafe();

  auto it = state.requestData_.find(val);
  bool conflict = it != state.requestData_.end();
  if (conflict) {
    if (behaviour == DoSetBehaviour::SET_IF_ABSENT) {
      return false;
    } else if (behaviour == DoSetBehaviour::SET) {
      LOG_FIRST_N(WARNING, 1)
          << "Calling RequestContext::setContextData for "
          << val.getDebugString() << " but it is already set";
    }
  }

  auto wlock = ulock.moveFromUpgradeToWrite();
  if (conflict) {
    if (it->second) {
      if (it->second->hasCallback()) {
        it->second->onUnset();
        wlock->callbackData_.erase(it->second.get());
      }
      it->second.reset(nullptr);
    }
    if (behaviour == DoSetBehaviour::SET) {
      return true;
    }
  }

  if (data && data->hasCallback()) {
    wlock->callbackData_.insert(data.get());
    data->onSet();
  }
  auto ptr = RequestData::constructPtr(data.release());
  if (conflict) {
    it->second = std::move(ptr);
  } else {
    wlock->requestData_.insert(std::make_pair(val, std::move(ptr)));
  }
  return true;
}

void RequestContext::setContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  doSetContextData(val, data, DoSetBehaviour::SET);
}

bool RequestContext::setContextDataIfAbsent(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  return doSetContextData(val, data, DoSetBehaviour::SET_IF_ABSENT);
}

void RequestContext::overwriteContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  doSetContextData(val, data, DoSetBehaviour::OVERWRITE);
}

bool RequestContext::hasContextData(const RequestToken& val) const {
  return state_.rlock()->requestData_.count(val);
}

RequestData* RequestContext::getContextData(const RequestToken& val) {
  const RequestData::SharedPtr dflt{nullptr};
  return get_ref_default(state_.rlock()->requestData_, val, dflt).get();
}

const RequestData* RequestContext::getContextData(
    const RequestToken& val) const {
  const RequestData::SharedPtr dflt{nullptr};
  return get_ref_default(state_.rlock()->requestData_, val, dflt).get();
}

void RequestContext::onSet() {
  auto rlock = state_.rlock();
  for (const auto& data : rlock->callbackData_) {
    data->onSet();
  }
}

void RequestContext::onUnset() {
  auto rlock = state_.rlock();
  for (const auto& data : rlock->callbackData_) {
    data->onUnset();
  }
}

void RequestContext::clearContextData(const RequestToken& val) {
  RequestData::SharedPtr requestData;
  // Delete the RequestData after giving up the wlock just in case one of the
  // RequestData destructors will try to grab the lock again.
  {
    auto ulock = state_.ulock();
    // Need non-const iterators to use under write lock.
    auto& state = ulock.asNonConstUnsafe();
    auto it = state.requestData_.find(val);
    if (it == state.requestData_.end()) {
      return;
    }

    auto wlock = ulock.moveFromUpgradeToWrite();
    if (it->second && it->second->hasCallback()) {
      it->second->onUnset();
      wlock->callbackData_.erase(it->second.get());
    }

    requestData = std::move(it->second);
    wlock->requestData_.erase(it);
  }
}

namespace {
// Execute functor exec for all RequestData in data, which are not in other
// Similar to std::set_difference but avoid intermediate data structure
template <typename TData, typename TExec>
void exec_set_difference(const TData& data, const TData& other, TExec&& exec) {
  auto diter = data.begin();
  auto dend = data.end();
  auto oiter = other.begin();
  auto oend = other.end();
  while (diter != dend) {
    // Order of "if" optimizes for the 2 common cases:
    // 1) empty other, switching to default context
    // 2) identical other, switching to similar context with same callbacks
    if (oiter == oend) {
      exec(*diter);
      ++diter;
    } else if (*diter == *oiter) {
      ++diter;
      ++oiter;
    } else if (*diter < *oiter) {
      exec(*diter);
      ++diter;
    } else {
      ++oiter;
    }
  }
}
} // namespace

std::shared_ptr<RequestContext> RequestContext::setContext(
    std::shared_ptr<RequestContext> const& newCtx) {
  return setContext(copy(newCtx));
}

std::shared_ptr<RequestContext> RequestContext::setContext(
    std::shared_ptr<RequestContext>&& newCtx_) {
  auto newCtx = std::move(newCtx_); // enforce that it is really moved-from

  auto& staticCtx = getStaticContext();
  if (newCtx == staticCtx) {
    return newCtx;
  }

  FOLLY_SDT(
      folly, request_context_switch_before, staticCtx.get(), newCtx.get());

  auto curCtx = staticCtx;
  if (newCtx && curCtx) {
    // Only call set/unset for all request data that differs
    auto ret = folly::acquireLocked(
        as_const(newCtx->state_), as_const(curCtx->state_));
    auto& newLock = std::get<0>(ret);
    auto& curLock = std::get<1>(ret);
    auto& newData = newLock->callbackData_;
    auto& curData = curLock->callbackData_;
    exec_set_difference(
        curData, newData, [](RequestData* data) { data->onUnset(); });
    staticCtx = newCtx;
    exec_set_difference(
        newData, curData, [](RequestData* data) { data->onSet(); });
  } else {
    if (curCtx) {
      curCtx->onUnset();
    }
    staticCtx = newCtx;
    if (newCtx) {
      newCtx->onSet();
    }
  }
  return curCtx;
}

std::shared_ptr<RequestContext>& RequestContext::getStaticContext() {
  using SingletonT = SingletonThreadLocal<std::shared_ptr<RequestContext>>;
  return SingletonT::get();
}

/* static */ std::shared_ptr<RequestContext>
RequestContext::setShallowCopyContext() {
  auto& parent = getStaticContext();
  auto child = parent ? std::make_shared<RequestContext>(*parent)
                      : std::make_shared<RequestContext>();
  // Do not use setContext to avoid global set/unset
  std::swap(child, parent);
  return child;
}

RequestContext* RequestContext::get() {
  auto& context = getStaticContext();
  if (!context) {
    static RequestContext defaultContext;
    return std::addressof(defaultContext);
  }
  return context.get();
}
} // namespace folly
<commit_msg>Simplify doSetContextData<commit_after>/*
 * Copyright 2016-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/io/async/Request.h>
#include <folly/tracing/StaticTracepoint.h>

#include <glog/logging.h>

#include <folly/MapUtil.h>
#include <folly/SingletonThreadLocal.h>

namespace folly {

RequestToken::RequestToken(const std::string& str) {
  auto& cache = getCache();
  {
    auto c = cache.rlock();
    auto res = c->find(str);
    if (res != c->end()) {
      token_ = res->second;
      return;
    }
  }
  auto c = cache.wlock();
  auto res = c->find(str);
  if (res != c->end()) {
    token_ = res->second;
    return;
  }
  static uint32_t nextToken{1};

  token_ = nextToken++;
  (*c)[str] = token_;
}

std::string RequestToken::getDebugString() const {
  auto& cache = getCache();
  auto c = cache.rlock();
  for (auto& v : *c) {
    if (v.second == token_) {
      return v.first;
    }
  }
  throw std::logic_error("Could not find debug string in RequestToken");
}

Synchronized<F14FastMap<std::string, uint32_t>>& RequestToken::getCache() {
  static Indestructible<Synchronized<F14FastMap<std::string, uint32_t>>> cache;
  return *cache;
}

void RequestData::DestructPtr::operator()(RequestData* ptr) {
  if (ptr) {
    auto keepAliveCounter =
        ptr->keepAliveCounter_.fetch_sub(1, std::memory_order_acq_rel);
    // Note: this is the value before decrement, hence == 1 check
    DCHECK(keepAliveCounter > 0);
    if (keepAliveCounter == 1) {
      delete ptr;
    }
  }
}

/* static */ RequestData::SharedPtr RequestData::constructPtr(
    RequestData* ptr) {
  if (ptr) {
    auto keepAliveCounter =
        ptr->keepAliveCounter_.fetch_add(1, std::memory_order_relaxed);
    DCHECK(keepAliveCounter >= 0);
  }
  return SharedPtr(ptr);
}

bool RequestContext::doSetContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData>& data,
    DoSetBehaviour behaviour) {
  auto wlock = state_.wlock();
  auto& state = *wlock;

  auto it = state.requestData_.find(val);
  if (it != state.requestData_.end()) {
    if (behaviour == DoSetBehaviour::SET_IF_ABSENT) {
      return false;
    }
    if (it->second) {
      if (it->second->hasCallback()) {
        it->second->onUnset();
        state.callbackData_.erase(it->second.get());
      }
      it->second.reset(nullptr);
    }
    if (behaviour == DoSetBehaviour::SET) {
      LOG_FIRST_N(WARNING, 1)
          << "Calling RequestContext::setContextData for "
          << val.getDebugString() << " but it is already set";
      return true;
    }
    DCHECK(behaviour == DoSetBehaviour::OVERWRITE);
  }

  if (data && data->hasCallback()) {
    state.callbackData_.insert(data.get());
    data->onSet();
  }
  auto ptr = RequestData::constructPtr(data.release());
  if (it != state.requestData_.end()) {
    it->second = std::move(ptr);
  } else {
    state.requestData_.insert(std::make_pair(val, std::move(ptr)));
  }
  return true;
}

void RequestContext::setContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  doSetContextData(val, data, DoSetBehaviour::SET);
}

bool RequestContext::setContextDataIfAbsent(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  return doSetContextData(val, data, DoSetBehaviour::SET_IF_ABSENT);
}

void RequestContext::overwriteContextData(
    const RequestToken& val,
    std::unique_ptr<RequestData> data) {
  doSetContextData(val, data, DoSetBehaviour::OVERWRITE);
}

bool RequestContext::hasContextData(const RequestToken& val) const {
  return state_.rlock()->requestData_.count(val);
}

RequestData* RequestContext::getContextData(const RequestToken& val) {
  const RequestData::SharedPtr dflt{nullptr};
  return get_ref_default(state_.rlock()->requestData_, val, dflt).get();
}

const RequestData* RequestContext::getContextData(
    const RequestToken& val) const {
  const RequestData::SharedPtr dflt{nullptr};
  return get_ref_default(state_.rlock()->requestData_, val, dflt).get();
}

void RequestContext::onSet() {
  auto rlock = state_.rlock();
  for (const auto& data : rlock->callbackData_) {
    data->onSet();
  }
}

void RequestContext::onUnset() {
  auto rlock = state_.rlock();
  for (const auto& data : rlock->callbackData_) {
    data->onUnset();
  }
}

void RequestContext::clearContextData(const RequestToken& val) {
  RequestData::SharedPtr requestData;
  // Delete the RequestData after giving up the wlock just in case one of the
  // RequestData destructors will try to grab the lock again.
  {
    auto ulock = state_.ulock();
    // Need non-const iterators to use under write lock.
    auto& state = ulock.asNonConstUnsafe();
    auto it = state.requestData_.find(val);
    if (it == state.requestData_.end()) {
      return;
    }

    auto wlock = ulock.moveFromUpgradeToWrite();
    if (it->second && it->second->hasCallback()) {
      it->second->onUnset();
      wlock->callbackData_.erase(it->second.get());
    }

    requestData = std::move(it->second);
    wlock->requestData_.erase(it);
  }
}

namespace {
// Execute functor exec for all RequestData in data, which are not in other
// Similar to std::set_difference but avoid intermediate data structure
template <typename TData, typename TExec>
void exec_set_difference(const TData& data, const TData& other, TExec&& exec) {
  auto diter = data.begin();
  auto dend = data.end();
  auto oiter = other.begin();
  auto oend = other.end();
  while (diter != dend) {
    // Order of "if" optimizes for the 2 common cases:
    // 1) empty other, switching to default context
    // 2) identical other, switching to similar context with same callbacks
    if (oiter == oend) {
      exec(*diter);
      ++diter;
    } else if (*diter == *oiter) {
      ++diter;
      ++oiter;
    } else if (*diter < *oiter) {
      exec(*diter);
      ++diter;
    } else {
      ++oiter;
    }
  }
}
} // namespace

std::shared_ptr<RequestContext> RequestContext::setContext(
    std::shared_ptr<RequestContext> const& newCtx) {
  return setContext(copy(newCtx));
}

std::shared_ptr<RequestContext> RequestContext::setContext(
    std::shared_ptr<RequestContext>&& newCtx_) {
  auto newCtx = std::move(newCtx_); // enforce that it is really moved-from

  auto& staticCtx = getStaticContext();
  if (newCtx == staticCtx) {
    return newCtx;
  }

  FOLLY_SDT(
      folly, request_context_switch_before, staticCtx.get(), newCtx.get());

  auto curCtx = staticCtx;
  if (newCtx && curCtx) {
    // Only call set/unset for all request data that differs
    auto ret = folly::acquireLocked(
        as_const(newCtx->state_), as_const(curCtx->state_));
    auto& newLock = std::get<0>(ret);
    auto& curLock = std::get<1>(ret);
    auto& newData = newLock->callbackData_;
    auto& curData = curLock->callbackData_;
    exec_set_difference(
        curData, newData, [](RequestData* data) { data->onUnset(); });
    staticCtx = newCtx;
    exec_set_difference(
        newData, curData, [](RequestData* data) { data->onSet(); });
  } else {
    if (curCtx) {
      curCtx->onUnset();
    }
    staticCtx = newCtx;
    if (newCtx) {
      newCtx->onSet();
    }
  }
  return curCtx;
}

std::shared_ptr<RequestContext>& RequestContext::getStaticContext() {
  using SingletonT = SingletonThreadLocal<std::shared_ptr<RequestContext>>;
  return SingletonT::get();
}

/* static */ std::shared_ptr<RequestContext>
RequestContext::setShallowCopyContext() {
  auto& parent = getStaticContext();
  auto child = parent ? std::make_shared<RequestContext>(*parent)
                      : std::make_shared<RequestContext>();
  // Do not use setContext to avoid global set/unset
  std::swap(child, parent);
  return child;
}

RequestContext* RequestContext::get() {
  auto& context = getStaticContext();
  if (!context) {
    static RequestContext defaultContext;
    return std::addressof(defaultContext);
  }
  return context.get();
}
} // namespace folly
<|endoftext|>


<commit_before>#include <cstdarg>

#ifdef SOLAR_JAVA
#include <jni.h>
#endif // SOLAR_JAVA

#ifdef SOLAR_JAVA
#include <com/sun/star/java/XJavaVM.hpp>
#include <com/sun/star/java/XJavaThreadRegister_11.hpp>
#else
#include <com/sun/star/uno/RuntimeException.hpp>
#endif // SOLAR_JAVA

#include "rtl/ref.hxx"
#include "jvmaccess/virtualmachine.hxx"

class Window;
class INetURLObject;
class SvCommandList;
class Size;
namespace com { namespace sun { namespace star { namespace uno {
    class XComponentContext;
} } } }

#ifdef SOLAR_JAVA
struct EmbeddedWindow;
#endif // SOLAR_JAVA

struct SjApplet2_Impl {
#ifdef SOLAR_JAVA
    Window              * _pParentWin;

    rtl::Reference<jvmaccess::VirtualMachine> _virtualMachine;

    jobject     _joAppletExecutionContext;
    jclass      _jcAppletExecutionContext;

    EmbeddedWindow * _pEmbeddedWindow;
#endif // SOLAR_JAVA
    SjApplet2_Impl() throw(com::sun::star::uno::RuntimeException);
    ~SjApplet2_Impl() throw();

    void init(Window * pParentWin,
              com::sun::star::uno::Reference<
                  com::sun::star::uno::XComponentContext > const & context,
              const INetURLObject & rDocBase,
              const SvCommandList & rCmdList) throw(com::sun::star::uno::RuntimeException);

    void setSize(const Size & rSize) throw(com::sun::star::uno::RuntimeException);
    void restart() throw(com::sun::star::uno::RuntimeException);
    void reload() throw(com::sun::star::uno::RuntimeException);
    void start() throw(com::sun::star::uno::RuntimeException);
    void stop() throw(com::sun::star::uno::RuntimeException);
    void close() throw(com::sun::star::uno::RuntimeException);
};
<commit_msg>INTEGRATION: CWS thbpp8 (1.6.4); FILE MERGED 2007/07/05 09:55:32 thb 1.6.4.1: #i79236# Make --without-java build work again<commit_after>#include <cstdarg>

#ifdef SOLAR_JAVA
#include <jni.h>
#endif // SOLAR_JAVA

#ifdef SOLAR_JAVA
#include <com/sun/star/java/XJavaVM.hpp>
#include <com/sun/star/java/XJavaThreadRegister_11.hpp>
#else
#include <com/sun/star/uno/RuntimeException.hpp>
#endif // SOLAR_JAVA

#include "rtl/ref.hxx"
#include "com/sun/star/uno/Reference.hxx"
#include "jvmaccess/virtualmachine.hxx"

class Window;
class INetURLObject;
class SvCommandList;
class Size;
namespace com { namespace sun { namespace star { namespace uno {
    class XComponentContext;
} } } }

#ifdef SOLAR_JAVA
struct EmbeddedWindow;
#endif // SOLAR_JAVA

struct SjApplet2_Impl {
#ifdef SOLAR_JAVA
    Window              * _pParentWin;

    rtl::Reference<jvmaccess::VirtualMachine> _virtualMachine;

    jobject     _joAppletExecutionContext;
    jclass      _jcAppletExecutionContext;

    EmbeddedWindow * _pEmbeddedWindow;
#endif // SOLAR_JAVA
    SjApplet2_Impl() throw(com::sun::star::uno::RuntimeException);
    ~SjApplet2_Impl() throw();

    void init(Window * pParentWin,
              com::sun::star::uno::Reference<
                  com::sun::star::uno::XComponentContext > const & context,
              const INetURLObject & rDocBase,
              const SvCommandList & rCmdList) throw(com::sun::star::uno::RuntimeException);

    void setSize(const Size & rSize) throw(com::sun::star::uno::RuntimeException);
    void restart() throw(com::sun::star::uno::RuntimeException);
    void reload() throw(com::sun::star::uno::RuntimeException);
    void start() throw(com::sun::star::uno::RuntimeException);
    void stop() throw(com::sun::star::uno::RuntimeException);
    void close() throw(com::sun::star::uno::RuntimeException);
};
<|endoftext|>


<commit_before><commit_msg>Linux: reference Freetype headers by name.<commit_after><|endoftext|>


<commit_before>#include <signal.h>
#ifdef PROFILER
#include <gperftools/profiler.h>
#endif
#include "sparse_matrix.h"
#include "matrix/FG_sparse_matrix.h"

using namespace fm;

void int_handler(int sig_num)
{
#ifdef PROFILER
	printf("stop profiling\n");
	if (!fg::graph_conf.get_prof_file().empty())
		ProfilerStop();
#endif
	exit(0);
}

int main(int argc, char *argv[])
{
	if (argc < 4) {
		fprintf(stderr, "test conf_file graph_file index_file\n");
		exit(1);
	}

	std::string conf_file = argv[1];
	std::string graph_file = argv[2];
	std::string index_file = argv[3];
	signal(SIGINT, int_handler);

	struct timeval start, end;
	config_map::ptr configs = config_map::create(conf_file);
	init_flash_matrix(configs);

	fg::FG_graph::ptr fg = fg::FG_graph::create(graph_file, index_file, configs);
	fg::FG_adj_matrix::ptr fg_m = fg::FG_adj_matrix::create(fg);
	fg::FG_vector<double>::ptr in = fg::FG_vector<double>::create(fg_m->get_num_cols());
	for (size_t i = 0; i < in->get_size(); i++)
		in->set(i, i);
	printf("sum of input: %lf\n", in->sum());

	fg::FG_vector<double>::ptr fg_out = fg::FG_vector<double>::create(
			fg_m->get_num_rows());
	gettimeofday(&start, NULL);
	fg_m->multiply<double>(*in, *fg_out);
	gettimeofday(&end, NULL);
	printf("sum of input: %lf, sum of FG product: %lf, it takes %.3f seconds\n",
			in->sum(), fg_out->sum(), time_diff(start, end));

	type_mem_vector<double>::ptr in_vec
		= type_mem_vector<double>::create(fg_m->get_num_cols());
	for (size_t i = 0; i < fg_m->get_num_cols(); i++)
		in_vec->set(i, i);
	sparse_matrix::ptr m = sparse_matrix::create(fg);
	gettimeofday(&start, NULL);
	type_mem_vector<double>::ptr out = m->multiply<double>(in_vec);
	double sum = 0;
	for (size_t i = 0; i < fg_m->get_num_cols(); i++)
		sum += out->get(i);
	gettimeofday(&end, NULL);
	printf("sum of input: %lf, sum of product: %lf, it takes %.3f seconds\n",
			in->sum(), sum, time_diff(start, end));
	destroy_flash_matrix();
}
<commit_msg>[Matrix]: fix a bug in measuring perf of fg_SpMV.<commit_after>#include <signal.h>
#ifdef PROFILER
#include <gperftools/profiler.h>
#endif
#include "sparse_matrix.h"
#include "matrix/FG_sparse_matrix.h"

using namespace fm;

void int_handler(int sig_num)
{
#ifdef PROFILER
	printf("stop profiling\n");
	if (!fg::graph_conf.get_prof_file().empty())
		ProfilerStop();
#endif
	exit(0);
}

int main(int argc, char *argv[])
{
	if (argc < 4) {
		fprintf(stderr, "test conf_file graph_file index_file\n");
		exit(1);
	}

	std::string conf_file = argv[1];
	std::string graph_file = argv[2];
	std::string index_file = argv[3];
	signal(SIGINT, int_handler);

	struct timeval start, end;
	config_map::ptr configs = config_map::create(conf_file);
	init_flash_matrix(configs);

	fg::FG_graph::ptr fg = fg::FG_graph::create(graph_file, index_file, configs);
	fg::FG_adj_matrix::ptr fg_m = fg::FG_adj_matrix::create(fg);
	fg::FG_vector<double>::ptr in = fg::FG_vector<double>::create(fg_m->get_num_cols());
	for (size_t i = 0; i < in->get_size(); i++)
		in->set(i, i);
	printf("sum of input: %lf\n", in->sum());

	fg::FG_vector<double>::ptr fg_out = fg::FG_vector<double>::create(
			fg_m->get_num_rows());
	gettimeofday(&start, NULL);
	fg_m->multiply<double>(*in, *fg_out);
	gettimeofday(&end, NULL);
	printf("sum of input: %lf, sum of FG product: %lf, it takes %.3f seconds\n",
			in->sum(), fg_out->sum(), time_diff(start, end));

	type_mem_vector<double>::ptr in_vec
		= type_mem_vector<double>::create(fg_m->get_num_cols());
	for (size_t i = 0; i < fg_m->get_num_cols(); i++)
		in_vec->set(i, i);
	sparse_matrix::ptr m = sparse_matrix::create(fg);
	gettimeofday(&start, NULL);
	type_mem_vector<double>::ptr out = m->multiply<double>(in_vec);
	gettimeofday(&end, NULL);
	double sum = 0;
	for (size_t i = 0; i < fg_m->get_num_cols(); i++)
		sum += out->get(i);
	printf("sum of input: %lf, sum of product: %lf, it takes %.3f seconds\n",
			in->sum(), sum, time_diff(start, end));
	destroy_flash_matrix();
}
<|endoftext|>


<commit_before>/**
* @file FastIntDistribution.hpp
* @brief The FastIntDistribution class.
* @author Dominique LaSalle <dominique@solidlake.com>
* Copyright 2019
* @version 1
* @date 2019-02-09
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef SOLIDUTILS_INCLUDE_FASTINTDISTRIBUTION_HPP
#define SOLIDUTILS_INCLUDE_FASTINTDISTRIBUTION_HPP

namespace sl
{

/**
* @brief This distribution is designed to be fast and consistent across
* platforms. However, it will not be uniform.
*
* @tparam T
*/
template<typename T>
class FastIntDistribution
{
  public:
  FastIntDistribution(
      T const min,
      T const max) :
    m_min(min),
    m_range(max-min+1)
  {
    // do nothing
  }

  template<class RNG>
  T operator()(RNG&& rng)
  {
    constexpr auto RNG_RANGE = rng.max() - rng.min() + 1;

    size_t const width = m_range / RNG_RANGE;

    uint64_t num = 0;
    for (size_t i = 0; i <= width; ++i) {
      num *= static_cast<uint64_t>(RNG_RANGE);
      num += static_cast<uint64_t>(rng() - rng.min());
    }
    num = num % m_range;

    return static_cast<T>(num) + m_min;
  }

  private:
  T m_min;
  T m_range;

};

}

#endif

<commit_msg>Add documentation<commit_after>/**
* @file FastIntDistribution.hpp
* @brief The FastIntDistribution class.
* @author Dominique LaSalle <dominique@solidlake.com>
* Copyright 2019
* @version 1
* @date 2019-02-09
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef SOLIDUTILS_INCLUDE_FASTINTDISTRIBUTION_HPP
#define SOLIDUTILS_INCLUDE_FASTINTDISTRIBUTION_HPP

namespace sl
{

/**
* @brief This distribution is designed to be fast and consistent across
* platforms. However, it will not be uniform.
*
* @tparam T
*/
template<typename T>
class FastIntDistribution
{
  public:
  /**
  * @brief Create a new FastIntDistribution which will result in numbers
  * [min,max].
  *
  * @param min The minimum number.
  * @param max The maximum number.
  */
  FastIntDistribution(
      T const min,
      T const max) :
    m_min(min),
    m_range(max-min+1)
  {
    // do nothing
  }

  /**
  * @brief Generate a number in the range of [min, max]. The distribution may
  * not be uniform, particularily for larger ranges.
  *
  * @tparam RNG The random engine type.
  * @param rng The random engine.
  *
  * @return A number in the range of [min, max].
  */
  template<class RNG>
  T operator()(RNG&& rng)
  {
    constexpr auto RNG_RANGE = rng.max() - rng.min() + 1;

    size_t const width = m_range / RNG_RANGE;

    uint64_t num = 0;
    for (size_t i = 0; i <= width; ++i) {
      num *= static_cast<uint64_t>(RNG_RANGE);
      num += static_cast<uint64_t>(rng() - rng.min());
    }
    num = num % m_range;

    return static_cast<T>(num) + m_min;
  }

  private:
  T m_min;
  T m_range;

};

}

#endif

<|endoftext|>


<commit_before>// Copyright (c) 2012, Sergey Zolotarev
// 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.
//
// 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "pluginversion.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

static std::map<AMX*, jit::Jitter*> jitters;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	#if defined __GNUC__
		if ((amx->flags & AMX_FLAG_BROWSE) == AMX_FLAG_BROWSE) {
			// amx_BrowseRelocate() wants the opcode list.
			assert(::opcode_list != 0);
			*retval = reinterpret_cast<cell>(::opcode_list);
			return AMX_ERR_NONE;
		}
	#endif
	std::map<AMX*, jit::Jitter*>::iterator iterator = jitters.find(amx);
	if (iterator != jitters.end()) {
		iterator->second->CallPublicFunction(index, retval);
		return AMX_ERR_NONE;
	} else {
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (std::map<AMX*, jit::Jitter*>::iterator it = jitters.begin(); it != jitters.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	try {
		jit::Jitter *jitter = new jit::Jitter(amx, ::opcode_list);
		jitters.insert(std::make_pair(amx, jitter));
	} catch (const jit::JitError &) {
		try {
			logprintf("[jit] An error occured, this script will run without JIT!");
			throw;
		} catch (const jit::InstructionError &e) {
			const jit::AmxInstruction &instr = e.GetInstruction();
			AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
			cell address = reinterpret_cast<cell>(instr.GetIP())
						 - reinterpret_cast<cell>(amx->base + hdr->cod);
			try {
				throw;
			} catch (const jit::InvalidInstructionError &) {
				logprintf("[jit] Error: Invalid instruction at address %08x:", address);
			} catch (const jit::UnsupportedInstructionError &) {
				logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
			} catch (const jit::ObsoleteInstructionError &) {
				logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
			}
			const cell *ip = instr.GetIP();
			logprintf("  %08x %08x %08x %08x %08x %08x ...",
					*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 5), *(ip + 5));
		} catch (const jit::BadJumpError &e) {
			logprintf("[jit]: Error: Bad jump address: %08x", e.GetDestination());
		}
	} catch (...) {
		logprintf("[jit] Error: Unknown error");
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	std::map<AMX*, jit::Jitter*>::iterator it = jitters.find(amx);
	if (it != jitters.end()) {
		delete it->second;
		jitters.erase(it);
	}
	return AMX_ERR_NONE;
}
<commit_msg>Make amx_Exec_JIT() return AMX_ERR_INVINSTR if InstructionError caught<commit_after>// Copyright (c) 2012, Sergey Zolotarev
// 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.
//
// 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "pluginversion.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

static std::map<AMX*, jit::Jitter*> jitters;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	#if defined __GNUC__
		if ((amx->flags & AMX_FLAG_BROWSE) == AMX_FLAG_BROWSE) {
			// amx_BrowseRelocate() wants the opcode list.
			assert(::opcode_list != 0);
			*retval = reinterpret_cast<cell>(::opcode_list);
			return AMX_ERR_NONE;
		}
	#endif
	std::map<AMX*, jit::Jitter*>::iterator iterator = jitters.find(amx);
	if (iterator != jitters.end()) {
		iterator->second->CallPublicFunction(index, retval);
		return AMX_ERR_NONE;
	} else {
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (std::map<AMX*, jit::Jitter*>::iterator it = jitters.begin(); it != jitters.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	try {
		jit::Jitter *jitter = new jit::Jitter(amx, ::opcode_list);
		jitters.insert(std::make_pair(amx, jitter));
	} catch (const jit::JitError &) {
		try {
			logprintf("[jit] An error occured, this script will run without JIT!");
			throw;
		} catch (const jit::InstructionError &e) {
			const jit::AmxInstruction &instr = e.GetInstruction();
			AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
			cell address = reinterpret_cast<cell>(instr.GetIP())
						 - reinterpret_cast<cell>(amx->base + hdr->cod);
			try {
				throw;
			} catch (const jit::InvalidInstructionError &) {
				logprintf("[jit] Error: Invalid instruction at address %08x:", address);
			} catch (const jit::UnsupportedInstructionError &) {
				logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
			} catch (const jit::ObsoleteInstructionError &) {
				logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
			}
			const cell *ip = instr.GetIP();
			logprintf("  %08x %08x %08x %08x %08x %08x ...",
					*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 5), *(ip + 5));
			return AMX_ERR_INVINSTR;
		} catch (const jit::BadJumpError &e) {
			logprintf("[jit]: Error: Bad jump address: %08x", e.GetDestination());
		}
	} catch (...) {
		logprintf("[jit] Error: Unknown error");
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	std::map<AMX*, jit::Jitter*>::iterator it = jitters.find(amx);
	if (it != jitters.end()) {
		delete it->second;
		jitters.erase(it);
	}
	return AMX_ERR_NONE;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012, Zeex
// 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.
//
// 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "version.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

typedef std::map<AMX*, jit::Jitter*> AmxToJitterMap;
static AmxToJitterMap amx_to_jitter;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	// A Jitter instance associated with this AMX.
	jit::Jitter *jitter = 0;

	// When amx_Exec() is called for the first time attempt to
	// JIT-compile this AMX. In case of compilation failure a null
	// pointer is put into amx_to_jit map to indicate this.
	AmxToJitterMap::iterator iterator = amx_to_jitter.find(amx);
	if (iterator == amx_to_jitter.end()) {
		jitter = new jit::Jitter(amx, ::opcode_list);
		int error = AMX_ERR_NONE;
		try {
			jitter->Compile();
		} catch (const jit::JitError &) {
			try {
				logprintf("[jit] An error occured, this script will run without JIT!");
				throw;
			} catch (const jit::CompileError &e) {
				const jit::AmxInstruction &instr = e.GetInstruction();
				AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
				cell address = reinterpret_cast<cell>(instr.GetIP())
							 - reinterpret_cast<cell>(amx->base + hdr->cod);
				try {
					throw;
				} catch (const jit::InvalidInstructionError &) {
					logprintf("[jit] Error: Invalid instruction at address %08x:", address);
				} catch (const jit::UnsupportedInstructionError &) {
					logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
				} catch (const jit::ObsoleteInstructionError &) {
					logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
				}
				const cell *ip = instr.GetIP();
				logprintf("  %08x %08x %08x %08x %08x %08x ...",
						*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 4), *(ip + 5));
				error = AMX_ERR_INVINSTR;
			}
		}
		if (error != AMX_ERR_NONE) {
			delete jitter;
			jitter = 0;
		}
		amx_to_jitter.insert(std::make_pair(amx, jitter));
	}

	if (jitter == 0) {
		// Compilation previously failed, call normal amx_Exec().
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	} else {
		return jitter->CallPublicFunction(index, retval);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (AmxToJitterMap::iterator it = amx_to_jitter.begin();
			it != amx_to_jitter.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__ && !defined WIN32
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	AmxToJitterMap::iterator it = amx_to_jitter.find(amx);
	if (it != amx_to_jitter.end()) {
		delete it->second;
		amx_to_jitter.erase(it);
	}
	return AMX_ERR_NONE;
}
<commit_msg>Fix stupid mistake in amx_Exec_JIT()<commit_after>// Copyright (c) 2012, Zeex
// 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.
//
// 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "version.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

typedef std::map<AMX*, jit::Jitter*> AmxToJitterMap;
static AmxToJitterMap amx_to_jitter;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	// A Jitter instance associated with this AMX.
	jit::Jitter *jitter = 0;

	// When amx_Exec() is called for the first time attempt to
	// JIT-compile this AMX. In case of compilation failure a null
	// pointer is put into amx_to_jit map to indicate this.
	AmxToJitterMap::iterator iterator = amx_to_jitter.find(amx);
	if (iterator == amx_to_jitter.end()) {
		jitter = new jit::Jitter(amx, ::opcode_list);
		int error = AMX_ERR_NONE;
		try {
			jitter->Compile();
		} catch (const jit::JitError &) {
			try {
				logprintf("[jit] An error occured, this script will run without JIT!");
				throw;
			} catch (const jit::CompileError &e) {
				const jit::AmxInstruction &instr = e.GetInstruction();
				AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
				cell address = reinterpret_cast<cell>(instr.GetIP())
							 - reinterpret_cast<cell>(amx->base + hdr->cod);
				try {
					throw;
				} catch (const jit::InvalidInstructionError &) {
					logprintf("[jit] Error: Invalid instruction at address %08x:", address);
				} catch (const jit::UnsupportedInstructionError &) {
					logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
				} catch (const jit::ObsoleteInstructionError &) {
					logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
				}
				const cell *ip = instr.GetIP();
				logprintf("  %08x %08x %08x %08x %08x %08x ...",
						*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 4), *(ip + 5));
				error = AMX_ERR_INVINSTR;
			}
		}
		if (error != AMX_ERR_NONE) {
			delete jitter;
			jitter = 0;
		}
		amx_to_jitter.insert(std::make_pair(amx, jitter));
	} else {
		jitter = iterator->second;
	}

	if (jitter == 0) {
		// Compilation previously failed, call normal amx_Exec().
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	} else {
		return jitter->CallPublicFunction(index, retval);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (AmxToJitterMap::iterator it = amx_to_jitter.begin();
			it != amx_to_jitter.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__ && !defined WIN32
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	AmxToJitterMap::iterator it = amx_to_jitter.find(amx);
	if (it != amx_to_jitter.end()) {
		delete it->second;
		amx_to_jitter.erase(it);
	}
	return AMX_ERR_NONE;
}
<|endoftext|>


<commit_before>#include <cassert>
#include <iostream>
#include "xcam.h"

using std::cout;
using std::endl;

using xcam::opcodes::soft::soft_cam_t;
using xcam::xcam_index_t;
using xcam::xcam_subkey_t;
using xcam::xcam_key_t;
using xcam::xcam_value_t;
using xcam::xcam_entry_t;

soft_cam_t::cpu_map_t soft_cam_t::cpu_map;

soft_cam_t* soft_cam_t::instance(int cpu_id) {
    if (cpu_map.find(cpu_id) == cpu_map.end()) {
        cpu_map[cpu_id] = new soft_cam_t();
    }
    return cpu_map[cpu_id];
}

xcam_subkey_t soft_cam_t::camlk0(const xcam_index_t ix, const int offset) const {
    const xcam_subkey_t result = cam_state.at(ix + offset).key.k0;
    cout << "cam[" << (ix + offset) << "].k0 => " << result << endl;
    return result;
}

xcam_subkey_t soft_cam_t::camlk1(const xcam_index_t ix, const int offset) const {
    const xcam_subkey_t result = cam_state.at(ix + offset).key.k1;
    cout << "cam[" << (ix + offset) << "].k1 => " << result << endl;
    return result;
}

xcam_value_t soft_cam_t::camlv(const xcam_index_t ix, const int offset) const {
    const xcam_value_t result = cam_state.at(ix + offset).value;
    cout << "cam[" << (ix + offset) << "].v => " << result << endl;
    return result;
}

void soft_cam_t::camsk0(const xcam_index_t ix, const int offset, const xcam_subkey_t k0) {
    const state_ix_t ixo = ix + offset;
    remove_row(ixo);
    cam_state.at(ixo).key.k0 = k0;
    add_row(ixo);
    cout << "cam[" << ixo << "].k0 <= " << k0 << endl;
}

void soft_cam_t::camsk1(const xcam_index_t ix, const int offset, const xcam_subkey_t k1) {
    const state_ix_t ixo = ix + offset;
    remove_row(ixo);
    cam_state.at(ixo).key.k1 = k1;
    add_row(ixo);
    cout << "cam[" << ixo << "].k1 <= " << k1 << endl;
}

void soft_cam_t::camsv(const xcam_index_t ix, const int offset, const xcam_value_t v) {
    const state_ix_t ixo = ix + offset;
    remove_row(ixo);
    cam_state.at(ixo).value = v;
    add_row(ixo);
    cout << "cam[" << ixo << "].v <= " << v << endl;
}

void soft_cam_t::remove_row(const state_ix_t ix) {
    const value_type row = cam_state.at(ix);
    if (row.value != 0) {
        // CAM row does not contain a zero value, so the multimap should have an entry pointing to this row.
        cout << "cam[" << ix << "] invalidating (" << row.key.k0 << ", " << row.key.k1 << ") -> " << row.value << endl;

        std::pair<map_t::iterator, map_t::iterator> range = cam_map.equal_range(row.key);
        while (range.first != range.second) {
            if ((range.first)->second == ix) {
                // Found the correct multimap entry.
                cam_map.erase(range.first);
                return;
            }
            ++range.first;
        }

        // Failed to find the expected entry.
        assert(false);
    }
}

void soft_cam_t::add_row(const state_ix_t ix) {
    const value_type row = cam_state.at(ix);
    if (row.value != 0) {
      // CAM row does not contain a zero value. Create an entry in the multimap pointing to this row.
      cam_map.insert(map_t::value_type(row.key, ix));
      cout << "cam[" << ix << "] validating (" << row.key.k0 << ", " << row.key.k1 << ") -> " << row.value << endl;
    }
}

xcam_value_t soft_cam_t::cam(const xcam_subkey_t k0, const xcam_subkey_t k1, const int insignificantBits) const {
    const xcam_subkey_t mask = -1 << insignificantBits;
    const xcam_subkey_t k1_lowerbound = k1 & mask;
    const xcam_subkey_t k1_upperbound = k1 | ~mask;

    const key_type key_lowerbound(k0, k1_lowerbound);
    const key_type key_upperbound(k0, k1_upperbound);

    // Find a range of entries in the map that could potentially match (k0, k1) considering insignificantBits.
    map_t::const_iterator lb = cam_map.lower_bound(key_lowerbound);
    const map_t::const_iterator ub = cam_map.upper_bound(key_upperbound);

    bool found_match = false;
    state_ix_t match_ix = 0;

    // Iterate over the potentially matching rows and take the actual matching row with the lowest ix.
    while (lb != ub) {
        const xcam_subkey_t row_k0 = lb->first.k0;
        const xcam_subkey_t row_k1 = lb->first.k1;
        const xcam_subkey_t row_k1_lowerbound = row_k1 & mask;
        if (row_k0 == k0 && row_k1_lowerbound == k1_lowerbound) {
            // Found a matching row.
            if (!found_match) {
                found_match = true;
                match_ix = lb->second;
                cout << "cam(" << k0 << ", " << k1 << " & 0x" << std::hex << mask << ").v => " << endl;
            } else {
                match_ix = std::min(match_ix, lb->second);
            }
            cout << "    matches ix=" << lb->second << " (" << row_k0 << ", " << row_k1 << ") -> " << cam_state.at(lb->second).value << endl;
        }
        ++lb;
    }

    if (found_match) {
        // Overwrite the insignificantBits of the result with the least-significant-bits of k1.
        const xcam_value_t result = cam_state.at(match_ix).value;
        const xcam_subkey_t k1_suffix = k1 & ~mask;
        const xcam_value_t result_with_suffix = (result & mask) | k1_suffix;

        cout << "    minimum ix=" << match_ix << " (" << result << " & 0x" << std::hex << mask << ") | 0x " << std::hex << k1_suffix << " = " << result_with_suffix << endl;
        return result_with_suffix;
    }
    else {
        // Key is not in the cam. Return zero.
        cout << "cam(" << k0 << ", " << k1 << " & 0x" << std::hex << mask << ").v => null" << endl;
        return 0;
    }
}
<commit_msg>Improved the debug messages<commit_after>#include <cassert>
#include <iostream>
#include "xcam.h"

using std::cout;
using std::endl;

using xcam::opcodes::soft::soft_cam_t;
using xcam::xcam_index_t;
using xcam::xcam_subkey_t;
using xcam::xcam_key_t;
using xcam::xcam_value_t;
using xcam::xcam_entry_t;

soft_cam_t::cpu_map_t soft_cam_t::cpu_map;

soft_cam_t* soft_cam_t::instance(int cpu_id) {
    if (cpu_map.find(cpu_id) == cpu_map.end()) {
        cpu_map[cpu_id] = new soft_cam_t();
    }
    return cpu_map[cpu_id];
}

xcam_subkey_t soft_cam_t::camlk0(const xcam_index_t ix, const int offset) const {
    const xcam_subkey_t result = cam_state.at(ix + offset).key.k0;
    cout << "cam[" << (ix + offset) << "].k0 => " << result << endl;
    return result;
}

xcam_subkey_t soft_cam_t::camlk1(const xcam_index_t ix, const int offset) const {
    const xcam_subkey_t result = cam_state.at(ix + offset).key.k1;
    cout << "cam[" << (ix + offset) << "].k1 => " << result << endl;
    return result;
}

xcam_value_t soft_cam_t::camlv(const xcam_index_t ix, const int offset) const {
    const xcam_value_t result = cam_state.at(ix + offset).value;
    cout << "cam[" << (ix + offset) << "].v => " << result << endl;
    return result;
}

void soft_cam_t::camsk0(const xcam_index_t ix, const int offset, const xcam_subkey_t k0) {
    const state_ix_t ixo = ix + offset;
    cout << "cam[" << ixo << "].k0 <= " << k0 << endl;
    if (cam_state.at(ixo).key.k0 != k0) {
        remove_row(ixo);
        cam_state.at(ixo).key.k0 = k0;
        add_row(ixo);
    }
}

void soft_cam_t::camsk1(const xcam_index_t ix, const int offset, const xcam_subkey_t k1) {
    const state_ix_t ixo = ix + offset;
    cout << "cam[" << ixo << "].k1 <= " << k1 << endl;
    if (cam_state.at(ixo).key.k1 != k1) {
        remove_row(ixo);
        cam_state.at(ixo).key.k1 = k1;
        add_row(ixo);
    }
}

void soft_cam_t::camsv(const xcam_index_t ix, const int offset, const xcam_value_t v) {
    const state_ix_t ixo = ix + offset;
    cout << "cam[" << ixo << "].v <= " << v << endl;
    if (cam_state.at(ixo).value != v) {
        remove_row(ixo);
        cam_state.at(ixo).value = v;
        add_row(ixo);
    }
}

void soft_cam_t::remove_row(const state_ix_t ix) {
    const value_type row = cam_state.at(ix);
    if (row.value != 0) {
        // CAM row does not contain a zero value, so the multimap should have an entry pointing to this row.
        cout << "cam[" << ix << "] invalidating (" << row.key.k0 << ", " << row.key.k1 << ") -> " << row.value << endl;

        std::pair<map_t::iterator, map_t::iterator> range = cam_map.equal_range(row.key);
        while (range.first != range.second) {
            if ((range.first)->second == ix) {
                // Found the correct multimap entry.
                cam_map.erase(range.first);
                return;
            }
            ++range.first;
        }

        // Failed to find the expected entry.
        assert(false);
    }
}

void soft_cam_t::add_row(const state_ix_t ix) {
    const value_type row = cam_state.at(ix);
    if (row.value != 0) {
      // CAM row does not contain a zero value. Create an entry in the multimap pointing to this row.
      cam_map.insert(map_t::value_type(row.key, ix));
      cout << "cam[" << ix << "] validating (" << row.key.k0 << ", " << row.key.k1 << ") -> " << row.value << endl;
    }
}

xcam_value_t soft_cam_t::cam(const xcam_subkey_t k0, const xcam_subkey_t k1, const int insignificantBits) const {
    const xcam_subkey_t mask = -1 << insignificantBits;
    const xcam_subkey_t k1_lowerbound = k1 & mask;
    const xcam_subkey_t k1_upperbound = k1 | ~mask;

    const key_type key_lowerbound(k0, k1_lowerbound);
    const key_type key_upperbound(k0, k1_upperbound);

    // Find a range of entries in the map that could potentially match (k0, k1) considering insignificantBits.
    map_t::const_iterator lb = cam_map.lower_bound(key_lowerbound);
    const map_t::const_iterator ub = cam_map.upper_bound(key_upperbound);

    bool found_match = false;
    state_ix_t match_ix = 0;

    // Iterate over the potentially matching rows and take the actual matching row with the lowest ix.
    while (lb != ub) {
        const xcam_subkey_t row_k0 = lb->first.k0;
        const xcam_subkey_t row_k1 = lb->first.k1;
        const xcam_subkey_t row_k1_lowerbound = row_k1 & mask;
        if (row_k0 == k0 && row_k1_lowerbound == k1_lowerbound) {
            // Found a matching row.
            if (!found_match) {
                found_match = true;
                match_ix = lb->second;
                cout << "cam(" << k0 << ", " << k1 << " & 0x" << std::hex << mask << ").v => " << endl;
            } else {
                match_ix = std::min(match_ix, lb->second);
            }
            cout << "    matches ix=" << lb->second << " (" << row_k0 << ", " << row_k1 << ") -> " << cam_state.at(lb->second).value << endl;
        }
        ++lb;
    }

    if (found_match) {
        // Overwrite the insignificantBits of the result with the least-significant-bits of k1.
        const xcam_value_t result = cam_state.at(match_ix).value;
        const xcam_subkey_t k1_suffix = k1 & ~mask;
        const xcam_value_t result_with_suffix = (result & mask) | k1_suffix;

        cout << "    minimum ix=" << match_ix << " (" << result << " & 0x" << std::hex << mask << ") | 0x" << std::hex << k1_suffix << " = " << result_with_suffix << endl;
        return result_with_suffix;
    }
    else {
        // Key is not in the cam. Return zero.
        cout << "cam(" << k0 << ", " << k1 << " & 0x" << std::hex << mask << ").v => null" << endl;
        return 0;
    }
}
<|endoftext|>


<commit_before>#include "cpardiso.hpp"
#include "hypre.hpp"
#include <algorithm>
#include <vector>
#include <numeric>

namespace mfem
{
CPardisoSolver::CPardisoSolver(MPI_Comm comm) : comm_(comm)
{
   // Solver default parameters overriden with provided by iparm
   iparm[0] = 1;
   // Use METIS for fill-in reordering
   iparm[1] = 2;
   // Write solution into x
   iparm[5] = 0;
   // Max number of iterative refinement steps
   iparm[7] = 2;
   // Perturb the pivot elements with 1E-13
   iparm[9] = 13;
   // Use nonsymmetric permutation and scaling MPS
   iparm[10] = 1;
   // Switch on Maximum Weighted Matching algorithm (default for non-symmetric)
   iparm[12] = 1;
   // Output: Number of nonzeros in the factor LU
   iparm[17] = -1;
   // Output: Mflops for LU factorization
   iparm[18] = -1;
   // Check input data for correctness
   iparm[26] = 1;
   // 0-based indexing
   iparm[34] = 1;
   // All inputs are distributed between MPI processes
   iparm[39] = 2;
   // Maximum number of numerical factorizations
   maxfct = 1;
   // Which factorization to use
   mnum = 1;
   // Print statistical information in file
   msglvl = 0;
   // Initialize error flag
   error = 0;
   // Real unsymmetric matrix
   mtype = MatType::REAL_UNSYMMETRIC;
   // Number of right hand sides
   nrhs = 1;
};

void CPardisoSolver::SetOperator(const Operator &op)
{
   auto hypreParMat = dynamic_cast<const HypreParMatrix &>(op);

   MFEM_ASSERT(hypreParMat, "Must pass HypreParMatrix as Operator");

   auto parcsr_op = static_cast<hypre_ParCSRMatrix *>(
                       const_cast<HypreParMatrix &>(hypreParMat));

   hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
   hypre_CSRMatrixSetDataOwner(csr_op, 0);

#if MFEM_HYPRE_VERSION >= 21600
   hypre_CSRMatrixBigJtoJ(csr_op);
#endif

   m = parcsr_op->global_num_rows;
   first_row = parcsr_op->first_row_index;
   nnz_loc = csr_op->num_nonzeros;
   m_loc = csr_op->num_rows;

   height = m_loc;
   width = m_loc;

   double *csr_nzval = csr_op->data;
   int *csr_colind = csr_op->j;

   delete[] csr_rowptr;
   delete[] reordered_csr_colind;
   delete[] reordered_csr_nzval;
   csr_rowptr = new int[m_loc + 1];
   reordered_csr_colind = new int[nnz_loc];
   reordered_csr_nzval = new double[nnz_loc];

   for (int i = 0; i <= m_loc; i++)
   {
      csr_rowptr[i] = (csr_op->i)[i];
   }

   // CPardiso expects the column indices to be sorted for each row
   std::vector<int> permutation_idx(nnz_loc);
   std::iota(permutation_idx.begin(), permutation_idx.end(), 0);
   for (int i = 0; i < m_loc; i++)
   {
      std::sort(permutation_idx.begin() + csr_rowptr[i],
                permutation_idx.begin() + csr_rowptr[i + 1],
                [csr_colind](int i1, int i2)
      {
         return csr_colind[i1] < csr_colind[i2];
      });
   }

   for (int i = 0; i < nnz_loc; i++)
   {
      reordered_csr_colind[i] = csr_colind[permutation_idx[i]];
      reordered_csr_nzval[i] = csr_nzval[permutation_idx[i]];
   }

   hypre_CSRMatrixDestroy(csr_op);

   // The number of row in global matrix, rhs element and solution vector that
   // begins the input domain belonging to this MPI process
   iparm[40] = first_row;

   // The number of row in global matrix, rhs element and solution vector that
   // ends the input domain belonging to this MPI process
   iparm[41] = first_row + m_loc - 1;

   // Analyze inputs
   phase = 11;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso analyze input error");

   // Numerical factorization
   phase = 22;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso factorization input error");
}

void CPardisoSolver::Mult(const Vector &b, Vector &x) const
{
   // Solve
   phase = 33;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         b.GetData(),
                         x.GetData(),
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso solve error");
}

void CPardisoSolver::SetPrintLevel(int print_level)
{
   msglvl = print_level;
}

void CPardisoSolver::SetMatrixType(MatType mat_type)
{
   mtype = mat_type;
}

CPardisoSolver::~CPardisoSolver()
{
   // Release all internal memory
   phase = -1;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso free error");

   delete[] csr_rowptr;
   delete[] reordered_csr_colind;
   delete[] reordered_csr_nzval;
}

} // namespace mfem<commit_msg>change matrix data ownership<commit_after>#include "cpardiso.hpp"
#include "hypre.hpp"
#include <algorithm>
#include <vector>
#include <numeric>

namespace mfem
{
CPardisoSolver::CPardisoSolver(MPI_Comm comm) : comm_(comm)
{
   // Solver default parameters overriden with provided by iparm
   iparm[0] = 1;
   // Use METIS for fill-in reordering
   iparm[1] = 2;
   // Write solution into x
   iparm[5] = 0;
   // Max number of iterative refinement steps
   iparm[7] = 2;
   // Perturb the pivot elements with 1E-13
   iparm[9] = 13;
   // Use nonsymmetric permutation and scaling MPS
   iparm[10] = 1;
   // Switch on Maximum Weighted Matching algorithm (default for non-symmetric)
   iparm[12] = 1;
   // Output: Number of nonzeros in the factor LU
   iparm[17] = -1;
   // Output: Mflops for LU factorization
   iparm[18] = -1;
   // Check input data for correctness
   iparm[26] = 1;
   // 0-based indexing
   iparm[34] = 1;
   // All inputs are distributed between MPI processes
   iparm[39] = 2;
   // Maximum number of numerical factorizations
   maxfct = 1;
   // Which factorization to use
   mnum = 1;
   // Print statistical information in file
   msglvl = 0;
   // Initialize error flag
   error = 0;
   // Real unsymmetric matrix
   mtype = MatType::REAL_UNSYMMETRIC;
   // Number of right hand sides
   nrhs = 1;
};

void CPardisoSolver::SetOperator(const Operator &op)
{
   auto hypreParMat = dynamic_cast<const HypreParMatrix &>(op);

   MFEM_ASSERT(hypreParMat, "Must pass HypreParMatrix as Operator");

   auto parcsr_op = static_cast<hypre_ParCSRMatrix *>(
                       const_cast<HypreParMatrix &>(hypreParMat));

   hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
#if MFEM_HYPRE_VERSION >= 21600
   hypre_CSRMatrixBigJtoJ(csr_op);
#endif

   m = parcsr_op->global_num_rows;
   first_row = parcsr_op->first_row_index;
   nnz_loc = csr_op->num_nonzeros;
   m_loc = csr_op->num_rows;

   height = m_loc;
   width = m_loc;

   double *csr_nzval = csr_op->data;
   int *csr_colind = csr_op->j;

   delete[] csr_rowptr;
   delete[] reordered_csr_colind;
   delete[] reordered_csr_nzval;
   csr_rowptr = new int[m_loc + 1];
   reordered_csr_colind = new int[nnz_loc];
   reordered_csr_nzval = new double[nnz_loc];

   for (int i = 0; i <= m_loc; i++)
   {
      csr_rowptr[i] = (csr_op->i)[i];
   }

   // CPardiso expects the column indices to be sorted for each row
   std::vector<int> permutation_idx(nnz_loc);
   std::iota(permutation_idx.begin(), permutation_idx.end(), 0);
   for (int i = 0; i < m_loc; i++)
   {
      std::sort(permutation_idx.begin() + csr_rowptr[i],
                permutation_idx.begin() + csr_rowptr[i + 1],
                [csr_colind](int i1, int i2)
      {
         return csr_colind[i1] < csr_colind[i2];
      });
   }

   for (int i = 0; i < nnz_loc; i++)
   {
      reordered_csr_colind[i] = csr_colind[permutation_idx[i]];
      reordered_csr_nzval[i] = csr_nzval[permutation_idx[i]];
   }

   hypre_CSRMatrixDestroy(csr_op);

   // The number of row in global matrix, rhs element and solution vector that
   // begins the input domain belonging to this MPI process
   iparm[40] = first_row;

   // The number of row in global matrix, rhs element and solution vector that
   // ends the input domain belonging to this MPI process
   iparm[41] = first_row + m_loc - 1;

   // Analyze inputs
   phase = 11;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso analyze input error");

   // Numerical factorization
   phase = 22;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso factorization input error");
}

void CPardisoSolver::Mult(const Vector &b, Vector &x) const
{
   // Solve
   phase = 33;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         b.GetData(),
                         x.GetData(),
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso solve error");
}

void CPardisoSolver::SetPrintLevel(int print_level)
{
   msglvl = print_level;
}

void CPardisoSolver::SetMatrixType(MatType mat_type)
{
   mtype = mat_type;
}

CPardisoSolver::~CPardisoSolver()
{
   // Release all internal memory
   phase = -1;
   cluster_sparse_solver(pt,
                         &maxfct,
                         &mnum,
                         &mtype,
                         &phase,
                         &m,
                         reordered_csr_nzval,
                         csr_rowptr,
                         reordered_csr_colind,
                         &idum,
                         &nrhs,
                         iparm,
                         &msglvl,
                         &ddum,
                         &ddum,
                         &comm_,
                         &error);

   MFEM_ASSERT(error == 0, "Pardiso free error");

   delete[] csr_rowptr;
   delete[] reordered_csr_colind;
   delete[] reordered_csr_nzval;
}

} // namespace mfem<|endoftext|>


<commit_before>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "unittest/server_test_helper.hpp"

#include "errors.hpp"
#include <boost/bind.hpp>

#include "arch/io/disk.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "arch/timing.hpp"
#include "btree/slice.hpp"
#include "buffer_cache/buffer_cache.hpp"
#include "unittest/unittest_utils.hpp"
#include "serializer/config.hpp"
#include "serializer/log/log_serializer.hpp"
#include "serializer/translator.hpp"

namespace unittest {

const uint32_t server_test_helper_t::init_value = 0x12345678;
const uint32_t server_test_helper_t::changed_value = 0x87654321;

server_test_helper_t::server_test_helper_t()
    : serializer(NULL), thread_pool(new thread_pool_t(1, false)) { }

// Destructor defined in the .cc so that thread_pool_t isn't an incomplete type.
server_test_helper_t::~server_test_helper_t() { }

void server_test_helper_t::run() {
    unittest::run_in_thread_pool(boost::bind(&server_test_helper_t::setup_server_and_run_tests, this));
}

void server_test_helper_t::setup_server_and_run_tests() {
    temp_file_t db_file;

    scoped_ptr_t<io_backender_t> io_backender;
    make_io_backender(aio_default, &io_backender);

    {
        filepath_file_opener_t file_opener(db_file.name(), io_backender.get());
        standard_serializer_t::create(
            &file_opener,
            standard_serializer_t::static_config_t());
        standard_serializer_t log_serializer(
            standard_serializer_t::dynamic_config_t(),
            &file_opener,
            &get_global_perfmon_collection());

        std::vector<standard_serializer_t *> serializers;
        serializers.push_back(&log_serializer);
        serializer_multiplexer_t::create(serializers, 1);
        serializer_multiplexer_t multiplexer(serializers);

        this->serializer = multiplexer.proxies[0];

        run_serializer_tests();
    }

    trace_call(thread_pool->shutdown_thread_pool);
}

void server_test_helper_t::run_serializer_tests() {
    cache_t::create(this->serializer);
    mirrored_cache_config_t cache_cfg;
    cache_cfg.flush_timer_ms = MILLION;
    cache_cfg.flush_dirty_size = BILLION;
    cache_cfg.max_size = GIGABYTE;
    cache_t cache(this->serializer, cache_cfg, &get_global_perfmon_collection());

    run_tests(&cache);
}

void server_test_helper_t::snap(transaction_t *txn) {
    txn->snapshot();
}

void server_test_helper_t::change_value(buf_lock_t *buf, uint32_t value) {
    *static_cast<uint32_t *>(buf->get_data_write()) = value;
}

uint32_t server_test_helper_t::get_value(buf_lock_t *buf) {
    return *static_cast<const uint32_t *>(buf->get_data_read());
}

bool server_test_helper_t::acq_check_if_blocks_until_buf_released(buf_lock_t *newly_acquired_block, transaction_t *txn, buf_lock_t *already_acquired_block, access_t acquire_mode, bool do_release) {
    acquiring_coro_t acq_coro(newly_acquired_block, txn, already_acquired_block->get_block_id(), acquire_mode);

    coro_t::spawn(boost::bind(&acquiring_coro_t::run, &acq_coro));
    nap(500);
    bool result = !acq_coro.signaled;

    if (do_release) {
        already_acquired_block->release();
        if (result) {
            nap(500);
            rassert(acq_coro.signaled, "Waiting acquire did not complete following release. May be a bug in the test.");
        }
    }

    rassert(newly_acquired_block->is_acquired());

    return result;
}

void server_test_helper_t::create_two_blocks(transaction_t *txn, block_id_t *block_A, block_id_t *block_B) {
    buf_lock_t buf_A(txn);
    buf_lock_t buf_B(txn);
    *block_A = buf_A.get_block_id();
    *block_B = buf_B.get_block_id();
    change_value(&buf_A, init_value);
    change_value(&buf_B, init_value);
}

void server_test_helper_t::acquiring_coro_t::run() {
    buf_lock_t tmp(txn, block_id, mode);
    result->swap(tmp);
    signaled = true;
}

}  // namespace unittest
<commit_msg>Made server_test_helper_t use a mock_file_opener_t instead of a filepath_file_opener_t.<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "unittest/server_test_helper.hpp"

#include "errors.hpp"
#include <boost/bind.hpp>

#include "arch/io/disk.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "arch/timing.hpp"
#include "btree/slice.hpp"
#include "buffer_cache/buffer_cache.hpp"
#include "unittest/mock_file.hpp"
#include "unittest/unittest_utils.hpp"
#include "serializer/config.hpp"
#include "serializer/log/log_serializer.hpp"
#include "serializer/translator.hpp"

namespace unittest {

const uint32_t server_test_helper_t::init_value = 0x12345678;
const uint32_t server_test_helper_t::changed_value = 0x87654321;

server_test_helper_t::server_test_helper_t()
    : serializer(NULL), thread_pool(new thread_pool_t(1, false)) { }

// Destructor defined in the .cc so that thread_pool_t isn't an incomplete type.
server_test_helper_t::~server_test_helper_t() { }

void server_test_helper_t::run() {
    unittest::run_in_thread_pool(boost::bind(&server_test_helper_t::setup_server_and_run_tests, this));
}

void server_test_helper_t::setup_server_and_run_tests() {
    {
        mock_file_opener_t file_opener;
        standard_serializer_t::create(
            &file_opener,
            standard_serializer_t::static_config_t());
        standard_serializer_t log_serializer(
            standard_serializer_t::dynamic_config_t(),
            &file_opener,
            &get_global_perfmon_collection());

        std::vector<standard_serializer_t *> serializers;
        serializers.push_back(&log_serializer);
        serializer_multiplexer_t::create(serializers, 1);
        serializer_multiplexer_t multiplexer(serializers);

        this->serializer = multiplexer.proxies[0];

        run_serializer_tests();
    }

    trace_call(thread_pool->shutdown_thread_pool);
}

void server_test_helper_t::run_serializer_tests() {
    cache_t::create(this->serializer);
    mirrored_cache_config_t cache_cfg;
    cache_cfg.flush_timer_ms = MILLION;
    cache_cfg.flush_dirty_size = BILLION;
    cache_cfg.max_size = GIGABYTE;
    cache_t cache(this->serializer, cache_cfg, &get_global_perfmon_collection());

    run_tests(&cache);
}

void server_test_helper_t::snap(transaction_t *txn) {
    txn->snapshot();
}

void server_test_helper_t::change_value(buf_lock_t *buf, uint32_t value) {
    *static_cast<uint32_t *>(buf->get_data_write()) = value;
}

uint32_t server_test_helper_t::get_value(buf_lock_t *buf) {
    return *static_cast<const uint32_t *>(buf->get_data_read());
}

bool server_test_helper_t::acq_check_if_blocks_until_buf_released(buf_lock_t *newly_acquired_block, transaction_t *txn, buf_lock_t *already_acquired_block, access_t acquire_mode, bool do_release) {
    acquiring_coro_t acq_coro(newly_acquired_block, txn, already_acquired_block->get_block_id(), acquire_mode);

    coro_t::spawn(boost::bind(&acquiring_coro_t::run, &acq_coro));
    nap(500);
    bool result = !acq_coro.signaled;

    if (do_release) {
        already_acquired_block->release();
        if (result) {
            nap(500);
            rassert(acq_coro.signaled, "Waiting acquire did not complete following release. May be a bug in the test.");
        }
    }

    rassert(newly_acquired_block->is_acquired());

    return result;
}

void server_test_helper_t::create_two_blocks(transaction_t *txn, block_id_t *block_A, block_id_t *block_B) {
    buf_lock_t buf_A(txn);
    buf_lock_t buf_B(txn);
    *block_A = buf_A.get_block_id();
    *block_B = buf_B.get_block_id();
    change_value(&buf_A, init_value);
    change_value(&buf_B, init_value);
}

void server_test_helper_t::acquiring_coro_t::run() {
    buf_lock_t tmp(txn, block_id, mode);
    result->swap(tmp);
    signaled = true;
}

}  // namespace unittest
<|endoftext|>


<commit_before>#include <MMM/Motion/Motion.h>
#include <MMM/Motion/MotionFrame.h>
#include <MMM/Motion/MotionReaderXML.h>

#include "utils/mmm/TrajectoryPlayer.h"
#include "utils/mmm/ControlPoint.h"
#include "utils/mmm/ControlValue.h"
#include "utils/mmm/ControlMatrix.h"

bool TrajectoryPlayer::update(float dt)
{
    if (isRunning && frameCounter <= motion->getMotionFrames().size())
    {
        time += dt;

        float remaining = nextFrame->timestep - time;

        if (remaining < 0)
        {
            if (frameCounter < motion->getMotionFrames().size())
            {
                currentFrame = nextFrame;
                nextFrame = motion->getMotionFrame(frameCounter);
                frameCounter++;
            }
            else
            {
                isRunning = false;
            }
        }
    }

    return isRunning;
}

void TrajectoryPlayer::reset()
{
    isRunning = false;
    nextFrame = motion->getMotionFrame(0);
    frameCounter = 1;
    time = 0;
}

bool TrajectoryPlayer::loadMotion(const std::string& motionPath, const std::string& goalMotionName)
{
    MMM::MotionReaderXMLPtr reader(new MMM::MotionReaderXML());
    std::vector<std::string> motionNames = reader->getMotionNames(motionPath);

    std::string motionName = goalMotionName;
    if (goalMotionName == "")
    {
        motionName = motionNames[0];
    }
    else
    {
        auto iter = std::find(motionNames.begin(), motionNames.end(), motionName);
        if (iter == motionNames.end())
        {
            std::cout << "Error: Motion " << motionName << " not found. Using first motion instead!" << std::endl;
            return false;
        }
    }

    boost::shared_ptr<ControlPointParser3f> comParser (new ControlPointParser3f("CoM"));
    boost::shared_ptr<ControlPointParser2f> zmpParser (new ControlPointParser2f("ZMP"));
    boost::shared_ptr<ControlMatrixParser4f> leftFootParser (new ControlMatrixParser4f("LeftFoot"));
    boost::shared_ptr<ControlMatrixParser4f> rightFootParser (new ControlMatrixParser4f("RightFoot"));
    boost::shared_ptr<ControlMatrixParser4f> chestParser (new ControlMatrixParser4f("Chest"));
    boost::shared_ptr<ControlMatrixParser4f> pelvisParser (new ControlMatrixParser4f("Pelvis"));
    boost::shared_ptr<ControlValueParser<int>> phaseParser (new ControlValueParser<int>("SupportPhase"));

    reader->registerMotionFrameXMLTag("CoM", comParser);
    reader->registerMotionFrameXMLTag("ZMP", zmpParser);
    reader->registerMotionFrameXMLTag("LeftFoot", leftFootParser);
    reader->registerMotionFrameXMLTag("RightFoot", rightFootParser);
    reader->registerMotionFrameXMLTag("Chest", chestParser);
    reader->registerMotionFrameXMLTag("Pelvis", pelvisParser);
    reader->registerMotionFrameXMLTag("SupportPhase", phaseParser);

    motion = reader->loadMotion(motionPath, motionName);
    if (motion->getMotionFrames().size() < 2)
    {
        std::cout << "Error: Motion needs at least 2 frames!" << std::endl;
        return false;
    }
    reset();
}

<commit_msg>Fixed missing return statement<commit_after>#include <MMM/Motion/Motion.h>
#include <MMM/Motion/MotionFrame.h>
#include <MMM/Motion/MotionReaderXML.h>

#include "utils/mmm/TrajectoryPlayer.h"
#include "utils/mmm/ControlPoint.h"
#include "utils/mmm/ControlValue.h"
#include "utils/mmm/ControlMatrix.h"

bool TrajectoryPlayer::update(float dt)
{
    if (isRunning && frameCounter <= motion->getMotionFrames().size())
    {
        time += dt;

        float remaining = nextFrame->timestep - time;

        if (remaining < 0)
        {
            if (frameCounter < motion->getMotionFrames().size())
            {
                currentFrame = nextFrame;
                nextFrame = motion->getMotionFrame(frameCounter);
                frameCounter++;
            }
            else
            {
                isRunning = false;
            }
        }
    }

    return isRunning;
}

void TrajectoryPlayer::reset()
{
    isRunning = false;
    nextFrame = motion->getMotionFrame(0);
    frameCounter = 1;
    time = 0;
}

bool TrajectoryPlayer::loadMotion(const std::string& motionPath, const std::string& goalMotionName)
{
    MMM::MotionReaderXMLPtr reader(new MMM::MotionReaderXML());
    std::vector<std::string> motionNames = reader->getMotionNames(motionPath);

    std::string motionName = goalMotionName;
    if (goalMotionName == "")
    {
        motionName = motionNames[0];
    }
    else
    {
        auto iter = std::find(motionNames.begin(), motionNames.end(), motionName);
        if (iter == motionNames.end())
        {
            std::cout << "Error: Motion " << motionName << " not found. Using first motion instead!" << std::endl;
            return false;
        }
    }

    boost::shared_ptr<ControlPointParser3f> comParser (new ControlPointParser3f("CoM"));
    boost::shared_ptr<ControlPointParser2f> zmpParser (new ControlPointParser2f("ZMP"));
    boost::shared_ptr<ControlMatrixParser4f> leftFootParser (new ControlMatrixParser4f("LeftFoot"));
    boost::shared_ptr<ControlMatrixParser4f> rightFootParser (new ControlMatrixParser4f("RightFoot"));
    boost::shared_ptr<ControlMatrixParser4f> chestParser (new ControlMatrixParser4f("Chest"));
    boost::shared_ptr<ControlMatrixParser4f> pelvisParser (new ControlMatrixParser4f("Pelvis"));
    boost::shared_ptr<ControlValueParser<int>> phaseParser (new ControlValueParser<int>("SupportPhase"));

    reader->registerMotionFrameXMLTag("CoM", comParser);
    reader->registerMotionFrameXMLTag("ZMP", zmpParser);
    reader->registerMotionFrameXMLTag("LeftFoot", leftFootParser);
    reader->registerMotionFrameXMLTag("RightFoot", rightFootParser);
    reader->registerMotionFrameXMLTag("Chest", chestParser);
    reader->registerMotionFrameXMLTag("Pelvis", pelvisParser);
    reader->registerMotionFrameXMLTag("SupportPhase", phaseParser);

    motion = reader->loadMotion(motionPath, motionName);
    if (motion->getMotionFrames().size() < 2)
    {
        std::cout << "Error: Motion needs at least 2 frames!" << std::endl;
        return false;
    }
    reset();

    return true;
}

<|endoftext|>