<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/gfx/gl/gl_context_egl.h"

#include "build/build_config.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "third_party/angle/include/EGL/egl.h"

// This header must come after the above third-party include, as
// it brings in #defines that cause conflicts.
#include "app/gfx/gl/gl_bindings.h"

#if defined(OS_LINUX)
extern "C" {
#include <X11/Xlib.h>
}
#define EGL_HAS_PBUFFERS 1
#endif

namespace gfx {

namespace {

// The EGL configuration to use.
EGLDisplay g_display;
EGLConfig g_config;

// Returns the last EGL error as a string.
const char* GetLastEGLErrorString() {
  EGLint error = eglGetError();
  switch (error) {
    case EGL_SUCCESS:
      return "EGL_SUCCESS";
    case EGL_BAD_ACCESS:
      return "EGL_BAD_ACCESS";
    case EGL_BAD_ALLOC:
      return "EGL_BAD_ALLOC";
    case EGL_BAD_ATTRIBUTE:
      return "EGL_BAD_ATTRIBUTE";
    case EGL_BAD_CONTEXT:
      return "EGL_BAD_CONTEXT";
    case EGL_BAD_CONFIG:
      return "EGL_BAD_CONFIG";
    case EGL_BAD_CURRENT_SURFACE:
      return "EGL_BAD_CURRENT_SURFACE";
    case EGL_BAD_DISPLAY:
      return "EGL_BAD_DISPLAY";
    case EGL_BAD_SURFACE:
      return "EGL_BAD_SURFACE";
    case EGL_BAD_MATCH:
      return "EGL_BAD_MATCH";
    case EGL_BAD_PARAMETER:
      return "EGL_BAD_PARAMETER";
    case EGL_BAD_NATIVE_PIXMAP:
      return "EGL_BAD_NATIVE_PIXMAP";
    case EGL_BAD_NATIVE_WINDOW:
      return "EGL_BAD_NATIVE_WINDOW";
    default:
      return "UNKNOWN";
  }
}
}  // namespace anonymous

SharedEGLSurface::SharedEGLSurface(EGLSurface surface) : surface_(surface) {
}

SharedEGLSurface::~SharedEGLSurface() {
  if (surface_) {
    if (!eglDestroySurface(g_display, surface_)) {
      LOG(ERROR) << "eglDestroySurface failed with error "
                 << GetLastEGLErrorString();
    }
  }
}

EGLSurface SharedEGLSurface::egl_surface() const {
  return surface_;
}

bool BaseEGLContext::InitializeOneOff() {
  static bool initialized = false;
  if (initialized)
    return true;

#ifdef OS_LINUX
  EGLNativeDisplayType native_display = XOpenDisplay(NULL);
#else
  EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY;
#endif
  g_display = eglGetDisplay(native_display);
  if (!g_display) {
    LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
    return false;
  }

  if (!eglInitialize(g_display, NULL, NULL)) {
    LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
    return false;
  }

  // Choose an EGL configuration.
  static const EGLint kConfigAttribs[] = {
    EGL_BUFFER_SIZE, 32,
    EGL_ALPHA_SIZE, 8,
    EGL_BLUE_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_DEPTH_SIZE, 16,
    EGL_STENCIL_SIZE, 8,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#ifdef EGL_HAS_PBUFFERS
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
#else
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif
    EGL_NONE
  };

  EGLint num_configs;
  if (!eglChooseConfig(g_display,
                       kConfigAttribs,
                       NULL,
                       0,
                       &num_configs)) {
    LOG(ERROR) << "eglChooseConfig failed failed with error "
               << GetLastEGLErrorString();
    return false;
  }

  if (num_configs == 0) {
    LOG(ERROR) << "No suitable EGL configs found.";
    return false;
  }

  scoped_array<EGLConfig> configs(new EGLConfig[num_configs]);
  if (!eglChooseConfig(g_display,
                       kConfigAttribs,
                       configs.get(),
                       num_configs,
                       &num_configs)) {
    LOG(ERROR) << "eglChooseConfig failed with error "
               << GetLastEGLErrorString();
    return false;
  }

  g_config = configs[0];

  initialized = true;
  return true;
}

EGLDisplay BaseEGLContext::GetDisplay() {
  return g_display;
}

std::string BaseEGLContext::GetExtensions() {
  const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS);
  if (!extensions)
    return GLContext::GetExtensions();

  return GLContext::GetExtensions() + " " + extensions;
}

NativeViewEGLContext::NativeViewEGLContext(void* window)
    : window_(window),
      context_(NULL)
{
}

NativeViewEGLContext::~NativeViewEGLContext() {
}

bool NativeViewEGLContext::Initialize() {
  DCHECK(!context_);

  // Create a surface for the native window.
  EGLNativeWindowType native_window =
      reinterpret_cast<EGLNativeWindowType>(window_);
  surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display,
                                                         g_config,
                                                         native_window,
                                                         NULL));

  if (!surface_->egl_surface()) {
    LOG(ERROR) << "eglCreateWindowSurface failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  static const EGLint kContextAttributes[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
  };

  context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
  if (!context_) {
    LOG(ERROR) << "eglCreateContext failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  if (!MakeCurrent()) {
    LOG(ERROR) << "MakeCurrent failed.";
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    LOG(ERROR) << "GLContext::InitializeCommon failed.";
    Destroy();
    return false;
  }

  return true;
}

void NativeViewEGLContext::Destroy() {
  if (context_) {
    if (!eglDestroyContext(g_display, context_)) {
      LOG(ERROR) << "eglDestroyContext failed with error "
                 << GetLastEGLErrorString();
    }

    context_ = NULL;
  }

  surface_ = NULL;
}

bool NativeViewEGLContext::MakeCurrent() {
  DCHECK(context_);
  if (!eglMakeCurrent(g_display,
                      surface_->egl_surface(),
                      surface_->egl_surface(),
                      context_)) {
    VLOG(1) << "eglMakeCurrent failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

bool NativeViewEGLContext::IsCurrent() {
  DCHECK(context_);
  return context_ == eglGetCurrentContext();
}

bool NativeViewEGLContext::IsOffscreen() {
  return false;
}

bool NativeViewEGLContext::SwapBuffers() {
  if (!eglSwapBuffers(g_display, surface_->egl_surface())) {
    VLOG(1) << "eglSwapBuffers failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

gfx::Size NativeViewEGLContext::GetSize() {
#if defined(OS_WIN)
  RECT rect;
  if (!GetClientRect(static_cast<HWND>(window_), &rect)) {
    DCHECK(false) << "GetClientRect failed.";
    return gfx::Size();
  }

  return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
#else
  // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't
  // get updated on resize. When it does, we can share the code.
  EGLint width;
  EGLint height;
  if (!eglQuerySurface(
          g_display, surface_->egl_surface(), EGL_WIDTH, &width) ||
      !eglQuerySurface(
          g_display, surface_->egl_surface(), EGL_HEIGHT, &height)) {
    NOTREACHED() << "eglQuerySurface failed with error "
                 << GetLastEGLErrorString();
    return gfx::Size();
  }

  return gfx::Size(width, height);
#endif
}

void* NativeViewEGLContext::GetHandle() {
  return context_;
}

void NativeViewEGLContext::SetSwapInterval(int interval) {
  DCHECK(IsCurrent());
  if (!eglSwapInterval(g_display, interval)) {
    LOG(ERROR) << "eglSwapInterval failed with error "
               << GetLastEGLErrorString();
  }
}

SharedEGLSurface* NativeViewEGLContext::GetSurface() {
  return surface_;
}

SecondaryEGLContext::SecondaryEGLContext()
    : context_(NULL)
{
}

SecondaryEGLContext::~SecondaryEGLContext() {
}

bool SecondaryEGLContext::Initialize(GLContext* shared_context) {
  DCHECK(!context_);

  static const EGLint kContextAttributes[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
  };

  if (shared_context) {
    surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface();

    // Create a context.
    context_ = eglCreateContext(g_display,
                                g_config,
                                shared_context->GetHandle(),
                                kContextAttributes);
  } else {
#ifdef EGL_HAS_PBUFFERS
    static const EGLint kPbufferAttribs[] = {
      EGL_WIDTH, 1,
      EGL_HEIGHT, 1,
      EGL_NONE
    };

    surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display,
                                                            g_config,
                                                            kPbufferAttribs));
    if (!surface_->egl_surface()) {
      LOG(ERROR) << "eglCreatePbufferSurface failed with error "
                 << GetLastEGLErrorString();
      Destroy();
      return false;
    }

    context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
#else
    NOTIMPLEMENTED() << "Offscreen non-shared GLES context";
    return false;
#endif
  }

  if (!context_) {
    LOG(ERROR) << "eglCreateContext failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  return true;
}

void SecondaryEGLContext::Destroy() {
  if (context_) {
    if (!eglDestroyContext(g_display, context_)) {
      LOG(ERROR) << "eglDestroyContext failed with error "
                 << GetLastEGLErrorString();
    }

    context_ = NULL;
  }

  surface_ = NULL;
}

bool SecondaryEGLContext::MakeCurrent() {
  DCHECK(context_);
  if (!eglMakeCurrent(g_display,
                      surface_->egl_surface(),
                      surface_->egl_surface(),
                      context_)) {
    VLOG(1) << "eglMakeCurrent failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

bool SecondaryEGLContext::IsCurrent() {
  DCHECK(context_);
  return context_ == eglGetCurrentContext();
}

bool SecondaryEGLContext::IsOffscreen() {
  return true;
}

bool SecondaryEGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a SecondaryEGLContext.";
  return false;
}

gfx::Size SecondaryEGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this SecondaryEGLContext.";
  return gfx::Size(1, 1);
}

void* SecondaryEGLContext::GetHandle() {
  return context_;
}

void SecondaryEGLContext::SetSwapInterval(int interval) {
  DCHECK(IsCurrent());
  NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext.";
}

SharedEGLSurface* SecondaryEGLContext::GetSurface() {
  return surface_;
}

}  // namespace gfx
<commit_msg>Reland 77766<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/gfx/gl/gl_context_egl.h"

#include "build/build_config.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "third_party/angle/include/EGL/egl.h"

// This header must come after the above third-party include, as
// it brings in #defines that cause conflicts.
#include "app/gfx/gl/gl_bindings.h"

#if defined(OS_WIN)
#include <d3d11.h>
#include <d3dcompiler.h>
#endif

#if defined(OS_LINUX)
extern "C" {
#include <X11/Xlib.h>
}
#define EGL_HAS_PBUFFERS 1
#endif

namespace gfx {

namespace {

// The EGL configuration to use.
EGLDisplay g_display;
EGLConfig g_config;

// Returns the last EGL error as a string.
const char* GetLastEGLErrorString() {
  EGLint error = eglGetError();
  switch (error) {
    case EGL_SUCCESS:
      return "EGL_SUCCESS";
    case EGL_BAD_ACCESS:
      return "EGL_BAD_ACCESS";
    case EGL_BAD_ALLOC:
      return "EGL_BAD_ALLOC";
    case EGL_BAD_ATTRIBUTE:
      return "EGL_BAD_ATTRIBUTE";
    case EGL_BAD_CONTEXT:
      return "EGL_BAD_CONTEXT";
    case EGL_BAD_CONFIG:
      return "EGL_BAD_CONFIG";
    case EGL_BAD_CURRENT_SURFACE:
      return "EGL_BAD_CURRENT_SURFACE";
    case EGL_BAD_DISPLAY:
      return "EGL_BAD_DISPLAY";
    case EGL_BAD_SURFACE:
      return "EGL_BAD_SURFACE";
    case EGL_BAD_MATCH:
      return "EGL_BAD_MATCH";
    case EGL_BAD_PARAMETER:
      return "EGL_BAD_PARAMETER";
    case EGL_BAD_NATIVE_PIXMAP:
      return "EGL_BAD_NATIVE_PIXMAP";
    case EGL_BAD_NATIVE_WINDOW:
      return "EGL_BAD_NATIVE_WINDOW";
    default:
      return "UNKNOWN";
  }
}
}  // namespace anonymous

SharedEGLSurface::SharedEGLSurface(EGLSurface surface) : surface_(surface) {
}

SharedEGLSurface::~SharedEGLSurface() {
  if (surface_) {
    if (!eglDestroySurface(g_display, surface_)) {
      LOG(ERROR) << "eglDestroySurface failed with error "
                 << GetLastEGLErrorString();
    }
  }
}

EGLSurface SharedEGLSurface::egl_surface() const {
  return surface_;
}

bool BaseEGLContext::InitializeOneOff() {
  static bool initialized = false;
  if (initialized)
    return true;

#ifdef OS_LINUX
  EGLNativeDisplayType native_display = XOpenDisplay(NULL);
#else
  EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY;
#endif

#if defined(OS_WIN)
  FilePath module_path;
  if (!PathService::Get(base::DIR_MODULE, &module_path))
    return false;

  base::LoadNativeLibrary(module_path.Append(D3DCOMPILER_DLL));
#endif

  g_display = eglGetDisplay(native_display);
  if (!g_display) {
    LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
    return false;
  }

  if (!eglInitialize(g_display, NULL, NULL)) {
    LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
    return false;
  }

  // Choose an EGL configuration.
  static const EGLint kConfigAttribs[] = {
    EGL_BUFFER_SIZE, 32,
    EGL_ALPHA_SIZE, 8,
    EGL_BLUE_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_DEPTH_SIZE, 16,
    EGL_STENCIL_SIZE, 8,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#ifdef EGL_HAS_PBUFFERS
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
#else
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif
    EGL_NONE
  };

  EGLint num_configs;
  if (!eglChooseConfig(g_display,
                       kConfigAttribs,
                       NULL,
                       0,
                       &num_configs)) {
    LOG(ERROR) << "eglChooseConfig failed failed with error "
               << GetLastEGLErrorString();
    return false;
  }

  if (num_configs == 0) {
    LOG(ERROR) << "No suitable EGL configs found.";
    return false;
  }

  scoped_array<EGLConfig> configs(new EGLConfig[num_configs]);
  if (!eglChooseConfig(g_display,
                       kConfigAttribs,
                       configs.get(),
                       num_configs,
                       &num_configs)) {
    LOG(ERROR) << "eglChooseConfig failed with error "
               << GetLastEGLErrorString();
    return false;
  }

  g_config = configs[0];

  initialized = true;
  return true;
}

EGLDisplay BaseEGLContext::GetDisplay() {
  return g_display;
}

std::string BaseEGLContext::GetExtensions() {
  const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS);
  if (!extensions)
    return GLContext::GetExtensions();

  return GLContext::GetExtensions() + " " + extensions;
}

NativeViewEGLContext::NativeViewEGLContext(void* window)
    : window_(window),
      context_(NULL)
{
}

NativeViewEGLContext::~NativeViewEGLContext() {
}

bool NativeViewEGLContext::Initialize() {
  DCHECK(!context_);

  // Create a surface for the native window.
  EGLNativeWindowType native_window =
      reinterpret_cast<EGLNativeWindowType>(window_);
  surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display,
                                                         g_config,
                                                         native_window,
                                                         NULL));

  if (!surface_->egl_surface()) {
    LOG(ERROR) << "eglCreateWindowSurface failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  static const EGLint kContextAttributes[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
  };

  context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
  if (!context_) {
    LOG(ERROR) << "eglCreateContext failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  if (!MakeCurrent()) {
    LOG(ERROR) << "MakeCurrent failed.";
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    LOG(ERROR) << "GLContext::InitializeCommon failed.";
    Destroy();
    return false;
  }

  return true;
}

void NativeViewEGLContext::Destroy() {
  if (context_) {
    if (!eglDestroyContext(g_display, context_)) {
      LOG(ERROR) << "eglDestroyContext failed with error "
                 << GetLastEGLErrorString();
    }

    context_ = NULL;
  }

  surface_ = NULL;
}

bool NativeViewEGLContext::MakeCurrent() {
  DCHECK(context_);
  if (!eglMakeCurrent(g_display,
                      surface_->egl_surface(),
                      surface_->egl_surface(),
                      context_)) {
    VLOG(1) << "eglMakeCurrent failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

bool NativeViewEGLContext::IsCurrent() {
  DCHECK(context_);
  return context_ == eglGetCurrentContext();
}

bool NativeViewEGLContext::IsOffscreen() {
  return false;
}

bool NativeViewEGLContext::SwapBuffers() {
  if (!eglSwapBuffers(g_display, surface_->egl_surface())) {
    VLOG(1) << "eglSwapBuffers failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

gfx::Size NativeViewEGLContext::GetSize() {
#if defined(OS_WIN)
  RECT rect;
  if (!GetClientRect(static_cast<HWND>(window_), &rect)) {
    DCHECK(false) << "GetClientRect failed.";
    return gfx::Size();
  }

  return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
#else
  // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't
  // get updated on resize. When it does, we can share the code.
  EGLint width;
  EGLint height;
  if (!eglQuerySurface(
          g_display, surface_->egl_surface(), EGL_WIDTH, &width) ||
      !eglQuerySurface(
          g_display, surface_->egl_surface(), EGL_HEIGHT, &height)) {
    NOTREACHED() << "eglQuerySurface failed with error "
                 << GetLastEGLErrorString();
    return gfx::Size();
  }

  return gfx::Size(width, height);
#endif
}

void* NativeViewEGLContext::GetHandle() {
  return context_;
}

void NativeViewEGLContext::SetSwapInterval(int interval) {
  DCHECK(IsCurrent());
  if (!eglSwapInterval(g_display, interval)) {
    LOG(ERROR) << "eglSwapInterval failed with error "
               << GetLastEGLErrorString();
  }
}

SharedEGLSurface* NativeViewEGLContext::GetSurface() {
  return surface_;
}

SecondaryEGLContext::SecondaryEGLContext()
    : context_(NULL)
{
}

SecondaryEGLContext::~SecondaryEGLContext() {
}

bool SecondaryEGLContext::Initialize(GLContext* shared_context) {
  DCHECK(!context_);

  static const EGLint kContextAttributes[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
  };

  if (shared_context) {
    surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface();

    // Create a context.
    context_ = eglCreateContext(g_display,
                                g_config,
                                shared_context->GetHandle(),
                                kContextAttributes);
  } else {
#ifdef EGL_HAS_PBUFFERS
    static const EGLint kPbufferAttribs[] = {
      EGL_WIDTH, 1,
      EGL_HEIGHT, 1,
      EGL_NONE
    };

    surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display,
                                                            g_config,
                                                            kPbufferAttribs));
    if (!surface_->egl_surface()) {
      LOG(ERROR) << "eglCreatePbufferSurface failed with error "
                 << GetLastEGLErrorString();
      Destroy();
      return false;
    }

    context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
#else
    NOTIMPLEMENTED() << "Offscreen non-shared GLES context";
    return false;
#endif
  }

  if (!context_) {
    LOG(ERROR) << "eglCreateContext failed with error "
               << GetLastEGLErrorString();
    Destroy();
    return false;
  }

  return true;
}

void SecondaryEGLContext::Destroy() {
  if (context_) {
    if (!eglDestroyContext(g_display, context_)) {
      LOG(ERROR) << "eglDestroyContext failed with error "
                 << GetLastEGLErrorString();
    }

    context_ = NULL;
  }

  surface_ = NULL;
}

bool SecondaryEGLContext::MakeCurrent() {
  DCHECK(context_);
  if (!eglMakeCurrent(g_display,
                      surface_->egl_surface(),
                      surface_->egl_surface(),
                      context_)) {
    VLOG(1) << "eglMakeCurrent failed with error "
            << GetLastEGLErrorString();
    return false;
  }

  return true;
}

bool SecondaryEGLContext::IsCurrent() {
  DCHECK(context_);
  return context_ == eglGetCurrentContext();
}

bool SecondaryEGLContext::IsOffscreen() {
  return true;
}

bool SecondaryEGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a SecondaryEGLContext.";
  return false;
}

gfx::Size SecondaryEGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this SecondaryEGLContext.";
  return gfx::Size(1, 1);
}

void* SecondaryEGLContext::GetHandle() {
  return context_;
}

void SecondaryEGLContext::SetSwapInterval(int interval) {
  DCHECK(IsCurrent());
  NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext.";
}

SharedEGLSurface* SecondaryEGLContext::GetSurface() {
  return surface_;
}

}  // namespace gfx
<|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <tsdb/SQLEngine.h>
#include <tsdb/TSDBNode.h>
#include <tsdb/TimeWindowPartitioner.h>
#include <chartsql/defaults.h>

namespace tsdb {

SQLEngine::SQLEngine(TSDBNode* tsdb_node) : tsdb_node_(tsdb_node) {
  installDefaultSymbols(&sql_runtime_);
}

void SQLEngine::executeQuery(
    const String& tsdb_namespace,
    const String& query,
    RefPtr<csql::ResultFormat> result_format) {
  auto qplan = parseAndBuildQueryPlan(tsdb_namespace, query);
  sql_runtime_.executeQuery(qplan, result_format);
}

RefPtr<csql::QueryPlan> SQLEngine::parseAndBuildQueryPlan(
    const String& tsdb_namespace,
    const String& query) {
  return sql_runtime_.parseAndBuildQueryPlan(
      query,
      tableProviderForNamespace(tsdb_namespace),
      std::bind(
          &SQLEngine::rewriteQuery,
          this,
          tsdb_namespace,
          std::placeholders::_1));
}

RefPtr<csql::QueryTreeNode> SQLEngine::rewriteQuery(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode> query) {
  if (dynamic_cast<csql::TableExpressionNode*>(query.get())) {
    replaceAllSequentialScansWithUnions(tsdb_namespace, &query);
  }

  return query;
}

RefPtr<csql::TableProvider> SQLEngine::tableProviderForNamespace(
    const String& tsdb_namespace) {
  return new TSDBTableProvider(tsdb_namespace, tsdb_node_);
}

void SQLEngine::replaceAllSequentialScansWithUnions(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode>* node) {
  if (dynamic_cast<csql::SequentialScanNode*>(node->get())) {
    replaceSequentialScanWithUnion(tsdb_namespace, node);
    return;
  }

  auto ntables = node->get()->numChildren();
  for (int i = 0; i < ntables; ++i) {
    replaceAllSequentialScansWithUnions(
        tsdb_namespace,
        node->get()->mutableChild(i));
  }
}

void SQLEngine::replaceSequentialScanWithUnion(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode>* node) {
  auto seqscan = node->asInstanceOf<csql::SequentialScanNode>();

  auto table_ref = TSDBTableRef::parse(seqscan->tableName());
  if (!table_ref.partition_key.isEmpty()) {
    return;
  }

  if (table_ref.timerange_begin.isEmpty() ||
      table_ref.timerange_limit.isEmpty()) {
    RAISEF(
        kRuntimeError,
        "invalid reference to timeseries table '$0' without timerange. " \
        "try appending .last30days to the table name",
        table_ref.table_key);
  }

  auto partitions = TimeWindowPartitioner::partitionKeysFor(
      table_ref.table_key,
      table_ref.timerange_begin.get(),
      table_ref.timerange_limit.get(),
      4 * kMicrosPerHour);

  Vector<RefPtr<csql::QueryTreeNode>> union_tables;
  for (const auto& partition : partitions) {
    auto table_name = StringUtil::format(
        "tsdb://localhost/$0/$1",
        URI::urlEncode(table_ref.table_key),
        partition.toString());

    auto copy = seqscan->deepCopyAs<csql::SequentialScanNode>();
    copy->setTableName(table_name);
    union_tables.emplace_back(copy.get());
  }

  *node = RefPtr<csql::QueryTreeNode>(new csql::UnionNode(union_tables));
}

}
<commit_msg>cleaning up<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <tsdb/SQLEngine.h>
#include <tsdb/TSDBNode.h>
#include <tsdb/TimeWindowPartitioner.h>
#include <chartsql/defaults.h>

namespace tsdb {

SQLEngine::SQLEngine(TSDBNode* tsdb_node) : tsdb_node_(tsdb_node) {
  installDefaultSymbols(&sql_runtime_);
}

void SQLEngine::executeQuery(
    const String& tsdb_namespace,
    const String& query,
    RefPtr<csql::ResultFormat> result_format) {
  auto qplan = parseAndBuildQueryPlan(tsdb_namespace, query);
  sql_runtime_.executeQuery(qplan, result_format);
}

RefPtr<csql::QueryPlan> SQLEngine::parseAndBuildQueryPlan(
    const String& tsdb_namespace,
    const String& query) {
  return sql_runtime_.parseAndBuildQueryPlan(
      query,
      tableProviderForNamespace(tsdb_namespace),
      std::bind(
          &SQLEngine::rewriteQuery,
          this,
          tsdb_namespace,
          std::placeholders::_1));
}

RefPtr<csql::QueryTreeNode> SQLEngine::rewriteQuery(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode> query) {
  replaceAllSequentialScansWithUnions(tsdb_namespace, &query);
  return query;
}

RefPtr<csql::TableProvider> SQLEngine::tableProviderForNamespace(
    const String& tsdb_namespace) {
  return new TSDBTableProvider(tsdb_namespace, tsdb_node_);
}

void SQLEngine::replaceAllSequentialScansWithUnions(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode>* node) {
  if (dynamic_cast<csql::SequentialScanNode*>(node->get())) {
    replaceSequentialScanWithUnion(tsdb_namespace, node);
    return;
  }

  auto ntables = node->get()->numChildren();
  for (int i = 0; i < ntables; ++i) {
    replaceAllSequentialScansWithUnions(
        tsdb_namespace,
        node->get()->mutableChild(i));
  }
}

void SQLEngine::replaceSequentialScanWithUnion(
    const String& tsdb_namespace,
    RefPtr<csql::QueryTreeNode>* node) {
  auto seqscan = node->asInstanceOf<csql::SequentialScanNode>();

  auto table_ref = TSDBTableRef::parse(seqscan->tableName());
  if (!table_ref.partition_key.isEmpty()) {
    return;
  }

  if (table_ref.timerange_begin.isEmpty() ||
      table_ref.timerange_limit.isEmpty()) {
    RAISEF(
        kRuntimeError,
        "invalid reference to timeseries table '$0' without timerange. " \
        "try appending .last30days to the table name",
        table_ref.table_key);
  }

  auto partitions = TimeWindowPartitioner::partitionKeysFor(
      table_ref.table_key,
      table_ref.timerange_begin.get(),
      table_ref.timerange_limit.get(),
      4 * kMicrosPerHour);

  Vector<RefPtr<csql::QueryTreeNode>> union_tables;
  for (const auto& partition : partitions) {
    auto table_name = StringUtil::format(
        "tsdb://localhost/$0/$1",
        URI::urlEncode(table_ref.table_key),
        partition.toString());

    auto copy = seqscan->deepCopyAs<csql::SequentialScanNode>();
    copy->setTableName(table_name);
    union_tables.emplace_back(copy.get());
  }

  *node = RefPtr<csql::QueryTreeNode>(new csql::UnionNode(union_tables));
}

}
<|endoftext|>


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

   Flexbar - flexible barcode and adapter removal

   Version 3.5.0

   BSD 3-Clause License

   uses SeqAn library release 2.4.0
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

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

	using namespace std;
	using namespace seqan;

	const string version = "3.5 beta 3";
	const string date    = "January 2019";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<commit_msg>Flexbar 3.5 release<commit_after>/*==================================================

   Flexbar - flexible barcode and adapter removal

   Version 3.5.0

   BSD 3-Clause License

   uses SeqAn library release 2.4.0
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

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

	using namespace std;
	using namespace seqan;

	const string version = "3.5.0";
	const string date    = "May 2019";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Gyro class
 */
#import "I2CDevices.h"
#define DEG_TO_RAD 0.01745329278

I2CGyro::I2CGyro(int addr) : I2CDevice(addr) {
  _data = {0, 0, 0};
}

I2CGyro::I2CGyro() : I2CDevice(0x68) {
  _data = {0, 0, 0};
  _offset[0] = _offset[1] = _offset[2] = 0;
  _temp.i = 0;
  _cal_factor = 0.06956521739;
}

void I2CGyro::init() {
  send_cmd(0x3E, 0x80);
  send_cmd(0x16, 0x1B);
  send_cmd(0x15, 0x04); // 1kHz / (n+1) = f
  send_cmd(0x3E, 0x01);
}

void I2CGyro::update() {
  // Request for data
  send_cmd(0x1B); // Temperature
  Wire.requestFrom(_addr, 8);
  _temp.c[1] = (byte)Wire.read();
  _temp.c[0] = (byte)Wire.read();

  _data.b[1] = (byte)Wire.read();
  _data.b[0] = (byte)Wire.read();

  _data.b[3] = (byte)Wire.read();
  _data.b[2] = (byte)Wire.read();

  _data.b[5] = (byte)Wire.read();
  _data.b[4] = (byte)Wire.read();
}

float I2CGyro::temp_c() {
  return (_temp.i + 23300) / 280.0;
}

short int I2CGyro::x() {
  return - (_data.i[0] - _offset[0]);
}

short int I2CGyro::y() {
  return - (_data.i[1] - _offset[1]);
}

short int I2CGyro::z() {
  return _data.i[2] - _offset[2];
}

double I2CGyro::x_ds() {
  return x() * _cal_factor;
}

double I2CGyro::y_ds() {
  return y() * _cal_factor;
}

double I2CGyro::z_ds() {
  return z() * _cal_factor;
}

double I2CGyro::x_rs() {
  return x_ds() * DEG_TO_RAD;
}

double I2CGyro::y_rs() {
  return y() * DEG_TO_RAD;
}

double I2CGyro::z_rs() {
  return z() * DEG_TO_RAD;
}

void I2CGyro::calibrate(int n_sample, int dly) {
  double cal = 0.0;
  for (int i = 0; i < n_sample; i++) {
    update();
    _offset[0] += _data.i[0];
    _offset[1] += _data.i[1];
    _offset[2] += _data.i[2];
    delay(dly);
  }
  _offset[0] /= double(n_sample);
  _offset[1] /= double(n_sample);
  _offset[2] /= double(n_sample);
}

void I2CGyro::describe() {
  Serial.print("GYRO@0x");
  Serial.print(_addr, HEX);
  Serial.print(" T: ");
  Serial.print(temp_c());
  Serial.print(" x: ");
  Serial.print(x_ds());
  Serial.print(" y: ");
  Serial.print(y_ds());
  Serial.print(" z: ");
  Serial.print(z_ds());
}

void I2CGyro::describe(int mod) {
  Serial.print("GYRO@0x");
  Serial.print(_addr, HEX);
  Serial.print(" T: ");
  Serial.print(_temp.c[0], mod);
  Serial.print("|");
  Serial.print(_temp.c[1], mod);
  Serial.print(" x: ");
  Serial.print(_data.b[0], mod);
  Serial.print("|");
  Serial.print(_data.b[1], mod);
  Serial.print(" y: ");
  Serial.print(_data.b[2], mod);
  Serial.print("|");
  Serial.print(_data.b[3], mod);
  Serial.print(" z: ");
  Serial.print(_data.b[4], mod);
  Serial.print("|");
  Serial.print(_data.b[5], mod);
}
<commit_msg>Updated registers for Gyro<commit_after>/*
 * Gyro class
 */
#import "I2CDevices.h"
#define DEG_TO_RAD 0.01745329278

I2CGyro::I2CGyro(int addr) : I2CDevice(addr) {
  _data = {0, 0, 0};
}

I2CGyro::I2CGyro() : I2CDevice(0x68) {
  _data = {0, 0, 0};
  _offset[0] = _offset[1] = _offset[2] = 0;
  _temp.i = 0;
  _cal_factor = 0.06956521739;
}

void I2CGyro::init() {
  send_cmd(0x3E, 0x80); // Reset default
  send_cmd(0x16, 0x19); // Low Pass filter at 188Hz
  send_cmd(0x15, 0x04); // 1kHz / (n+1) = f
  send_cmd(0x3E, 0x01); // select X Gyro for clock reference
}

void I2CGyro::update() {
  // Request for data
  send_cmd(0x1B); // Temperature
  Wire.requestFrom(_addr, 8);
  _temp.c[1] = (byte)Wire.read();
  _temp.c[0] = (byte)Wire.read();

  _data.b[1] = (byte)Wire.read();
  _data.b[0] = (byte)Wire.read();

  _data.b[3] = (byte)Wire.read();
  _data.b[2] = (byte)Wire.read();

  _data.b[5] = (byte)Wire.read();
  _data.b[4] = (byte)Wire.read();
}

float I2CGyro::temp_c() {
  return (_temp.i + 23300) / 280.0;
}

short int I2CGyro::x() {
  return - (_data.i[0] - _offset[0]);
}

short int I2CGyro::y() {
  return - (_data.i[1] - _offset[1]);
}

short int I2CGyro::z() {
  return _data.i[2] - _offset[2];
}

double I2CGyro::x_ds() {
  return x() * _cal_factor;
}

double I2CGyro::y_ds() {
  return y() * _cal_factor;
}

double I2CGyro::z_ds() {
  return z() * _cal_factor;
}

double I2CGyro::x_rs() {
  return x_ds() * DEG_TO_RAD;
}

double I2CGyro::y_rs() {
  return y() * DEG_TO_RAD;
}

double I2CGyro::z_rs() {
  return z() * DEG_TO_RAD;
}

void I2CGyro::calibrate(int n_sample, int dly) {
  double cal = 0.0;
  for (int i = 0; i < n_sample; i++) {
    update();
    _offset[0] += _data.i[0];
    _offset[1] += _data.i[1];
    _offset[2] += _data.i[2];
    delay(dly);
  }
  _offset[0] /= double(n_sample);
  _offset[1] /= double(n_sample);
  _offset[2] /= double(n_sample);
}

void I2CGyro::describe() {
  Serial.print("GYRO@0x");
  Serial.print(_addr, HEX);
  Serial.print(" T: ");
  Serial.print(temp_c());
  Serial.print(" x: ");
  Serial.print(x_ds());
  Serial.print(" y: ");
  Serial.print(y_ds());
  Serial.print(" z: ");
  Serial.print(z_ds());
}

void I2CGyro::describe(int mod) {
  Serial.print("GYRO@0x");
  Serial.print(_addr, HEX);
  Serial.print(" T: ");
  Serial.print(_temp.c[0], mod);
  Serial.print("|");
  Serial.print(_temp.c[1], mod);
  Serial.print(" x: ");
  Serial.print(_data.b[0], mod);
  Serial.print("|");
  Serial.print(_data.b[1], mod);
  Serial.print(" y: ");
  Serial.print(_data.b[2], mod);
  Serial.print("|");
  Serial.print(_data.b[3], mod);
  Serial.print(" z: ");
  Serial.print(_data.b[4], mod);
  Serial.print("|");
  Serial.print(_data.b[5], mod);
}
<|endoftext|>


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

 Infomap software package for multi-level network clustering

 Copyright (c) 2013 Daniel Edler, Martin Rosvall

 For more information, see <http://www.mapequation.org>

 This file is part of Infomap software package.

 Infomap software package is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Infomap software package is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with Infomap software package.  If not, see <http://www.gnu.org/licenses/>.

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

#include <iostream>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include "utils/Logger.h"
#include "io/Config.h"
#include "infomap/InfomapContext.h"
#include "utils/Stopwatch.h"
#include "io/ProgramInterface.h"
#include "io/convert.h"
#include "utils/FileURI.h"
#include "utils/Date.h"
#include <iomanip>
#include "io/version.h"

void runInfomap(Config const& config)
{
	InfomapContext context(config);
	context.getInfomap()->run();
}

Config getConfig(int argc, char *argv[])
{
	Config conf;
	ProgramInterface api("Infomap",
			"Implementation of the Infomap clustering algorithm based on the Map Equation (see www.mapequation.org)",
			INFOMAP_VERSION);

	// --------------------- Input options ---------------------
	api.addNonOptionArgument(conf.networkFile, "network_file",
			"The file containing the network data. Accepted formats: Pajek (implied by .net) and link list (.txt)");

	api.addOptionArgument(conf.inputFormat, 'i', "input-format",
			"Specify input format ('pajek' or 'link-list') to override format possibly implied by file extension.", "s");

	api.addOptionArgument(conf.zeroBasedNodeNumbers, 'z', "zero-based-numbering",
			"Assume node numbers start from zero in the input file instead of one.");

	api.addOptionArgument(conf.includeSelfLinks, 'k', "include-self-links",
			"Include links with the same source and target node. (Ignored by default.)");

	api.addOptionArgument(conf.nodeLimit, 'O', "node-limit",
			"Limit the number of nodes to read from the network. Ignore links connected to ignored nodes.", "n");

	api.addOptionArgument(conf.clusterDataFile, 'c', "cluster-data",
			"Provide an initial two-level solution (.clu format).", "p");

	// --------------------- Output options ---------------------
	api.addOptionArgument(conf.printTree, "tree",
			"Print the hierarchy in .tree format. (default true)");

	api.addOptionArgument(conf.printMap, "map",
			"Print the top two-level modular network in the .map format.");

	api.addOptionArgument(conf.printClu, "clu",
			"Print the top cluster indices for each node.");

	api.addOptionArgument(conf.printNodeRanks, "node-ranks",
			"Print the calculated flow for each node to a file.");

	api.addOptionArgument(conf.printPajekNetwork, "pajek",
			"Print the parsed network in Pajek format.");

	api.addOptionArgument(conf.printBinaryTree, "btree",
			"Print the tree in a streamable binary format.");

	api.addOptionArgument(conf.printBinaryFlowTree, "bftree",
			"Print the tree including horizontal flow links in a streamable binary format.");

	api.addOptionArgument(conf.printFlowNetwork, "flow-network",
			"Print the network with calculated flow values.");

	api.addOptionArgument(conf.noFileOutput, '0', "no-file-output",
			"Don't print any output to file.");

	// --------------------- Core algorithm options ---------------------
	api.addOptionArgument(conf.twoLevel, '2', "two-level",
			"Optimize a two-level partition of the network.");

	bool dummyUndirected;
	api.addOptionArgument(dummyUndirected, 'u', "undirected",
			"Assume undirected links. (default)");

	api.addOptionArgument(conf.directed, 'd', "directed",
			"Assume directed links.");

	api.addOptionArgument(conf.undirdir, 't', "undirdir",
			"Two-mode dynamics: Assume undirected links for calculating flow, but directed when minimizing codelength.");

	api.addOptionArgument(conf.outdirdir, "outdirdir",
			"Two-mode dynamics: Count only ingoing links when calculating the flow, but all when minimizing codelength.");

	api.addOptionArgument(conf.rawdir, 'w', "rawdir",
			"Two-mode dynamics: Assume directed links and let the raw link weights be the flow.");

	api.addOptionArgument(conf.recordedTeleportation, 'e', "recorded-teleportation",
			"If teleportation is used to calculate the flow, also record it when minimizing codelength.");

	api.addOptionArgument(conf.teleportToNodes, 'o', "to-nodes",
			"Teleport to nodes (like the PageRank algorithm) instead of to links.");

	api.addOptionArgument(conf.teleportationProbability, 'p', "teleportation-probability",
			"The probability of teleporting to a random node or link.", "f");

	api.addOptionArgument(conf.selfTeleportationProbability, 'y', "self-link-teleportation-probability",
			"The probability of teleporting to itself. Effectively increasing the code rate, generating more and smaller modules.", "f");

	api.addOptionArgument(conf.seedToRandomNumberGenerator, 's', "seed",
			"A seed (integer) to the random number generator.", "n");

	// --------------------- Performance and accuracy options ---------------------
	api.addOptionArgument(conf.numTrials, 'N', "num-trials",
			"The number of outer-most loops to run before picking the best solution.", "n");

	api.addOptionArgument(conf.minimumCodelengthImprovement, 'm', "min-improvement",
			"Minimum codelength threshold for accepting a new solution.", "f");

	api.addOptionArgument(conf.randomizeCoreLoopLimit, 'a', "random-loop-limit",
			"Randomize the core loop limit from 1 to 'core-loop-limit'");

	api.addOptionArgument(conf.coreLoopLimit, 'M', "core-loop-limit",
			"Limit the number of loops that tries to move each node into the best possible module", "n");

	api.addOptionArgument(conf.levelAggregationLimit, 'L', "core-level-limit",
			"Limit the number of times the core loops are reapplied on existing modular network to search bigger structures.", "n");

	api.addOptionArgument(conf.tuneIterationLimit, 'T', "tune-iteration-limit",
			"Limit the number of main iterations in the two-level partition algorithm. 0 means no limit.", "n");

	api.addOptionArgument(conf.minimumRelativeTuneIterationImprovement, 'U', "tune-iteration-threshold",
			"Set a codelength improvement threshold of each new tune iteration to 'f' times the initial two-level codelength.", "f");

	api.addOptionArgument(conf.fastCoarseTunePartition, 'C', "fast-coarse-tune",
			"Try to find the quickest partition of each module when creating sub-modules for the coarse-tune part.");

	api.addOptionArgument(conf.alternateCoarseTuneLevel, 'A', "alternate-coarse-tune-level",
			"Try to find different levels of sub-modules to move in the coarse-tune part.");

	api.addOptionArgument(conf.coarseTuneLevel, 'S', "coarse-tune-level",
			"Set the recursion limit when searching for sub-modules. A level of 1 will find sub-sub-modules.", "n");

	api.addIncrementalOptionArgument(conf.fastHierarchicalSolution, 'F', "fast-hierarchical-solution",
			"Find top modules fast. Use -FF to keep all fast levels. Use -FFF to skip recursive part.");

	// --------------------- Output options ---------------------
	api.addNonOptionArgument(conf.outDirectory, "out_directory",
			"The directory to write the results to");

	api.addIncrementalOptionArgument(conf.verbosity, 'v', "verbose",
			"Verbose output on the console. Add additional 'v' flags to increase verbosity up to -vvv.");

	api.parseArgs(argc, argv);

	// Some checks
	if (*--conf.outDirectory.end() != '/')
		conf.outDirectory.append("/");

	return conf;
}

void initBenchmark(const Config& conf, int argc, char * const argv[])
{
	std::string networkName = FileURI(conf.networkFile).getName();
	std::string logFilename = io::Str() << conf.outDirectory << networkName << ".tsv";
	Logger::setBenchmarkFilename(logFilename);
	std::ostringstream logInfo;
	logInfo << "#benchmark for";
	for (int i = 0; i < argc; ++i)
		logInfo << " " << argv[i];
	Logger::benchmark(logInfo.str(), 0, 0, 0, 0, true);
	Logger::benchmark("elapsedSeconds\ttag\tcodelength\tnumTopModules\tnumNonTrivialTopModules\ttreeDepth",
			0, 0, 0, 0, true);
	// (todo: fix problem with initializing same static file from different functions to simplify above)
	std::cout << "(Writing benchmark log to '" << logFilename << "'...)\n";
}

int run(int argc, char* argv[])
{
	Date startDate;
	Config conf;
	try
	{
		conf = getConfig(argc, argv);
		if (conf.benchmark)
			initBenchmark(conf, argc, argv);
		if (conf.verbosity == 0)
			conf.verboseNumberPrecision = 4;
		std::cout << std::setprecision(conf.verboseNumberPrecision);
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
		return 1;
	}

	std::cout << "===========================================\n";
	std::cout << "  Infomap starts at " << Date() << "\n";
	std::cout << "===========================================\n";

	runInfomap(conf);

	ASSERT(NodeBase::nodeCount() == 0); //TODO: Not working with OpenMP
//	if (NodeBase::nodeCount() != 0)
//		std::cout << "Warning: " << NodeBase::nodeCount() << " nodes not deleted!\n";

	std::cout << "===========================================\n";
	std::cout << "  Infomap ends at " << Date() << "\n";
	std::cout << "  (Elapsed time: " << (Date() - startDate) << ")\n";
	std::cout << "===========================================\n";

//	ElapsedTime t1 = (Date() - startDate);
//	std::cout << "Elapsed time: " << t1 << " (" <<
//			Stopwatch::getElapsedTimeSinceProgramStartInSec() << "s serial)." << std::endl;
	return 0;
}

int main(int argc, char* argv[])
{
	return run(argc, argv);
}
<commit_msg>Writing out infomap version when running.<commit_after>/**********************************************************************************

 Infomap software package for multi-level network clustering

 Copyright (c) 2013 Daniel Edler, Martin Rosvall

 For more information, see <http://www.mapequation.org>

 This file is part of Infomap software package.

 Infomap software package is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Infomap software package is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with Infomap software package.  If not, see <http://www.gnu.org/licenses/>.

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

#include <iostream>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include "utils/Logger.h"
#include "io/Config.h"
#include "infomap/InfomapContext.h"
#include "utils/Stopwatch.h"
#include "io/ProgramInterface.h"
#include "io/convert.h"
#include "utils/FileURI.h"
#include "utils/Date.h"
#include <iomanip>
#include "io/version.h"

void runInfomap(Config const& config)
{
	InfomapContext context(config);
	context.getInfomap()->run();
}

Config getConfig(int argc, char *argv[])
{
	Config conf;
	ProgramInterface api("Infomap",
			"Implementation of the Infomap clustering algorithm based on the Map Equation (see www.mapequation.org)",
			INFOMAP_VERSION);

	// --------------------- Input options ---------------------
	api.addNonOptionArgument(conf.networkFile, "network_file",
			"The file containing the network data. Accepted formats: Pajek (implied by .net) and link list (.txt)");

	api.addOptionArgument(conf.inputFormat, 'i', "input-format",
			"Specify input format ('pajek' or 'link-list') to override format possibly implied by file extension.", "s");

	api.addOptionArgument(conf.zeroBasedNodeNumbers, 'z', "zero-based-numbering",
			"Assume node numbers start from zero in the input file instead of one.");

	api.addOptionArgument(conf.includeSelfLinks, 'k', "include-self-links",
			"Include links with the same source and target node. (Ignored by default.)");

	api.addOptionArgument(conf.nodeLimit, 'O', "node-limit",
			"Limit the number of nodes to read from the network. Ignore links connected to ignored nodes.", "n");

	api.addOptionArgument(conf.clusterDataFile, 'c', "cluster-data",
			"Provide an initial two-level solution (.clu format).", "p");

	// --------------------- Output options ---------------------
	api.addOptionArgument(conf.printTree, "tree",
			"Print the hierarchy in .tree format. (default true)");

	api.addOptionArgument(conf.printMap, "map",
			"Print the top two-level modular network in the .map format.");

	api.addOptionArgument(conf.printClu, "clu",
			"Print the top cluster indices for each node.");

	api.addOptionArgument(conf.printNodeRanks, "node-ranks",
			"Print the calculated flow for each node to a file.");

	api.addOptionArgument(conf.printPajekNetwork, "pajek",
			"Print the parsed network in Pajek format.");

	api.addOptionArgument(conf.printBinaryTree, "btree",
			"Print the tree in a streamable binary format.");

	api.addOptionArgument(conf.printBinaryFlowTree, "bftree",
			"Print the tree including horizontal flow links in a streamable binary format.");

	api.addOptionArgument(conf.printFlowNetwork, "flow-network",
			"Print the network with calculated flow values.");

	api.addOptionArgument(conf.noFileOutput, '0', "no-file-output",
			"Don't print any output to file.");

	// --------------------- Core algorithm options ---------------------
	api.addOptionArgument(conf.twoLevel, '2', "two-level",
			"Optimize a two-level partition of the network.");

	bool dummyUndirected;
	api.addOptionArgument(dummyUndirected, 'u', "undirected",
			"Assume undirected links. (default)");

	api.addOptionArgument(conf.directed, 'd', "directed",
			"Assume directed links.");

	api.addOptionArgument(conf.undirdir, 't', "undirdir",
			"Two-mode dynamics: Assume undirected links for calculating flow, but directed when minimizing codelength.");

	api.addOptionArgument(conf.outdirdir, "outdirdir",
			"Two-mode dynamics: Count only ingoing links when calculating the flow, but all when minimizing codelength.");

	api.addOptionArgument(conf.rawdir, 'w', "rawdir",
			"Two-mode dynamics: Assume directed links and let the raw link weights be the flow.");

	api.addOptionArgument(conf.recordedTeleportation, 'e', "recorded-teleportation",
			"If teleportation is used to calculate the flow, also record it when minimizing codelength.");

	api.addOptionArgument(conf.teleportToNodes, 'o', "to-nodes",
			"Teleport to nodes (like the PageRank algorithm) instead of to links.");

	api.addOptionArgument(conf.teleportationProbability, 'p', "teleportation-probability",
			"The probability of teleporting to a random node or link.", "f");

	api.addOptionArgument(conf.selfTeleportationProbability, 'y', "self-link-teleportation-probability",
			"The probability of teleporting to itself. Effectively increasing the code rate, generating more and smaller modules.", "f");

	api.addOptionArgument(conf.seedToRandomNumberGenerator, 's', "seed",
			"A seed (integer) to the random number generator.", "n");

	// --------------------- Performance and accuracy options ---------------------
	api.addOptionArgument(conf.numTrials, 'N', "num-trials",
			"The number of outer-most loops to run before picking the best solution.", "n");

	api.addOptionArgument(conf.minimumCodelengthImprovement, 'm', "min-improvement",
			"Minimum codelength threshold for accepting a new solution.", "f");

	api.addOptionArgument(conf.randomizeCoreLoopLimit, 'a', "random-loop-limit",
			"Randomize the core loop limit from 1 to 'core-loop-limit'");

	api.addOptionArgument(conf.coreLoopLimit, 'M', "core-loop-limit",
			"Limit the number of loops that tries to move each node into the best possible module", "n");

	api.addOptionArgument(conf.levelAggregationLimit, 'L', "core-level-limit",
			"Limit the number of times the core loops are reapplied on existing modular network to search bigger structures.", "n");

	api.addOptionArgument(conf.tuneIterationLimit, 'T', "tune-iteration-limit",
			"Limit the number of main iterations in the two-level partition algorithm. 0 means no limit.", "n");

	api.addOptionArgument(conf.minimumRelativeTuneIterationImprovement, 'U', "tune-iteration-threshold",
			"Set a codelength improvement threshold of each new tune iteration to 'f' times the initial two-level codelength.", "f");

	api.addOptionArgument(conf.fastCoarseTunePartition, 'C', "fast-coarse-tune",
			"Try to find the quickest partition of each module when creating sub-modules for the coarse-tune part.");

	api.addOptionArgument(conf.alternateCoarseTuneLevel, 'A', "alternate-coarse-tune-level",
			"Try to find different levels of sub-modules to move in the coarse-tune part.");

	api.addOptionArgument(conf.coarseTuneLevel, 'S', "coarse-tune-level",
			"Set the recursion limit when searching for sub-modules. A level of 1 will find sub-sub-modules.", "n");

	api.addIncrementalOptionArgument(conf.fastHierarchicalSolution, 'F', "fast-hierarchical-solution",
			"Find top modules fast. Use -FF to keep all fast levels. Use -FFF to skip recursive part.");

	// --------------------- Output options ---------------------
	api.addNonOptionArgument(conf.outDirectory, "out_directory",
			"The directory to write the results to");

	api.addIncrementalOptionArgument(conf.verbosity, 'v', "verbose",
			"Verbose output on the console. Add additional 'v' flags to increase verbosity up to -vvv.");

	api.parseArgs(argc, argv);

	// Some checks
	if (*--conf.outDirectory.end() != '/')
		conf.outDirectory.append("/");

	return conf;
}

void initBenchmark(const Config& conf, int argc, char * const argv[])
{
	std::string networkName = FileURI(conf.networkFile).getName();
	std::string logFilename = io::Str() << conf.outDirectory << networkName << ".tsv";
	Logger::setBenchmarkFilename(logFilename);
	std::ostringstream logInfo;
	logInfo << "#benchmark for";
	for (int i = 0; i < argc; ++i)
		logInfo << " " << argv[i];
	Logger::benchmark(logInfo.str(), 0, 0, 0, 0, true);
	Logger::benchmark("elapsedSeconds\ttag\tcodelength\tnumTopModules\tnumNonTrivialTopModules\ttreeDepth",
			0, 0, 0, 0, true);
	// (todo: fix problem with initializing same static file from different functions to simplify above)
	std::cout << "(Writing benchmark log to '" << logFilename << "'...)\n";
}

int run(int argc, char* argv[])
{
	Date startDate;
	Config conf;
	try
	{
		conf = getConfig(argc, argv);
		if (conf.benchmark)
			initBenchmark(conf, argc, argv);
		if (conf.verbosity == 0)
			conf.verboseNumberPrecision = 4;
		std::cout << std::setprecision(conf.verboseNumberPrecision);
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
		return 1;
	}

	std::cout << "===========================================\n";
	std::cout << "  Infomap v" << INFOMAP_VERSION << " starts at " << Date() << "\n";
	std::cout << "===========================================\n";

	runInfomap(conf);

	ASSERT(NodeBase::nodeCount() == 0); //TODO: Not working with OpenMP
//	if (NodeBase::nodeCount() != 0)
//		std::cout << "Warning: " << NodeBase::nodeCount() << " nodes not deleted!\n";

	std::cout << "===========================================\n";
	std::cout << "  Infomap ends at " << Date() << "\n";
	std::cout << "  (Elapsed time: " << (Date() - startDate) << ")\n";
	std::cout << "===========================================\n";

//	ElapsedTime t1 = (Date() - startDate);
//	std::cout << "Elapsed time: " << t1 << " (" <<
//			Stopwatch::getElapsedTimeSinceProgramStartInSec() << "s serial)." << std::endl;
	return 0;
}

int main(int argc, char* argv[])
{
	return run(argc, argv);
}
<|endoftext|>


<commit_before>#ifndef COMPOSE_HPP
# define COMPOSE_HPP
# pragma once

#include <type_traits>

#include <utility>

namespace
{

template <typename R, typename ...A>
struct signature
{
};

template <typename R, typename ...A>
constexpr auto extract_signature(R (*const)(A...)) noexcept
{
  return signature<R, A...>();
}

template <typename C, typename R, typename ...A>
constexpr auto extract_signature(R (C::* const)(A...)) noexcept
{
  return signature<R, A...>();
}

template <typename C, typename R, typename ...A>
constexpr auto extract_signature(R (C::* const)(A...) const) noexcept
{
  return signature<R, A...>();
}

template <typename F>
constexpr auto extract_signature(F const&) noexcept ->
  decltype(&F::operator(), extract_signature(&F::operator()))
{
  return extract_signature(&F::operator());
}

template <typename F1, typename F2, bool, typename ...A1>
class composer;

template <typename F1, typename F2, typename ...A1>
class composer<F1, F2, true, A1...>
{
  F1 const f1_;
  F2 const f2_;

public:
  explicit composer(F1&& f1, F2&& f2) noexcept :
    f1_(::std::forward<F1>(f1)),
    f2_(::std::forward<F2>(f2))
  {
  }

  auto operator()(A1&& ...args) const noexcept(
    noexcept(f2_(f1_(::std::forward<A1>(args)...)))
  )
  {
    return f2_(f1_(::std::forward<A1>(args)...));
  }
};

template <typename F1, typename F2, typename ...A1>
class composer<F1, F2, false, A1...>
{
  F1 const f1_;
  F2 const f2_;

public:
  explicit composer(F1&& f1, F2&& f2) noexcept :
    f1_(::std::forward<F1>(f1)),
    f2_(::std::forward<F2>(f2))
  {
  }

  auto operator()(A1&& ...args) const noexcept(
    noexcept(f1_(::std::forward<A1>(args)...), f2_())
  )
  {
    return f1_(::std::forward<A1>(args)...), f2_();
  }
};

template <
  typename F1, typename R1, typename ...A1,
  typename F2, typename R2, typename ...A2
>
inline auto compose(
  F1&& f1, signature<R1, A1...> const,
  F2&& f2, signature<R2, A2...> const) noexcept(
  noexcept(
    composer<F1, F2, sizeof...(A2), A1...>(::std::forward<F1>(f1),
      ::std::forward<F2>(f2)
    )
  )
)
{
  return composer<F1, F2, sizeof...(A2), A1...>(::std::forward<F1>(f1),
    ::std::forward<F2>(f2)
  );
}

}

template <typename F1, typename F2>
inline auto operator|(F1&& f1, F2&& f2) noexcept(
  noexcept(
    compose(
      ::std::forward<F1>(f1), extract_signature(f1),
      ::std::forward<F2>(f2), extract_signature(f2)
    )
  )
)
{
  return compose(
    ::std::forward<F1>(f1), extract_signature(f1),
    ::std::forward<F2>(f2), extract_signature(f2)
  );
}

#endif // COMPOSE_HPP
<commit_msg>some fixes<commit_after>#ifndef COMPOSE_HPP
# define COMPOSE_HPP
# pragma once

#include <type_traits>

#include <utility>

namespace
{

template <typename R, typename ...A>
struct signature
{
};

template <typename R, typename ...A>
constexpr auto extract_signature(R (*const)(A...)) noexcept
{
  return signature<R, A...>();
}

template <typename C, typename R, typename ...A>
constexpr auto extract_signature(R (C::* const)(A...)) noexcept
{
  return signature<R, A...>();
}

template <typename C, typename R, typename ...A>
constexpr auto extract_signature(R (C::* const)(A...) const) noexcept
{
  return signature<R, A...>();
}

template <typename F>
constexpr auto extract_signature(F const&) noexcept ->
  decltype(&F::operator(), extract_signature(&F::operator()))
{
  return extract_signature(&F::operator());
}

template <typename F1, typename F2, bool, typename ...A1>
class composer;

template <typename F1, typename F2, typename ...A1>
class composer<F1, F2, true, A1...>
{
  F1 const f1_;
  F2 const f2_;

public:
  explicit composer(F1&& f1, F2&& f2) noexcept :
    f1_(std::forward<F1>(f1)),
    f2_(std::forward<F2>(f2))
  {
  }

  auto operator()(A1&& ...args) const noexcept(
    noexcept(f2_(f1_(std::forward<A1>(args)...)))
  )
  {
    return f2_(f1_(std::forward<A1>(args)...));
  }
};

template <typename F1, typename F2, typename ...A1>
class composer<F1, F2, false, A1...>
{
  F1 const f1_;
  F2 const f2_;

public:
  explicit composer(F1&& f1, F2&& f2) noexcept :
    f1_(std::forward<F1>(f1)),
    f2_(std::forward<F2>(f2))
  {
  }

  auto operator()(A1&& ...args) const noexcept(
    noexcept(f1_(std::forward<A1>(args)...), f2_())
  )
  {
    return f1_(std::forward<A1>(args)...), f2_();
  }
};

template <
  typename F1, typename R1, typename ...A1,
  typename F2, typename R2, typename ...A2
>
inline auto compose(
  F1&& f1, signature<R1, A1...> const,
  F2&& f2, signature<R2, A2...> const) noexcept(
  noexcept(
    composer<F1, F2, sizeof...(A2), A1...>(std::forward<F1>(f1),
      std::forward<F2>(f2)
    )
  )
)
{
  return composer<F1, F2, sizeof...(A2), A1...>(std::forward<F1>(f1),
    std::forward<F2>(f2)
  );
}

}

template <typename F1, typename F2>
inline auto operator|(F1&& f1, F2&& f2) noexcept(
  noexcept(
    compose(
      std::forward<F1>(f1), extract_signature(f1),
      std::forward<F2>(f2), extract_signature(f2)
    )
  )
)
{
  return compose(
    std::forward<F1>(f1), extract_signature(f1),
    std::forward<F2>(f2), extract_signature(f2)
  );
}

#endif // COMPOSE_HPP
<|endoftext|>


<commit_before>namespace factor {

template <typename Type> struct data_root : public tagged<Type> {
  factor_vm* parent;

  void push() {
    parent->data_roots.push_back(&this->value_);
  }

  data_root(cell value, factor_vm* parent)
      : tagged<Type>(value), parent(parent) {
    push();
  }

  data_root(Type* value, factor_vm* parent)
      : tagged<Type>(value), parent(parent) {
    push();
  }

  const data_root<Type>& operator=(const Type* x) {
    tagged<Type>::operator=(x);
    return *this;
  }
  const data_root<Type>& operator=(const cell& x) {
    tagged<Type>::operator=(x);
    return *this;
  }

  ~data_root() { parent->data_roots.pop_back(); }
};

/* A similar hack for the bignum implementation */
struct gc_bignum {
  bignum** addr;
  factor_vm* parent;

  gc_bignum(bignum** addr, factor_vm* parent) : addr(addr), parent(parent) {
    /* Don't bother with variables holding NULL pointers. */
    if (*addr) {
      parent->check_data_pointer(*addr);
      parent->bignum_roots.push_back(addr);
    }
  }

  ~gc_bignum() {
    if (*addr) {
      FACTOR_ASSERT(parent->bignum_roots.back() == addr);
      parent->bignum_roots.pop_back();
    }
  }
};

#define GC_BIGNUM(x) gc_bignum x##__data_root(&x, this)

}
<commit_msg>VM: the copy assignment operator is overloaded so you need a custom swap<commit_after>namespace factor {

template <typename Type> struct data_root : public tagged<Type> {
  factor_vm* parent;

  void push() {
    parent->data_roots.push_back(&this->value_);
  }

  data_root(cell value, factor_vm* parent)
      : tagged<Type>(value), parent(parent) {
    push();
  }

  data_root(Type* value, factor_vm* parent)
      : tagged<Type>(value), parent(parent) {
    push();
  }

  const data_root<Type>& operator=(const Type* x) {
    tagged<Type>::operator=(x);
    return *this;
  }
  const data_root<Type>& operator=(const cell& x) {
    tagged<Type>::operator=(x);
    return *this;
  }

  ~data_root() {
    parent->data_roots.pop_back();
  }

  friend void swap(data_root<Type>& a, data_root<Type>& b) {
    cell tmp = a.value_;
    a.value_ = b.value_;
    b.value_ = tmp;
  }
};

/* A similar hack for the bignum implementation */
struct gc_bignum {
  bignum** addr;
  factor_vm* parent;

  gc_bignum(bignum** addr, factor_vm* parent) : addr(addr), parent(parent) {
    /* Don't bother with variables holding NULL pointers. */
    if (*addr) {
      parent->check_data_pointer(*addr);
      parent->bignum_roots.push_back(addr);
    }
  }

  ~gc_bignum() {
    if (*addr) {
      FACTOR_ASSERT(parent->bignum_roots.back() == addr);
      parent->bignum_roots.pop_back();
    }
  }
};

#define GC_BIGNUM(x) gc_bignum x##__data_root(&x, this)

}
<|endoftext|>


<commit_before>#ifndef RBX_GC_MANAGED_THREAD
#define RBX_GC_MANAGED_THREAD

#include "gc/slab.hpp"
#include "gc/variable_buffer.hpp"
#include "gc/root_buffer.hpp"
#include "gc/root.hpp"
#include "lock.hpp"

#include <vector>

namespace rubinius {
  class SharedState;
  class VM;
  class WorldState;

  typedef std::vector<ObjectHeader*> LockedObjects;

  class ManagedThread : public Lockable {
  public:
    // WorldState sets the run_state_ directly.
    friend class WorldState;

    enum Kind {
      eRuby, eSystem
    };

    enum RunState {
      eRunning,     //< Normal state. Running accessing GC memory.
      eSuspended,   //< Waiting to be told to restart
      eIndependent, //< Off running code that doesn't access GC memory.
      eAlone        //< Suspended all other threads, alone to run.
    };

  private:
    SharedState& shared_;
    Roots roots_;
    std::string name_;
    VariableRootBuffers variable_root_buffers_;
    RootBuffers root_buffers_;
    LockedObjects locked_objects_;
    RunState run_state_;
    Kind kind_;

  protected:
    gc::Slab local_slab_;
    pthread_t os_thread_;
    uint32_t id_;

  public:
    ManagedThread(uint32_t id, SharedState& ss, Kind kind);

    Roots& roots() {
      return roots_;
    }

    VariableRootBuffers& variable_root_buffers() {
      return variable_root_buffers_;
    }

    RootBuffers& root_buffers() {
      return root_buffers_;
    }

    gc::Slab& local_slab() {
      return local_slab_;
    }

    LockedObjects& locked_objects() {
      return locked_objects_;
    }

    void add_locked_object(ObjectHeader* obj) {
      locked_objects_.push_back(obj);
    }

    void del_locked_object(ObjectHeader* obj) {
      // Often we will remove the last locked object
      // because how locks are used in a stack wise manner.
      // Therefore we optimize here for this case and have a fast path
      ObjectHeader* last = locked_objects_.back();
      if(obj == last) {
        locked_objects_.pop_back();
      } else {
        LockedObjects::iterator f = std::find(locked_objects_.begin(), locked_objects_.end(), obj);
        if(f != locked_objects_.end()) {
          locked_objects_.erase(f);
        }
      }
    }

    Kind kind() {
      return kind_;
    }

    VM* as_vm() {
      if(kind_ == eRuby) return reinterpret_cast<VM*>(this);
      return 0;
    }

    std::string name() {
      return name_;
    }

    void set_name(std::string name) {
      name_ = name;
    }

    uint32_t thread_id() {
      return id_;
    }

    pthread_t& os_thread() {
      return os_thread_;
    }

    void set_run_state(RunState s) {
      run_state_ = s;
    }

    RunState run_state() {
      return run_state_;
    }

  public:
    static ManagedThread* current();
    static void set_current(ManagedThread* vm, std::string name);
  };
}

#endif
<commit_msg>All hail C++ crypted error messages<commit_after>#ifndef RBX_GC_MANAGED_THREAD
#define RBX_GC_MANAGED_THREAD

#include "gc/slab.hpp"
#include "gc/variable_buffer.hpp"
#include "gc/root_buffer.hpp"
#include "gc/root.hpp"
#include "lock.hpp"

#include <algorithm>
#include <vector>

namespace rubinius {
  class SharedState;
  class VM;
  class WorldState;

  typedef std::vector<ObjectHeader*> LockedObjects;

  class ManagedThread : public Lockable {
  public:
    // WorldState sets the run_state_ directly.
    friend class WorldState;

    enum Kind {
      eRuby, eSystem
    };

    enum RunState {
      eRunning,     //< Normal state. Running accessing GC memory.
      eSuspended,   //< Waiting to be told to restart
      eIndependent, //< Off running code that doesn't access GC memory.
      eAlone        //< Suspended all other threads, alone to run.
    };

  private:
    SharedState& shared_;
    Roots roots_;
    std::string name_;
    VariableRootBuffers variable_root_buffers_;
    RootBuffers root_buffers_;
    LockedObjects locked_objects_;
    RunState run_state_;
    Kind kind_;

  protected:
    gc::Slab local_slab_;
    pthread_t os_thread_;
    uint32_t id_;

  public:
    ManagedThread(uint32_t id, SharedState& ss, Kind kind);

    Roots& roots() {
      return roots_;
    }

    VariableRootBuffers& variable_root_buffers() {
      return variable_root_buffers_;
    }

    RootBuffers& root_buffers() {
      return root_buffers_;
    }

    gc::Slab& local_slab() {
      return local_slab_;
    }

    LockedObjects& locked_objects() {
      return locked_objects_;
    }

    void add_locked_object(ObjectHeader* obj) {
      locked_objects_.push_back(obj);
    }

    void del_locked_object(ObjectHeader* obj) {
      // Often we will remove the last locked object
      // because how locks are used in a stack wise manner.
      // Therefore we optimize here for this case and have a fast path
      ObjectHeader* last = locked_objects_.back();
      if(obj == last) {
        locked_objects_.pop_back();
      } else {
        LockedObjects::iterator f = std::find(locked_objects_.begin(), locked_objects_.end(), obj);
        if(f != locked_objects_.end()) {
          locked_objects_.erase(f);
        }
      }
    }

    Kind kind() {
      return kind_;
    }

    VM* as_vm() {
      if(kind_ == eRuby) return reinterpret_cast<VM*>(this);
      return 0;
    }

    std::string name() {
      return name_;
    }

    void set_name(std::string name) {
      name_ = name;
    }

    uint32_t thread_id() {
      return id_;
    }

    pthread_t& os_thread() {
      return os_thread_;
    }

    void set_run_state(RunState s) {
      run_state_ = s;
    }

    RunState run_state() {
      return run_state_;
    }

  public:
    static ManagedThread* current();
    static void set_current(ManagedThread* vm, std::string name);
  };
}

#endif
<|endoftext|>


<commit_before>#include "master.hpp"

namespace factor {

HMODULE hFactorDll;

void factor_vm::init_ffi() {
  hFactorDll = GetModuleHandle(NULL);
  if (!hFactorDll)
    fatal_error("GetModuleHandle() failed", 0);
}

void factor_vm::ffi_dlopen(dll* dll) {
  dll->handle = LoadLibraryEx((WCHAR*)alien_offset(dll->path), NULL, 0);
}

void* factor_vm::ffi_dlsym(dll* dll, symbol_char* symbol) {
  return (void*)GetProcAddress(dll ? (HMODULE) dll->handle : hFactorDll,
                               symbol);
}

void* factor_vm::ffi_dlsym_raw(dll* dll, symbol_char* symbol) {
  return ffi_dlsym(dll, symbol);
}

void factor_vm::ffi_dlclose(dll* dll) {
  FreeLibrary((HMODULE) dll->handle);
  dll->handle = NULL;
}

BOOL factor_vm::windows_stat(vm_char* path) {
  BY_HANDLE_FILE_INFORMATION bhfi;
  HANDLE h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
                         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

  if (h == INVALID_HANDLE_VALUE) {
    // FindFirstFile is the only call that can stat c:\pagefile.sys
    WIN32_FIND_DATA st;
    HANDLE h;

    if (INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
      return false;
    FindClose(h);
    return true;
  }
  BOOL ret = GetFileInformationByHandle(h, &bhfi);
  CloseHandle(h);
  return ret;
}

void factor_vm::windows_image_path(vm_char* full_path, vm_char* temp_path,
                                   unsigned int length) {
  wcsncpy(temp_path, full_path, length - 1);
  size_t full_path_len = wcslen(full_path);
  if (full_path_len < length - 1)
    wcsncat(temp_path, L".image", length - full_path_len - 1);
  temp_path[length - 1] = 0;
}

/* You must free() this yourself. */
const vm_char* factor_vm::default_image_path() {
  vm_char full_path[MAX_UNICODE_PATH];
  vm_char* ptr;
  vm_char temp_path[MAX_UNICODE_PATH];

  if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
    fatal_error("GetModuleFileName() failed", 0);

  if ((ptr = wcsrchr(full_path, '.')))
    *ptr = 0;

  wcsncpy(temp_path, full_path, MAX_UNICODE_PATH - 1);
  size_t full_path_len = wcslen(full_path);
  if (full_path_len < MAX_UNICODE_PATH - 1)
    wcsncat(temp_path, L".image", MAX_UNICODE_PATH - full_path_len - 1);
  temp_path[MAX_UNICODE_PATH - 1] = 0;

  return safe_strdup(temp_path);
}

/* You must free() this yourself. */
const vm_char* factor_vm::vm_executable_path() {
  vm_char full_path[MAX_UNICODE_PATH];
  if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
    fatal_error("GetModuleFileName() failed", 0);
  return safe_strdup(full_path);
}

void factor_vm::primitive_existsp() {
  vm_char* path = untag_check<byte_array>(ctx->pop())->data<vm_char>();
  ctx->push(tag_boolean(windows_stat(path)));
}

segment::segment(cell size_, bool executable_p) {
  size = size_;

  char* mem;
  DWORD ignore;

  if ((mem = (char*)VirtualAlloc(
           NULL, getpagesize() * 2 + size, MEM_COMMIT,
           executable_p ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)) ==
      0)
    out_of_memory();

  if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
    fatal_error("Cannot allocate low guard page", (cell)mem);

  if (!VirtualProtect(mem + size + getpagesize(), getpagesize(), PAGE_NOACCESS,
                      &ignore))
    fatal_error("Cannot allocate high guard page", (cell)mem);

  start = (cell)mem + getpagesize();
  end = start + size;
}

segment::~segment() {
  SYSTEM_INFO si;
  GetSystemInfo(&si);
  if (!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE))
    fatal_error("Segment deallocation failed", 0);
}

long getpagesize() {
  static long g_pagesize = 0;
  if (!g_pagesize) {
    SYSTEM_INFO system_info;
    GetSystemInfo(&system_info);
    g_pagesize = system_info.dwPageSize;
  }
  return g_pagesize;
}

void code_heap::guard_safepoint() {
  DWORD ignore;
  if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_NOACCESS, &ignore))
    fatal_error("Cannot protect safepoint guard page", (cell)safepoint_page);
}

void code_heap::unguard_safepoint() {
  DWORD ignore;
  if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_READWRITE, &ignore))
    fatal_error("Cannot unprotect safepoint guard page", (cell)safepoint_page);
}

void factor_vm::move_file(const vm_char* path1, const vm_char* path2) {
  if (MoveFileEx((path1), (path2), MOVEFILE_REPLACE_EXISTING) == false)
    general_error(ERROR_IO, tag_fixnum(GetLastError()), false_object);
}

void factor_vm::init_signals() {}

THREADHANDLE start_thread(void* (*start_routine)(void*), void* args) {
  return (void*)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) start_routine,
                             args, 0, 0);
}

uint64_t nano_count() {
  static double scale_factor;

  static uint32_t hi = 0;
  static uint32_t lo = 0;

  LARGE_INTEGER count;
  BOOL ret = QueryPerformanceCounter(&count);
  if (ret == 0)
    fatal_error("QueryPerformanceCounter", 0);

  if (scale_factor == 0.0) {
    LARGE_INTEGER frequency;
    BOOL ret = QueryPerformanceFrequency(&frequency);
    if (ret == 0)
      fatal_error("QueryPerformanceFrequency", 0);
    scale_factor = (1000000000.0 / frequency.QuadPart);
  }

#ifdef FACTOR_64
  hi = count.HighPart;
#else
  /* On VirtualBox, QueryPerformanceCounter does not increment
	the high part every time the low part overflows.  Workaround. */
  if (lo > count.LowPart)
    hi++;
#endif
  lo = count.LowPart;

  return (uint64_t)((((uint64_t)hi << 32) | (uint64_t)lo) * scale_factor);
}

void sleep_nanos(uint64_t nsec) { Sleep((DWORD)(nsec / 1000000)); }

typedef enum _EXCEPTION_DISPOSITION {
  ExceptionContinueExecution = 0,
  ExceptionContinueSearch = 1,
  ExceptionNestedException = 2,
  ExceptionCollidedUnwind = 3
} EXCEPTION_DISPOSITION;

LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c,
                                  void* dispatch) {
  switch (e->ExceptionCode) {
    case EXCEPTION_ACCESS_VIOLATION:
      signal_fault_addr = e->ExceptionInformation[1];
      verify_memory_protection_error(signal_fault_addr);
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::memory_signal_handler_impl);
      break;

    case STATUS_FLOAT_DENORMAL_OPERAND:
    case STATUS_FLOAT_DIVIDE_BY_ZERO:
    case STATUS_FLOAT_INEXACT_RESULT:
    case STATUS_FLOAT_INVALID_OPERATION:
    case STATUS_FLOAT_OVERFLOW:
    case STATUS_FLOAT_STACK_CHECK:
    case STATUS_FLOAT_UNDERFLOW:
    case STATUS_FLOAT_MULTIPLE_FAULTS:
    case STATUS_FLOAT_MULTIPLE_TRAPS:
#ifdef FACTOR_64
      signal_fpu_status = fpu_status(MXCSR(c));
#else
      signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c));

      /* This seems to have no effect */
      X87SW(c) = 0;
#endif
      MXCSR(c) &= 0xffffffc0;
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::fp_signal_handler_impl);
      break;
    default:
      signal_number = e->ExceptionCode;
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::synchronous_signal_handler_impl);
      break;
  }

  return ExceptionContinueExecution;
}

VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c,
                                void* dispatch) {
  if (factor_vm::fatal_erroring_p)
    return ExceptionContinueSearch;

  factor_vm* vm = current_vm_p();
  if (vm)
    return vm->exception_handler(e, frame, c, dispatch);
  else
    return ExceptionContinueSearch;
}

/* On Unix SIGINT (ctrl-c) automatically interrupts blocking io system
   calls. It doesn't on Windows, so we need to manually send some
   cancellation requests to unblock the thread. */
VOID CALLBACK dummy_cb (ULONG_PTR dwParam) { }

// CancelSynchronousIo is not in Windows XP
#if _WIN32_WINNT >= 0x0600
static void wake_up_thread(HANDLE thread) {
  if (!CancelSynchronousIo(thread)) {
    DWORD err = GetLastError();
    /* CancelSynchronousIo() didn't find anything to cancel, let's try
       with QueueUserAPC() instead. */
    if (err == ERROR_NOT_FOUND) {
      if (!QueueUserAPC(&dummy_cb, thread, NULL)) {
        fatal_error("QueueUserAPC() failed", GetLastError());
      }
    } else {
      fatal_error("CancelSynchronousIo() failed", err);
    }
  }
}
#else
static void wake_up_thread(HANDLE thread) {}
#endif

static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) {
  switch (dwCtrlType) {
    case CTRL_C_EVENT: {
      /* The CtrlHandler runs in its own thread without stopping the main
         thread. Since in practice nobody uses the multi-VM stuff yet, we just
         grab the first VM we can get. This will not be a good idea when we
         actually support native threads. */
      FACTOR_ASSERT(thread_vms.size() == 1);
      factor_vm* vm = thread_vms.begin()->second;
      vm->safepoint.enqueue_fep(vm);

      /* Before leaving the ctrl_handler, try and wake up the main
         thread. */
      wake_up_thread(factor::boot_thread);
      return TRUE;
    }
    default:
      return FALSE;
  }
}

void factor_vm::open_console() { handle_ctrl_c(); }

void factor_vm::ignore_ctrl_c() {
  SetConsoleCtrlHandler(factor::ctrl_handler, FALSE);
}

void factor_vm::handle_ctrl_c() {
  SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);
}

void factor_vm::lock_console() {}

void factor_vm::unlock_console() {}

void factor_vm::close_console() {}

void factor_vm::sampler_thread_loop() {
  LARGE_INTEGER counter, new_counter, units_per_second;
  DWORD ok;

  ok = QueryPerformanceFrequency(&units_per_second);
  FACTOR_ASSERT(ok);

  ok = QueryPerformanceCounter(&counter);
  FACTOR_ASSERT(ok);

  counter.QuadPart *= samples_per_second;
  while (atomic::load(&sampling_profiler_p)) {
    SwitchToThread();
    ok = QueryPerformanceCounter(&new_counter);
    FACTOR_ASSERT(ok);
    new_counter.QuadPart *= samples_per_second;
    cell samples = 0;
    while (new_counter.QuadPart - counter.QuadPart >
           units_per_second.QuadPart) {
      ++samples;
      counter.QuadPart += units_per_second.QuadPart;
    }

    if (samples > 0) {
      DWORD suscount = SuspendThread(thread);
      FACTOR_ASSERT(suscount == 0);

      CONTEXT context;
      memset((void*)&context, 0, sizeof(CONTEXT));
      context.ContextFlags = CONTEXT_CONTROL;
      BOOL context_ok = GetThreadContext(thread, &context);
      FACTOR_ASSERT(context_ok);

      suscount = ResumeThread(thread);
      FACTOR_ASSERT(suscount == 1);

      safepoint.enqueue_samples(this, samples, context.EIP, false);
    }
  }
}

static DWORD WINAPI sampler_thread_entry(LPVOID parent_vm) {
  static_cast<factor_vm*>(parent_vm)->sampler_thread_loop();
  return 0;
}

void factor_vm::start_sampling_profiler_timer() {
  sampler_thread = CreateThread(NULL, 0, &sampler_thread_entry,
                                static_cast<LPVOID>(this), 0, NULL);
}

void factor_vm::end_sampling_profiler_timer() {
  atomic::store(&sampling_profiler_p, false);
  DWORD wait_result =
      WaitForSingleObject(sampler_thread, 3000 * (DWORD) samples_per_second);
  if (wait_result != WAIT_OBJECT_0)
    TerminateThread(sampler_thread, 0);
  sampler_thread = NULL;
}

void abort() { ::abort(); }

int THREADSAFE_STRERROR(int errnum, char *buf, size_t buflen) {
  return strerror_s(buf, buflen, errnum);
}
<commit_msg>vm: Fix namespace brace.<commit_after>#include "master.hpp"

namespace factor {

HMODULE hFactorDll;

void factor_vm::init_ffi() {
  hFactorDll = GetModuleHandle(NULL);
  if (!hFactorDll)
    fatal_error("GetModuleHandle() failed", 0);
}

void factor_vm::ffi_dlopen(dll* dll) {
  dll->handle = LoadLibraryEx((WCHAR*)alien_offset(dll->path), NULL, 0);
}

void* factor_vm::ffi_dlsym(dll* dll, symbol_char* symbol) {
  return (void*)GetProcAddress(dll ? (HMODULE) dll->handle : hFactorDll,
                               symbol);
}

void* factor_vm::ffi_dlsym_raw(dll* dll, symbol_char* symbol) {
  return ffi_dlsym(dll, symbol);
}

void factor_vm::ffi_dlclose(dll* dll) {
  FreeLibrary((HMODULE) dll->handle);
  dll->handle = NULL;
}

BOOL factor_vm::windows_stat(vm_char* path) {
  BY_HANDLE_FILE_INFORMATION bhfi;
  HANDLE h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
                         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

  if (h == INVALID_HANDLE_VALUE) {
    // FindFirstFile is the only call that can stat c:\pagefile.sys
    WIN32_FIND_DATA st;
    HANDLE h;

    if (INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
      return false;
    FindClose(h);
    return true;
  }
  BOOL ret = GetFileInformationByHandle(h, &bhfi);
  CloseHandle(h);
  return ret;
}

void factor_vm::windows_image_path(vm_char* full_path, vm_char* temp_path,
                                   unsigned int length) {
  wcsncpy(temp_path, full_path, length - 1);
  size_t full_path_len = wcslen(full_path);
  if (full_path_len < length - 1)
    wcsncat(temp_path, L".image", length - full_path_len - 1);
  temp_path[length - 1] = 0;
}

/* You must free() this yourself. */
const vm_char* factor_vm::default_image_path() {
  vm_char full_path[MAX_UNICODE_PATH];
  vm_char* ptr;
  vm_char temp_path[MAX_UNICODE_PATH];

  if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
    fatal_error("GetModuleFileName() failed", 0);

  if ((ptr = wcsrchr(full_path, '.')))
    *ptr = 0;

  wcsncpy(temp_path, full_path, MAX_UNICODE_PATH - 1);
  size_t full_path_len = wcslen(full_path);
  if (full_path_len < MAX_UNICODE_PATH - 1)
    wcsncat(temp_path, L".image", MAX_UNICODE_PATH - full_path_len - 1);
  temp_path[MAX_UNICODE_PATH - 1] = 0;

  return safe_strdup(temp_path);
}

/* You must free() this yourself. */
const vm_char* factor_vm::vm_executable_path() {
  vm_char full_path[MAX_UNICODE_PATH];
  if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
    fatal_error("GetModuleFileName() failed", 0);
  return safe_strdup(full_path);
}

void factor_vm::primitive_existsp() {
  vm_char* path = untag_check<byte_array>(ctx->pop())->data<vm_char>();
  ctx->push(tag_boolean(windows_stat(path)));
}

segment::segment(cell size_, bool executable_p) {
  size = size_;

  char* mem;
  DWORD ignore;

  if ((mem = (char*)VirtualAlloc(
           NULL, getpagesize() * 2 + size, MEM_COMMIT,
           executable_p ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)) ==
      0)
    out_of_memory();

  if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
    fatal_error("Cannot allocate low guard page", (cell)mem);

  if (!VirtualProtect(mem + size + getpagesize(), getpagesize(), PAGE_NOACCESS,
                      &ignore))
    fatal_error("Cannot allocate high guard page", (cell)mem);

  start = (cell)mem + getpagesize();
  end = start + size;
}

segment::~segment() {
  SYSTEM_INFO si;
  GetSystemInfo(&si);
  if (!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE))
    fatal_error("Segment deallocation failed", 0);
}

long getpagesize() {
  static long g_pagesize = 0;
  if (!g_pagesize) {
    SYSTEM_INFO system_info;
    GetSystemInfo(&system_info);
    g_pagesize = system_info.dwPageSize;
  }
  return g_pagesize;
}

void code_heap::guard_safepoint() {
  DWORD ignore;
  if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_NOACCESS, &ignore))
    fatal_error("Cannot protect safepoint guard page", (cell)safepoint_page);
}

void code_heap::unguard_safepoint() {
  DWORD ignore;
  if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_READWRITE, &ignore))
    fatal_error("Cannot unprotect safepoint guard page", (cell)safepoint_page);
}

void factor_vm::move_file(const vm_char* path1, const vm_char* path2) {
  if (MoveFileEx((path1), (path2), MOVEFILE_REPLACE_EXISTING) == false)
    general_error(ERROR_IO, tag_fixnum(GetLastError()), false_object);
}

void factor_vm::init_signals() {}

THREADHANDLE start_thread(void* (*start_routine)(void*), void* args) {
  return (void*)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) start_routine,
                             args, 0, 0);
}

uint64_t nano_count() {
  static double scale_factor;

  static uint32_t hi = 0;
  static uint32_t lo = 0;

  LARGE_INTEGER count;
  BOOL ret = QueryPerformanceCounter(&count);
  if (ret == 0)
    fatal_error("QueryPerformanceCounter", 0);

  if (scale_factor == 0.0) {
    LARGE_INTEGER frequency;
    BOOL ret = QueryPerformanceFrequency(&frequency);
    if (ret == 0)
      fatal_error("QueryPerformanceFrequency", 0);
    scale_factor = (1000000000.0 / frequency.QuadPart);
  }

#ifdef FACTOR_64
  hi = count.HighPart;
#else
  /* On VirtualBox, QueryPerformanceCounter does not increment
	the high part every time the low part overflows.  Workaround. */
  if (lo > count.LowPart)
    hi++;
#endif
  lo = count.LowPart;

  return (uint64_t)((((uint64_t)hi << 32) | (uint64_t)lo) * scale_factor);
}

void sleep_nanos(uint64_t nsec) { Sleep((DWORD)(nsec / 1000000)); }

typedef enum _EXCEPTION_DISPOSITION {
  ExceptionContinueExecution = 0,
  ExceptionContinueSearch = 1,
  ExceptionNestedException = 2,
  ExceptionCollidedUnwind = 3
} EXCEPTION_DISPOSITION;

LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c,
                                  void* dispatch) {
  switch (e->ExceptionCode) {
    case EXCEPTION_ACCESS_VIOLATION:
      signal_fault_addr = e->ExceptionInformation[1];
      verify_memory_protection_error(signal_fault_addr);
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::memory_signal_handler_impl);
      break;

    case STATUS_FLOAT_DENORMAL_OPERAND:
    case STATUS_FLOAT_DIVIDE_BY_ZERO:
    case STATUS_FLOAT_INEXACT_RESULT:
    case STATUS_FLOAT_INVALID_OPERATION:
    case STATUS_FLOAT_OVERFLOW:
    case STATUS_FLOAT_STACK_CHECK:
    case STATUS_FLOAT_UNDERFLOW:
    case STATUS_FLOAT_MULTIPLE_FAULTS:
    case STATUS_FLOAT_MULTIPLE_TRAPS:
#ifdef FACTOR_64
      signal_fpu_status = fpu_status(MXCSR(c));
#else
      signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c));

      /* This seems to have no effect */
      X87SW(c) = 0;
#endif
      MXCSR(c) &= 0xffffffc0;
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::fp_signal_handler_impl);
      break;
    default:
      signal_number = e->ExceptionCode;
      dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP,
                              (cell)factor::synchronous_signal_handler_impl);
      break;
  }

  return ExceptionContinueExecution;
}

VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c,
                                void* dispatch) {
  if (factor_vm::fatal_erroring_p)
    return ExceptionContinueSearch;

  factor_vm* vm = current_vm_p();
  if (vm)
    return vm->exception_handler(e, frame, c, dispatch);
  else
    return ExceptionContinueSearch;
}

/* On Unix SIGINT (ctrl-c) automatically interrupts blocking io system
   calls. It doesn't on Windows, so we need to manually send some
   cancellation requests to unblock the thread. */
VOID CALLBACK dummy_cb (ULONG_PTR dwParam) { }

// CancelSynchronousIo is not in Windows XP
#if _WIN32_WINNT >= 0x0600
static void wake_up_thread(HANDLE thread) {
  if (!CancelSynchronousIo(thread)) {
    DWORD err = GetLastError();
    /* CancelSynchronousIo() didn't find anything to cancel, let's try
       with QueueUserAPC() instead. */
    if (err == ERROR_NOT_FOUND) {
      if (!QueueUserAPC(&dummy_cb, thread, NULL)) {
        fatal_error("QueueUserAPC() failed", GetLastError());
      }
    } else {
      fatal_error("CancelSynchronousIo() failed", err);
    }
  }
}
#else
static void wake_up_thread(HANDLE thread) {}
#endif

static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) {
  switch (dwCtrlType) {
    case CTRL_C_EVENT: {
      /* The CtrlHandler runs in its own thread without stopping the main
         thread. Since in practice nobody uses the multi-VM stuff yet, we just
         grab the first VM we can get. This will not be a good idea when we
         actually support native threads. */
      FACTOR_ASSERT(thread_vms.size() == 1);
      factor_vm* vm = thread_vms.begin()->second;
      vm->safepoint.enqueue_fep(vm);

      /* Before leaving the ctrl_handler, try and wake up the main
         thread. */
      wake_up_thread(factor::boot_thread);
      return TRUE;
    }
    default:
      return FALSE;
  }
}

void factor_vm::open_console() { handle_ctrl_c(); }

void factor_vm::ignore_ctrl_c() {
  SetConsoleCtrlHandler(factor::ctrl_handler, FALSE);
}

void factor_vm::handle_ctrl_c() {
  SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);
}

void factor_vm::lock_console() {}

void factor_vm::unlock_console() {}

void factor_vm::close_console() {}

void factor_vm::sampler_thread_loop() {
  LARGE_INTEGER counter, new_counter, units_per_second;
  DWORD ok;

  ok = QueryPerformanceFrequency(&units_per_second);
  FACTOR_ASSERT(ok);

  ok = QueryPerformanceCounter(&counter);
  FACTOR_ASSERT(ok);

  counter.QuadPart *= samples_per_second;
  while (atomic::load(&sampling_profiler_p)) {
    SwitchToThread();
    ok = QueryPerformanceCounter(&new_counter);
    FACTOR_ASSERT(ok);
    new_counter.QuadPart *= samples_per_second;
    cell samples = 0;
    while (new_counter.QuadPart - counter.QuadPart >
           units_per_second.QuadPart) {
      ++samples;
      counter.QuadPart += units_per_second.QuadPart;
    }

    if (samples > 0) {
      DWORD suscount = SuspendThread(thread);
      FACTOR_ASSERT(suscount == 0);

      CONTEXT context;
      memset((void*)&context, 0, sizeof(CONTEXT));
      context.ContextFlags = CONTEXT_CONTROL;
      BOOL context_ok = GetThreadContext(thread, &context);
      FACTOR_ASSERT(context_ok);

      suscount = ResumeThread(thread);
      FACTOR_ASSERT(suscount == 1);

      safepoint.enqueue_samples(this, samples, context.EIP, false);
    }
  }
}

static DWORD WINAPI sampler_thread_entry(LPVOID parent_vm) {
  static_cast<factor_vm*>(parent_vm)->sampler_thread_loop();
  return 0;
}

void factor_vm::start_sampling_profiler_timer() {
  sampler_thread = CreateThread(NULL, 0, &sampler_thread_entry,
                                static_cast<LPVOID>(this), 0, NULL);
}

void factor_vm::end_sampling_profiler_timer() {
  atomic::store(&sampling_profiler_p, false);
  DWORD wait_result =
      WaitForSingleObject(sampler_thread, 3000 * (DWORD) samples_per_second);
  if (wait_result != WAIT_OBJECT_0)
    TerminateThread(sampler_thread, 0);
  sampler_thread = NULL;
}

void abort() { ::abort(); }

int THREADSAFE_STRERROR(int errnum, char *buf, size_t buflen) {
  return strerror_s(buf, buflen, errnum);
}

}
<|endoftext|>


<commit_before>class Solution {
public:
    /**
     *@param num: A list of non negative integers
     *@return: A string
     */

     static bool cmp_ab(int a,int b){
        string ab;
        string ba;
        stringstream ss;
        ss<<a<<b;
        ab=ss.str();
        ss.str("");

        ss<<b<<a;
        ba=ss.str();
        ss.str("");

        return ab>ba;
    }

    string largestNumber(vector<int> &num) {
        // write your code here

        sort(num.begin(), num.end(),cmp_ab);

        if (num[0]==0){
            return "0";
        }

        stringstream ss;
        for(int i=0;i<num.size();i++){
            ss<<num[i];
        }

        string res=ss.str();
        ss.str("");

        return res;
    }
};<commit_msg>Solved 184<commit_after>class Solution {
public:
    /**
     *@param num: A list of non negative integers
     *@return: A string
     */

     static bool cmp_ab(int a,int b){
        string ab;
        string ba;
        stringstream ss;
        ss<<a<<b;
        ab=ss.str();
        ss.str("");

        ss<<b<<a;
        ba=ss.str();
        ss.str("");

        return ab>ba;
    }

    string largestNumber(vector<int> &num) {
        // write your code here

        sort(num.begin(), num.end(),cmp_ab);

        if (num[0]==0){
            return "0";
        }

        stringstream ss;
        for(int i=0;i<num.size();i++){
            ss<<num[i];
        }

        string res=ss.str();
        ss.str("");

        return res;
    }
};

// Total Runtime: 22 ms<|endoftext|>


<commit_before>class Solution {
public:
    /**
     * @param digits a number represented as an array of digits
     * @return the result
     */
    vector<int> plusOne(vector<int>& digits) {
        // Write your code here
        int i,j,k,n=digits.size();
        int tmp,s_tmp,jw=0;
        std::vector<int> vRev(digits.rbegin(),digits.rend());
        for (auto  s:vRev){
        	cout<<s<<" ";
        	s_tmp=jw+s+1;
        	s=s_tmp%10;
        	jw=s_tmp/10;
        }
        if (jw>1) vRev.push_back(jw);

        std::vector<int> rt_v(vRev.rbegin(),vRev.rend());
        return rt_v;
    }
};<commit_msg>Fixed the bug<commit_after>class Solution {
public:
    /**
     * @param digits a number represented as an array of digits
     * @return the result
     */
    vector<int> plusOne(vector<int>& digits) {
        // Write your code here
        int i,j,k,n=digits.size();
        int tmp,s_tmp,jw=0;
        std::vector<int> vRev(digits.rbegin(),digits.rend());
        for (auto &s:vRev){
        	cout<<s<<" ";
        	s_tmp=jw+s+1;
        	s=s_tmp%10;
        	cout<<s<<";";
        	jw=s_tmp/10;
        }
        if (jw>1) vRev.push_back(jw);

        std::vector<int> rt_v(vRev.rbegin(),vRev.rend());
        return rt_v;
    }
};<|endoftext|>