<commit_before>// Copyright 2013 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 "content/browser/android/in_process/synchronous_compositor_output_surface.h"

#include "base/auto_reset.h"
#include "base/logging.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/android/in_process/synchronous_compositor_registry.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"

namespace content {

namespace {

// Do not limit number of resources, so use an unrealistically high value.
const size_t kNumResourcesLimit = 10 * 1000 * 1000;

} // namespace

class SynchronousCompositorOutputSurface::SoftwareDevice
  : public cc::SoftwareOutputDevice {
 public:
  SoftwareDevice(SynchronousCompositorOutputSurface* surface)
    : surface_(surface) {
  }
  void Resize(const gfx::Size& pixel_size, float scale_factor) override {
    // Intentional no-op: canvas size is controlled by the embedder.
  }
  SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
    if (!surface_->current_sw_canvas_) {
      NOTREACHED() << "BeginPaint with no canvas set";
      return &null_canvas_;
    }
    LOG_IF(WARNING, surface_->frame_holder_.get())
        << "Mutliple calls to BeginPaint per frame";
    return surface_->current_sw_canvas_;
  }
  void EndPaint(cc::SoftwareFrameData* frame_data) override {}

 private:
  SynchronousCompositorOutputSurface* surface_;
  SkCanvas null_canvas_;

  DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
};

SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
    const scoped_refptr<cc::ContextProvider>& context_provider,
    const scoped_refptr<cc::ContextProvider>& worker_context_provider,
    int routing_id,
    scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
    : cc::OutputSurface(
          context_provider,
          worker_context_provider,
          scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
      routing_id_(routing_id),
      registered_(false),
      current_sw_canvas_(nullptr),
      memory_policy_(0),
      frame_swap_message_queue_(frame_swap_message_queue) {
  capabilities_.draw_and_swap_full_viewport_every_frame = true;
  capabilities_.adjust_deadline_for_parent = false;
  capabilities_.delegated_rendering = true;
  capabilities_.max_frames_pending = 1;
  memory_policy_.priority_cutoff_when_visible =
      gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
}

SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
  DCHECK(CalledOnValidThread());
  if (registered_) {
    SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface(
        routing_id_, this);
  }
}

bool SynchronousCompositorOutputSurface::BindToClient(
    cc::OutputSurfaceClient* surface_client) {
  DCHECK(CalledOnValidThread());
  if (!cc::OutputSurface::BindToClient(surface_client))
    return false;

  client_->SetMemoryPolicy(memory_policy_);

  SynchronousCompositorRegistry::GetInstance()->RegisterOutputSurface(
      routing_id_, this);
  registered_ = true;

  return true;
}

void SynchronousCompositorOutputSurface::SetCompositor(
    SynchronousCompositorImpl* compositor) {
  DCHECK(CalledOnValidThread());
  compositor_ = compositor;
}

void SynchronousCompositorOutputSurface::Reshape(
    const gfx::Size& size, float scale_factor) {
  // Intentional no-op: surface size is controlled by the embedder.
}

void SynchronousCompositorOutputSurface::SwapBuffers(
    cc::CompositorFrame* frame) {
  DCHECK(CalledOnValidThread());

  frame_holder_.reset(new cc::CompositorFrame);
  frame->AssignTo(frame_holder_.get());

  client_->DidSwapBuffers();
}

void SynchronousCompositorOutputSurface::Invalidate() {
  DCHECK(CalledOnValidThread());
  compositor_->PostInvalidate();
}

namespace {
void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
  // CC's draw origin starts at the viewport.
  transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
}
} // namespace

scoped_ptr<cc::CompositorFrame>
SynchronousCompositorOutputSurface::DemandDrawHw(
    gfx::Size surface_size,
    const gfx::Transform& transform,
    gfx::Rect viewport,
    gfx::Rect clip,
    gfx::Rect viewport_rect_for_tile_priority,
    const gfx::Transform& transform_for_tile_priority) {
  DCHECK(CalledOnValidThread());
  DCHECK(HasClient());
  DCHECK(context_provider_.get());

  surface_size_ = surface_size;
  InvokeComposite(transform,
                  viewport,
                  clip,
                  viewport_rect_for_tile_priority,
                  transform_for_tile_priority,
                  true);

  return frame_holder_.Pass();
}

scoped_ptr<cc::CompositorFrame>
SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
  DCHECK(CalledOnValidThread());
  DCHECK(canvas);
  DCHECK(!current_sw_canvas_);

  base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);

  SkIRect canvas_clip;
  canvas->getClipDeviceBounds(&canvas_clip);
  gfx::Rect clip = gfx::SkIRectToRect(canvas_clip);

  gfx::Transform transform(gfx::Transform::kSkipInitialization);
  transform.matrix() = canvas->getTotalMatrix();  // Converts 3x3 matrix to 4x4.

  surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
                            canvas->getDeviceSize().height());

  // Pass in the cached hw viewport and transform for tile priority to avoid
  // tile thrashing when the WebView is alternating between hardware and
  // software draws.
  InvokeComposite(transform,
                  clip,
                  clip,
                  cached_hw_viewport_rect_for_tile_priority_,
                  cached_hw_transform_for_tile_priority_,
                  false);

  return frame_holder_.Pass();
}

void SynchronousCompositorOutputSurface::InvokeComposite(
    const gfx::Transform& transform,
    gfx::Rect viewport,
    gfx::Rect clip,
    gfx::Rect viewport_rect_for_tile_priority,
    gfx::Transform transform_for_tile_priority,
    bool hardware_draw) {
  DCHECK(!frame_holder_.get());

  gfx::Transform adjusted_transform = transform;
  AdjustTransform(&adjusted_transform, viewport);
  SetExternalDrawConstraints(adjusted_transform,
                             viewport,
                             clip,
                             viewport_rect_for_tile_priority,
                             transform_for_tile_priority,
                             !hardware_draw);
  SetNeedsRedrawRect(gfx::Rect(viewport.size()));

  client_->OnDraw();

  // After software draws (which might move the viewport arbitrarily), restore
  // the previous hardware viewport to allow CC's tile manager to prioritize
  // properly.
  if (hardware_draw) {
    cached_hw_transform_ = adjusted_transform;
    cached_hw_viewport_ = viewport;
    cached_hw_clip_ = clip;
    cached_hw_viewport_rect_for_tile_priority_ =
        viewport_rect_for_tile_priority;
    cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
  } else {
    bool resourceless_software_draw = false;
    SetExternalDrawConstraints(cached_hw_transform_,
                               cached_hw_viewport_,
                               cached_hw_clip_,
                               cached_hw_viewport_rect_for_tile_priority_,
                               cached_hw_transform_for_tile_priority_,
                               resourceless_software_draw);
  }

  if (frame_holder_.get())
    client_->DidSwapBuffersComplete();
}

void SynchronousCompositorOutputSurface::ReturnResources(
    const cc::CompositorFrameAck& frame_ack) {
  ReclaimResources(&frame_ack);
}

void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
  DCHECK(CalledOnValidThread());
  bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit;
  bool became_non_zero =
      !memory_policy_.bytes_limit_when_visible && bytes_limit;
  memory_policy_.bytes_limit_when_visible = bytes_limit;
  memory_policy_.num_resources_limit = kNumResourcesLimit;

  if (client_)
    client_->SetMemoryPolicy(memory_policy_);

  if (became_zero) {
    // This is small hack to drop context resources without destroying it
    // when this compositor is put into the background.
    context_provider()->ContextSupport()->SetSurfaceVisible(false);
  } else if (became_non_zero) {
    context_provider()->ContextSupport()->SetSurfaceVisible(true);
  }
}

void SynchronousCompositorOutputSurface::SetTreeActivationCallback(
    const base::Closure& callback) {
  DCHECK(client_);
  client_->SetTreeActivationCallback(callback);
}

void SynchronousCompositorOutputSurface::GetMessagesToDeliver(
    ScopedVector<IPC::Message>* messages) {
  DCHECK(CalledOnValidThread());
  scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
      frame_swap_message_queue_->AcquireSendMessageScope();
  frame_swap_message_queue_->DrainMessages(messages);
}

// Not using base::NonThreadSafe as we want to enforce a more exacting threading
// requirement: SynchronousCompositorOutputSurface() must only be used on the UI
// thread.
bool SynchronousCompositorOutputSurface::CalledOnValidThread() const {
  return BrowserThread::CurrentlyOn(BrowserThread::UI);
}

}  // namespace content
<commit_msg>branch 2403 fork: Drop gpu raster resources in android webview<commit_after>// Copyright 2013 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 "content/browser/android/in_process/synchronous_compositor_output_surface.h"

#include "base/auto_reset.h"
#include "base/logging.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/android/in_process/synchronous_compositor_registry.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"

namespace content {

namespace {

// Do not limit number of resources, so use an unrealistically high value.
const size_t kNumResourcesLimit = 10 * 1000 * 1000;

} // namespace

class SynchronousCompositorOutputSurface::SoftwareDevice
  : public cc::SoftwareOutputDevice {
 public:
  SoftwareDevice(SynchronousCompositorOutputSurface* surface)
    : surface_(surface) {
  }
  void Resize(const gfx::Size& pixel_size, float scale_factor) override {
    // Intentional no-op: canvas size is controlled by the embedder.
  }
  SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
    if (!surface_->current_sw_canvas_) {
      NOTREACHED() << "BeginPaint with no canvas set";
      return &null_canvas_;
    }
    LOG_IF(WARNING, surface_->frame_holder_.get())
        << "Mutliple calls to BeginPaint per frame";
    return surface_->current_sw_canvas_;
  }
  void EndPaint(cc::SoftwareFrameData* frame_data) override {}

 private:
  SynchronousCompositorOutputSurface* surface_;
  SkCanvas null_canvas_;

  DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
};

SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
    const scoped_refptr<cc::ContextProvider>& context_provider,
    const scoped_refptr<cc::ContextProvider>& worker_context_provider,
    int routing_id,
    scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
    : cc::OutputSurface(
          context_provider,
          worker_context_provider,
          scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
      routing_id_(routing_id),
      registered_(false),
      current_sw_canvas_(nullptr),
      memory_policy_(0),
      frame_swap_message_queue_(frame_swap_message_queue) {
  capabilities_.draw_and_swap_full_viewport_every_frame = true;
  capabilities_.adjust_deadline_for_parent = false;
  capabilities_.delegated_rendering = true;
  capabilities_.max_frames_pending = 1;
  memory_policy_.priority_cutoff_when_visible =
      gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
}

SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
  DCHECK(CalledOnValidThread());
  if (registered_) {
    SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface(
        routing_id_, this);
  }
}

bool SynchronousCompositorOutputSurface::BindToClient(
    cc::OutputSurfaceClient* surface_client) {
  DCHECK(CalledOnValidThread());
  if (!cc::OutputSurface::BindToClient(surface_client))
    return false;

  client_->SetMemoryPolicy(memory_policy_);

  SynchronousCompositorRegistry::GetInstance()->RegisterOutputSurface(
      routing_id_, this);
  registered_ = true;

  return true;
}

void SynchronousCompositorOutputSurface::SetCompositor(
    SynchronousCompositorImpl* compositor) {
  DCHECK(CalledOnValidThread());
  compositor_ = compositor;
}

void SynchronousCompositorOutputSurface::Reshape(
    const gfx::Size& size, float scale_factor) {
  // Intentional no-op: surface size is controlled by the embedder.
}

void SynchronousCompositorOutputSurface::SwapBuffers(
    cc::CompositorFrame* frame) {
  DCHECK(CalledOnValidThread());

  frame_holder_.reset(new cc::CompositorFrame);
  frame->AssignTo(frame_holder_.get());

  client_->DidSwapBuffers();
}

void SynchronousCompositorOutputSurface::Invalidate() {
  DCHECK(CalledOnValidThread());
  compositor_->PostInvalidate();
}

namespace {
void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
  // CC's draw origin starts at the viewport.
  transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
}
} // namespace

scoped_ptr<cc::CompositorFrame>
SynchronousCompositorOutputSurface::DemandDrawHw(
    gfx::Size surface_size,
    const gfx::Transform& transform,
    gfx::Rect viewport,
    gfx::Rect clip,
    gfx::Rect viewport_rect_for_tile_priority,
    const gfx::Transform& transform_for_tile_priority) {
  DCHECK(CalledOnValidThread());
  DCHECK(HasClient());
  DCHECK(context_provider_.get());

  surface_size_ = surface_size;
  InvokeComposite(transform,
                  viewport,
                  clip,
                  viewport_rect_for_tile_priority,
                  transform_for_tile_priority,
                  true);

  return frame_holder_.Pass();
}

scoped_ptr<cc::CompositorFrame>
SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
  DCHECK(CalledOnValidThread());
  DCHECK(canvas);
  DCHECK(!current_sw_canvas_);

  base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);

  SkIRect canvas_clip;
  canvas->getClipDeviceBounds(&canvas_clip);
  gfx::Rect clip = gfx::SkIRectToRect(canvas_clip);

  gfx::Transform transform(gfx::Transform::kSkipInitialization);
  transform.matrix() = canvas->getTotalMatrix();  // Converts 3x3 matrix to 4x4.

  surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
                            canvas->getDeviceSize().height());

  // Pass in the cached hw viewport and transform for tile priority to avoid
  // tile thrashing when the WebView is alternating between hardware and
  // software draws.
  InvokeComposite(transform,
                  clip,
                  clip,
                  cached_hw_viewport_rect_for_tile_priority_,
                  cached_hw_transform_for_tile_priority_,
                  false);

  return frame_holder_.Pass();
}

void SynchronousCompositorOutputSurface::InvokeComposite(
    const gfx::Transform& transform,
    gfx::Rect viewport,
    gfx::Rect clip,
    gfx::Rect viewport_rect_for_tile_priority,
    gfx::Transform transform_for_tile_priority,
    bool hardware_draw) {
  DCHECK(!frame_holder_.get());

  gfx::Transform adjusted_transform = transform;
  AdjustTransform(&adjusted_transform, viewport);
  SetExternalDrawConstraints(adjusted_transform,
                             viewport,
                             clip,
                             viewport_rect_for_tile_priority,
                             transform_for_tile_priority,
                             !hardware_draw);
  SetNeedsRedrawRect(gfx::Rect(viewport.size()));

  client_->OnDraw();

  // After software draws (which might move the viewport arbitrarily), restore
  // the previous hardware viewport to allow CC's tile manager to prioritize
  // properly.
  if (hardware_draw) {
    cached_hw_transform_ = adjusted_transform;
    cached_hw_viewport_ = viewport;
    cached_hw_clip_ = clip;
    cached_hw_viewport_rect_for_tile_priority_ =
        viewport_rect_for_tile_priority;
    cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
  } else {
    bool resourceless_software_draw = false;
    SetExternalDrawConstraints(cached_hw_transform_,
                               cached_hw_viewport_,
                               cached_hw_clip_,
                               cached_hw_viewport_rect_for_tile_priority_,
                               cached_hw_transform_for_tile_priority_,
                               resourceless_software_draw);
  }

  if (frame_holder_.get())
    client_->DidSwapBuffersComplete();
}

void SynchronousCompositorOutputSurface::ReturnResources(
    const cc::CompositorFrameAck& frame_ack) {
  ReclaimResources(&frame_ack);
}

void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
  DCHECK(CalledOnValidThread());
  bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit;
  bool became_non_zero =
      !memory_policy_.bytes_limit_when_visible && bytes_limit;
  memory_policy_.bytes_limit_when_visible = bytes_limit;
  memory_policy_.num_resources_limit = kNumResourcesLimit;

  if (client_)
    client_->SetMemoryPolicy(memory_policy_);

  if (became_zero) {
    // This is small hack to drop context resources without destroying it
    // when this compositor is put into the background.
    context_provider()->DeleteCachedResources();
    context_provider()->ContextSupport()->SetSurfaceVisible(false);

    cc::ContextProvider* context = worker_context_provider();
    base::AutoLock context_lock(*context->GetLock());
    context->DetachFromThread();
    context->DeleteCachedResources();
    context->ContextSupport()->SetSurfaceVisible(false);
    context->DetachFromThread();
  } else if (became_non_zero) {
    context_provider()->ContextSupport()->SetSurfaceVisible(true);

    cc::ContextProvider* context = worker_context_provider();
    base::AutoLock context_lock(*context->GetLock());
    context->DetachFromThread();
    context->ContextSupport()->SetSurfaceVisible(true);
    context->DetachFromThread();
  }
}

void SynchronousCompositorOutputSurface::SetTreeActivationCallback(
    const base::Closure& callback) {
  DCHECK(client_);
  client_->SetTreeActivationCallback(callback);
}

void SynchronousCompositorOutputSurface::GetMessagesToDeliver(
    ScopedVector<IPC::Message>* messages) {
  DCHECK(CalledOnValidThread());
  scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
      frame_swap_message_queue_->AcquireSendMessageScope();
  frame_swap_message_queue_->DrainMessages(messages);
}

// Not using base::NonThreadSafe as we want to enforce a more exacting threading
// requirement: SynchronousCompositorOutputSurface() must only be used on the UI
// thread.
bool SynchronousCompositorOutputSurface::CalledOnValidThread() const {
  return BrowserThread::CurrentlyOn(BrowserThread::UI);
}

}  // namespace content
<|endoftext|>


<commit_before>/*! \file
 *
 * \brief Storage of generic data via (key, value) pair (source for python functions)
 * \author Benjamin Pritchard (ben@bennyp.org)
 */

#include "bpmodule/datastore/PropertyMap.hpp"
#include "bpmodule/python_helper/Convert.hpp"
#include "bpmodule/tensor/Tensor.hpp"
#include "bpmodule/exception/PythonConvertException.hpp"

using bpmodule::python_helper::ConvertToCpp;
using bpmodule::python_helper::ConvertToPy;
using bpmodule::python_helper::ConvertToCpp;
using bpmodule::exception::PythonConvertException;

namespace bpmodule {
namespace datastore {

// construct from python list
PropertyMap::PropertyMap(const boost::python::list & olist)
{
    int optlen = boost::python::extract<int>(olist.attr("__len__")());

    for(int i = 0; i < optlen; i++)
    {
        std::string key("(unknown)");

        // make sure it's a tuple
        std::string cl = boost::python::extract<std::string>(olist[i].attr("__class__").attr("__name__"));

        if(cl != "tuple")
        {
            PythonConvertException ex("PropertyMap element is not a tuple", "PropertyMap", key, cl, "tuple");
            ex.AppendInfo({ {"element", std::to_string(i) } });
            throw ex;
        }

        // check the number of elements in the tuple
        int tuplelen = boost::python::extract<int>(olist[i].attr("__len__")());
        if(tuplelen != 2)
        {
            PythonConvertException ex("PropertyMap element is not a tuple of 2 elements", "PropertyMap", key, cl, "tuple");
            ex.AppendInfo({ {"element", std::to_string(i) }, {"length", std::to_string(tuplelen)} });
            throw ex;
        }

        // actually convert now
        try {
            key = ConvertToCpp<std::string>(olist[i][0]);
            Set_(key, PropPlaceholder_(olist[i][1]));
        }
        catch(PythonConvertException & ex) // should always be a PythonConvertException?
        {
            ex.AppendInfo({ {"location", "PropertyMap"}, {"key", key} });
            throw;
        }
    }
}

template<>
boost::python::object PropertyMap::GetCopy<>(const std::string & key) const
{
    // may throw
    std::string type = GetType(key);

    if(type == typeid(bool).name())
        return ConvertToPy(GetRef<bool>(key));

    else if(type == typeid(long).name())
        return ConvertToPy(GetRef<long>(key));

    else if(type == typeid(double).name())
        return ConvertToPy(GetRef<double>(key));

    else if(type == typeid(std::string).name())
        return ConvertToPy(GetRef<std::string>(key));

    else if(type == typeid(std::vector<long>).name())
        return ConvertToPy(GetRef<std::vector<long>>(key));

    else if(type == typeid(std::vector<double>).name())
        return ConvertToPy(GetRef<std::vector<double>>(key));

    else if(type == typeid(std::vector<std::string>).name())
        return ConvertToPy(GetRef<std::vector<std::string>>(key));

    else if(type == typeid(tensor::Tensor).name())
        return ConvertToPy(GetRef<tensor::Tensor>(key));
    else
        throw PythonConvertException("Invalid type to convert to python",
                                     "PropertyMap", key, type, "boost::python::object", "in GetCopy<>");
}

template<>
void PropertyMap::Set(const std::string & key, const boost::python::object & value)
{
    // catch errors from conversions in PropPlaceholder_
    try {
        Set_(key, PropPlaceholder_(value));
    }
    catch(PythonConvertException & ex)
    {
        // append key info
        ex.AppendInfo({ {"key", key} });
        throw;
    }
}

PropertyMap::PropPlaceholderPtr PropertyMap::PropertyMap::PropPlaceholder_(const boost::python::object & value)
{
    std::string cl = boost::python::extract<std::string>(value.attr("__class__").attr("__name__"));
    if(cl == "bool")
        return PropPlaceholderPtr(new PropHolder<bool>(ConvertToCpp<bool>(value)));
    else if(cl == "int")
        return PropPlaceholderPtr(new PropHolder<long>(ConvertToCpp<long>(value)));
    else if(cl == "float")
        return PropPlaceholderPtr(new PropHolder<double>(ConvertToCpp<double>(value)));
    else if(cl == "str")
        return PropPlaceholderPtr(new PropHolder<std::string>(ConvertToCpp<std::string>(value)));
    else if(cl == "list")
    {
        // get type of first element
        boost::python::list lst = boost::python::extract<boost::python::list>(value);
        int length = boost::python::extract<int>(lst.attr("__len__")());
        if(length == 0)
            throw PythonConvertException("Empty list passed from python", "PropertyMap", "(none)", "(none)");

        std::string cl2 = boost::python::extract<std::string>(lst[0].attr("__class__").attr("__name__"));

        // check if this is a homogeneous container
        for(int i = 1; i < length; i++)
        {
            std::string cltmp = boost::python::extract<std::string>(lst[i].attr("__class__").attr("__name__"));
            if(cl2 != cltmp)
                throw PythonConvertException("Cannot convert heterogeneous container", cltmp, cl2);
        }

        // now parse list
        if(cl2 == "bool")
            return PropPlaceholderPtr(new PropHolder<std::vector<bool>>(ConvertToCpp<std::vector<bool>>(lst)));
        if(cl2 == "int")
            return PropPlaceholderPtr(new PropHolder<std::vector<long>>(ConvertToCpp<std::vector<long>>(lst)));
        else if(cl2 == "float")
            return PropPlaceholderPtr(new PropHolder<std::vector<double>>(ConvertToCpp<std::vector<double>>(lst)));
        else if(cl2 == "str")
            return PropPlaceholderPtr(new PropHolder<std::vector<std::string>>(ConvertToCpp<std::vector<std::string>>(lst)));
        else
        {
        throw PythonConvertException("Invalid type to convert from python",
                                     "PropertyMap", "(see below)", cl2, "boost::python::object", "In converting a list");
        }
    }
    else
    {
        throw PythonConvertException("Invalid type to convert from python",
                                     "PropertyMap", "(see below)", cl, "boost::python::object");
    }
}

} // close namespace datastore
} // close namespace bpmodule

<commit_msg>Small cleanup<commit_after>/*! \file
 *
 * \brief Storage of generic data via (key, value) pair (source for python functions)
 * \author Benjamin Pritchard (ben@bennyp.org)
 */

#include "bpmodule/datastore/PropertyMap.hpp"
#include "bpmodule/python_helper/Convert.hpp"
#include "bpmodule/tensor/Tensor.hpp"
#include "bpmodule/exception/PythonConvertException.hpp"

using bpmodule::python_helper::ConvertToCpp;
using bpmodule::python_helper::ConvertToPy;
using bpmodule::python_helper::ConvertToCpp;
using bpmodule::exception::PythonConvertException;

namespace bpmodule {
namespace datastore {

// construct from python list
PropertyMap::PropertyMap(const boost::python::list & olist)
{
    int optlen = boost::python::extract<int>(olist.attr("__len__")());

    for(int i = 0; i < optlen; i++)
    {
        std::string key("(unknown)");

        // make sure it's a tuple
        std::string cl = boost::python::extract<std::string>(olist[i].attr("__class__").attr("__name__"));

        if(cl != "tuple")
        {
            PythonConvertException ex("PropertyMap element is not a tuple", "PropertyMap", key, cl, "tuple");
            ex.AppendInfo({ {"element", std::to_string(i) } });
            throw ex;
        }

        // check the number of elements in the tuple
        int tuplelen = boost::python::extract<int>(olist[i].attr("__len__")());
        if(tuplelen != 2)
        {
            PythonConvertException ex("PropertyMap element is not a tuple of 2 elements", "PropertyMap", key, cl, "tuple");
            ex.AppendInfo({ {"element", std::to_string(i) }, {"length", std::to_string(tuplelen)} });
            throw ex;
        }

        // actually convert now
        try {
            key = ConvertToCpp<std::string>(olist[i][0]);
            Set_(key, PropPlaceholder_(olist[i][1]));
        }
        catch(PythonConvertException & ex) // should always be a PythonConvertException?
        {
            ex.AppendInfo({ {"location", "PropertyMap"}, {"key", key} });
            throw;
        }
    }
}

template<>
boost::python::object PropertyMap::GetCopy<>(const std::string & key) const
{
    // may throw
    std::string type = GetType(key);

    if(type == typeid(bool).name())
        return ConvertToPy(GetRef<bool>(key));

    else if(type == typeid(long).name())
        return ConvertToPy(GetRef<long>(key));

    else if(type == typeid(double).name())
        return ConvertToPy(GetRef<double>(key));

    else if(type == typeid(std::string).name())
        return ConvertToPy(GetRef<std::string>(key));

    else if(type == typeid(std::vector<long>).name())
        return ConvertToPy(GetRef<std::vector<long>>(key));

    else if(type == typeid(std::vector<double>).name())
        return ConvertToPy(GetRef<std::vector<double>>(key));

    else if(type == typeid(std::vector<std::string>).name())
        return ConvertToPy(GetRef<std::vector<std::string>>(key));

    else if(type == typeid(tensor::Tensor).name())
        return ConvertToPy(GetRef<tensor::Tensor>(key));
    else
        throw PythonConvertException("Invalid type to convert to python",
                                     "PropertyMap", key, type, "boost::python::object", "in GetCopy<>");
}

template<>
void PropertyMap::Set(const std::string & key, const boost::python::object & value)
{
    // catch errors from conversions in PropPlaceholder_
    try {
        Set_(key, PropPlaceholder_(value));
    }
    catch(PythonConvertException & ex)
    {
        // append key info
        ex.AppendInfo({ {"key", key} });
        throw;
    }
}

PropertyMap::PropPlaceholderPtr PropertyMap::PropertyMap::PropPlaceholder_(const boost::python::object & value)
{
    std::string cl = boost::python::extract<std::string>(value.attr("__class__").attr("__name__"));
    if(cl == "bool")
        return PropPlaceholderPtr(new PropHolder<bool>(ConvertToCpp<bool>(value)));
    else if(cl == "int")
        return PropPlaceholderPtr(new PropHolder<long>(ConvertToCpp<long>(value)));
    else if(cl == "float")
        return PropPlaceholderPtr(new PropHolder<double>(ConvertToCpp<double>(value)));
    else if(cl == "str")
        return PropPlaceholderPtr(new PropHolder<std::string>(ConvertToCpp<std::string>(value)));
    else if(cl == "list")
    {
        // get type of first element
        boost::python::list lst = boost::python::extract<boost::python::list>(value);
        int length = boost::python::extract<int>(lst.attr("__len__")());
        if(length == 0)
            throw PythonConvertException("Empty list passed from python", "PropertyMap", "(none)", "(none)");

        std::string cl2 = boost::python::extract<std::string>(lst[0].attr("__class__").attr("__name__"));

        // check if this is a homogeneous container
        for(int i = 1; i < length; i++)
        {
            std::string cltmp = boost::python::extract<std::string>(lst[i].attr("__class__").attr("__name__"));
            if(cl2 != cltmp)
                throw PythonConvertException("Cannot convert heterogeneous container", cltmp, cl2);
        }

        // now parse list
        if(cl2 == "bool")
            return PropPlaceholderPtr(new PropHolder<std::vector<bool>>(ConvertToCpp<std::vector<bool>>(lst)));
        if(cl2 == "int")
            return PropPlaceholderPtr(new PropHolder<std::vector<long>>(ConvertToCpp<std::vector<long>>(lst)));
        else if(cl2 == "float")
            return PropPlaceholderPtr(new PropHolder<std::vector<double>>(ConvertToCpp<std::vector<double>>(lst)));
        else if(cl2 == "str")
            return PropPlaceholderPtr(new PropHolder<std::vector<std::string>>(ConvertToCpp<std::vector<std::string>>(lst)));
        else
        {
            throw PythonConvertException("Invalid type to convert from python",
                                         "PropertyMap", "(see below)", cl2, "boost::python::object", "In converting a list");
        }
    }
    else
    {
        throw PythonConvertException("Invalid type to convert from python",
                                     "PropertyMap", "(see below)", cl, "boost::python::object");
    }
}

} // close namespace datastore
} // close namespace bpmodule

<|endoftext|>


<commit_before>/*===========================================================================*
 * This file is part of the Discrete Conic Optimization (DisCO) Solver.      *
 *                                                                           *
 * DisCO is distributed under the Eclipse Public License as part of the      *
 * COIN-OR repository (http://www.coin-or.org).                              *
 *                                                                           *
 * Authors:                                                                  *
 *          Aykut Bulut, Lehigh University                                   *
 *          Yan Xu, Lehigh University                                        *
 *          Ted Ralphs, Lehigh University                                    *
 *                                                                           *
 * Copyright (C) 2001-2018, Lehigh University, Aykut Bulut, Yan Xu, and      *
 * Ted Ralphs. All Rights Reserved.                                          *
 *===========================================================================*/

#include "DcoBranchObject.hpp"
#include "DcoMessage.hpp"

DcoBranchObject::DcoBranchObject(int index, double score, double value)
  : BcpsBranchObject(DcoBranchingObjectTypeInt, index, score, value) {
  ubDownBranch_ = floor(value);
  lbUpBranch_ = ceil(value);
}

/// Copy constructor.
DcoBranchObject::DcoBranchObject(DcoBranchObject const & other)
  : BcpsBranchObject(other) {
  ubDownBranch_ = other.ubDownBranch();
  lbUpBranch_ = other.lbUpBranch();
}

/// Helpful Copy constructor.
DcoBranchObject::DcoBranchObject(BcpsBranchObject const * other)
  : AlpsKnowledge(other->getType(), other->broker_),
    BcpsBranchObject(*other) {
  DcoBranchObject const * dco_other = dynamic_cast<DcoBranchObject const *>(other);
  if (dco_other==NULL) {
    std::cerr << "Fatal error!" << std::endl;
    throw std::exception();
  }
  ubDownBranch_ = dco_other->ubDownBranch();
  lbUpBranch_ = dco_other->lbUpBranch();
}

/// Copy assignment operator
DcoBranchObject & DcoBranchObject::operator=(DcoBranchObject const & rhs) {
  BcpsBranchObject::operator=(rhs);
  ubDownBranch_ = rhs.ubDownBranch();
  lbUpBranch_ = rhs.lbUpBranch();
  return *this;
}

DcoBranchObject::~DcoBranchObject() {
}

// BcpsBranchObject * DcoBranchObject::clone() const {
//   DcoModel * dco_model = dynamic_cast<DcoModel*> (model());
//   int index = getObjectIndex();
//   double up_score = getUpScore();
//   double down_score = getDownScore();
//   int direction = getDirection();
//   double value = getValue();
//   BcpsBranchObject * nbo = new DcoBranchObject(dco_model, index, up_score,
//                                                down_score, direction, value);
//   return nbo;
// }

// double DcoBranchObject::branch(bool normalBranch) {
//   DcoModel * model = dynamic_cast<DcoModel*> (model_);
//   int col_index = model->relaxedCols()[objectIndex_];
//   // Decrement number of branches left by 1.
//   --numBranchesLeft_;
//   if (direction_<0) {
//     model->solver()->setColUpper(col_index, ubDownBranch_);
//     direction_ = 1;
//   }
//   else {
//     model->solver()->setColLower(col_index, lbUpBranch_);
//     direction_ = -1;          // Swap direction
//   }
//   return 0.0;
// }

// bool DcoBranchObject::boundBranch() const {
//   // return True if branching fixes the bound.
//   // return True if variable we are branching is binary
//   return false;
// }

/// The number of branch arms created for this branch object.
int DcoBranchObject::numBranches() const {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1;
}

/// The number of branch arms left to be evaluated.
int DcoBranchObject::numBranchesLeft() const {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1;
}

/// Spit out a branch and, update this or superclass fields if necessary.
double DcoBranchObject::branch(bool normalBranch) {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1.0;
}

/// Encode the content of this into the given AlpsEncoded object.
AlpsReturnStatus DcoBranchObject::encode(AlpsEncoded * encoded) const {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  status = BcpsBranchObject::encode(encoded);
  assert(status==AlpsReturnStatusOk);
  encoded->writeRep(ubDownBranch_);
  encoded->writeRep(lbUpBranch_);
  return status;
}

/// Decode the given AlpsEncoded object into a new AlpsKnowledge object and
/// return a pointer to it.
AlpsKnowledge * DcoBranchObject::decode(AlpsEncoded & encoded) const {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  // create a new object with default values,
  // Bcps decode will decode right values into them.
  AlpsKnowledge * new_bo = new DcoBranchObject(-1, 0.0, 0.0);
  status = new_bo->decodeToSelf(encoded);
  assert(status=AlpsReturnStatusOk);
  return new_bo;;
}

/// Decode the given AlpsEncoded object into this.
AlpsReturnStatus DcoBranchObject::decodeToSelf(AlpsEncoded & encoded) {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  // decode Bcps part.
  status = BcpsBranchObject::decodeToSelf(encoded);
  assert(status=AlpsReturnStatusOk);
  // decode fields of DcoBranchObject
  encoded.readRep(ubDownBranch_);
  encoded.readRep(lbUpBranch_);
  return status;
}
<commit_msg>Remove redundant semicolon in DcoBranchObject.cpp.<commit_after>/*===========================================================================*
 * This file is part of the Discrete Conic Optimization (DisCO) Solver.      *
 *                                                                           *
 * DisCO is distributed under the Eclipse Public License as part of the      *
 * COIN-OR repository (http://www.coin-or.org).                              *
 *                                                                           *
 * Authors:                                                                  *
 *          Aykut Bulut, Lehigh University                                   *
 *          Yan Xu, Lehigh University                                        *
 *          Ted Ralphs, Lehigh University                                    *
 *                                                                           *
 * Copyright (C) 2001-2018, Lehigh University, Aykut Bulut, Yan Xu, and      *
 * Ted Ralphs. All Rights Reserved.                                          *
 *===========================================================================*/

#include "DcoBranchObject.hpp"
#include "DcoMessage.hpp"

DcoBranchObject::DcoBranchObject(int index, double score, double value)
  : BcpsBranchObject(DcoBranchingObjectTypeInt, index, score, value) {
  ubDownBranch_ = floor(value);
  lbUpBranch_ = ceil(value);
}

/// Copy constructor.
DcoBranchObject::DcoBranchObject(DcoBranchObject const & other)
  : BcpsBranchObject(other) {
  ubDownBranch_ = other.ubDownBranch();
  lbUpBranch_ = other.lbUpBranch();
}

/// Helpful Copy constructor.
DcoBranchObject::DcoBranchObject(BcpsBranchObject const * other)
  : AlpsKnowledge(other->getType(), other->broker_),
    BcpsBranchObject(*other) {
  DcoBranchObject const * dco_other = dynamic_cast<DcoBranchObject const *>(other);
  if (dco_other==NULL) {
    std::cerr << "Fatal error!" << std::endl;
    throw std::exception();
  }
  ubDownBranch_ = dco_other->ubDownBranch();
  lbUpBranch_ = dco_other->lbUpBranch();
}

/// Copy assignment operator
DcoBranchObject & DcoBranchObject::operator=(DcoBranchObject const & rhs) {
  BcpsBranchObject::operator=(rhs);
  ubDownBranch_ = rhs.ubDownBranch();
  lbUpBranch_ = rhs.lbUpBranch();
  return *this;
}

DcoBranchObject::~DcoBranchObject() {
}

// BcpsBranchObject * DcoBranchObject::clone() const {
//   DcoModel * dco_model = dynamic_cast<DcoModel*> (model());
//   int index = getObjectIndex();
//   double up_score = getUpScore();
//   double down_score = getDownScore();
//   int direction = getDirection();
//   double value = getValue();
//   BcpsBranchObject * nbo = new DcoBranchObject(dco_model, index, up_score,
//                                                down_score, direction, value);
//   return nbo;
// }

// double DcoBranchObject::branch(bool normalBranch) {
//   DcoModel * model = dynamic_cast<DcoModel*> (model_);
//   int col_index = model->relaxedCols()[objectIndex_];
//   // Decrement number of branches left by 1.
//   --numBranchesLeft_;
//   if (direction_<0) {
//     model->solver()->setColUpper(col_index, ubDownBranch_);
//     direction_ = 1;
//   }
//   else {
//     model->solver()->setColLower(col_index, lbUpBranch_);
//     direction_ = -1;          // Swap direction
//   }
//   return 0.0;
// }

// bool DcoBranchObject::boundBranch() const {
//   // return True if branching fixes the bound.
//   // return True if variable we are branching is binary
//   return false;
// }

/// The number of branch arms created for this branch object.
int DcoBranchObject::numBranches() const {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1;
}

/// The number of branch arms left to be evaluated.
int DcoBranchObject::numBranchesLeft() const {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1;
}

/// Spit out a branch and, update this or superclass fields if necessary.
double DcoBranchObject::branch(bool normalBranch) {
  DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  CoinMessages * messages = dco_model->dcoMessages_;
  message_handler->message(DISCO_NOT_IMPLEMENTED, *messages)
    << __FILE__ << __LINE__ << CoinMessageEol;
  return -1.0;
}

/// Encode the content of this into the given AlpsEncoded object.
AlpsReturnStatus DcoBranchObject::encode(AlpsEncoded * encoded) const {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  status = BcpsBranchObject::encode(encoded);
  assert(status==AlpsReturnStatusOk);
  encoded->writeRep(ubDownBranch_);
  encoded->writeRep(lbUpBranch_);
  return status;
}

/// Decode the given AlpsEncoded object into a new AlpsKnowledge object and
/// return a pointer to it.
AlpsKnowledge * DcoBranchObject::decode(AlpsEncoded & encoded) const {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  // create a new object with default values,
  // Bcps decode will decode right values into them.
  AlpsKnowledge * new_bo = new DcoBranchObject(-1, 0.0, 0.0);
  status = new_bo->decodeToSelf(encoded);
  assert(status=AlpsReturnStatusOk);
  return new_bo;
}

/// Decode the given AlpsEncoded object into this.
AlpsReturnStatus DcoBranchObject::decodeToSelf(AlpsEncoded & encoded) {
  // DcoModel * dco_model = dynamic_cast<DcoModel*>(broker_->getModel());
  // CoinMessageHandler * message_handler = dco_model->dcoMessageHandler_;
  // CoinMessages * messages = dco_model->dcoMessages_;
  AlpsReturnStatus status;
  // decode Bcps part.
  status = BcpsBranchObject::decodeToSelf(encoded);
  assert(status=AlpsReturnStatusOk);
  // decode fields of DcoBranchObject
  encoded.readRep(ubDownBranch_);
  encoded.readRep(lbUpBranch_);
  return status;
}
<|endoftext|>


<commit_before>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2008 Phusion
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "system_calls.hpp"
#include <boost/thread.hpp>
#include <cerrno>

using namespace boost;
using namespace oxt;

/*************************************
 * oxt
 *************************************/

static void
interruption_signal_handler(int sig) {
	// Do nothing.
}

void
oxt::setup_syscall_interruption_support() {
	struct sigaction action;
	int ret;

	action.sa_handler = interruption_signal_handler;
	action.sa_flags   = 0;
	sigemptyset(&action.sa_mask);
	do {
		ret = sigaction(INTERRUPTION_SIGNAL, &action, NULL);
	} while (ret == -1 && errno == EINTR);
	do {
		ret = siginterrupt(INTERRUPTION_SIGNAL, 1);
	} while (ret == -1 && errno == EINTR);
}

/*************************************
 * Passenger::syscalls
 *************************************/

#define CHECK_INTERRUPTION(error_expression, code) \
	do { \
		int _my_errno; \
		do { \
			code; \
			_my_errno = errno; \
		} while ((error_expression) && _my_errno == EINTR \
			&& !this_thread::syscalls_interruptable()); \
		if ((error_expression) && _my_errno == EINTR && this_thread::syscalls_interruptable()) { \
			throw thread_interrupted(); \
		} \
		errno = _my_errno; \
	} while (false)

ssize_t
syscalls::read(int fd, void *buf, size_t count) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::read(fd, buf, count)
	);
	return ret;
}

ssize_t
syscalls::write(int fd, const void *buf, size_t count) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::write(fd, buf, count)
	);
	return ret;
}

int
syscalls::close(int fd) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::close(fd)
	);
	return ret;
}

int
syscalls::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::accept(sockfd, addr, addrlen)
	);
	return ret;
}

int
syscalls::bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::bind(sockfd, addr, addrlen)
	);
	return ret;
}

int
syscalls::connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::connect(sockfd, serv_addr, addrlen);
	);
	return ret;
}

int
syscalls::listen(int sockfd, int backlog) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::listen(sockfd, backlog)
	);
	return ret;
}

int
syscalls::socket(int domain, int type, int protocol) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::socket(domain, type, protocol)
	);
	return ret;
}

int
syscalls::socketpair(int d, int type, int protocol, int sv[2]) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::socketpair(d, type, protocol, sv)
	);
	return ret;
}

ssize_t
syscalls::recvmsg(int s, struct msghdr *msg, int flags) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		#ifdef _AIX53
			ret = ::nrecvmsg(s, msg, flags)
		#else
			ret = ::recvmsg(s, msg, flags)
		#endif
	);
	return ret;
}

ssize_t
syscalls::sendmsg(int s, const struct msghdr *msg, int flags) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		#ifdef _AIX53
			ret = ::nsendmsg(s, msg, flags)
		#else
			ret = ::sendmsg(s, msg, flags)
		#endif
	);
	return ret;
}

int
syscalls::setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::setsockopt(s, level, optname, optval, optlen)
	);
	return ret;
}

int
syscalls::shutdown(int s, int how) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::shutdown(s, how)
	);
	return ret;
}

FILE *
syscalls::fopen(const char *path, const char *mode) {
	FILE *ret;
	CHECK_INTERRUPTION(
		ret == NULL,
		ret = ::fopen(path, mode)
	);
	return ret;
}

int
syscalls::fclose(FILE *fp) {
	int ret;
	CHECK_INTERRUPTION(
		ret == EOF,
		ret = ::fclose(fp)
	);
	return ret;
}

int
syscalls::unlink(const char *pathname) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::unlink(pathname)
	);
	return ret;
}

int
syscalls::stat(const char *path, struct stat *buf) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::stat(path, buf)
	);
	return ret;
}

time_t
syscalls::time(time_t *t) {
	time_t ret;
	CHECK_INTERRUPTION(
		ret == (time_t) -1,
		ret = ::time(t)
	);
	return ret;
}

int
syscalls::usleep(useconds_t usec) {
	struct timespec spec;
	spec.tv_sec = usec / 1000000;
	spec.tv_nsec = usec % 1000000;
	return syscalls::nanosleep(&spec, NULL);
}

int
syscalls::nanosleep(const struct timespec *req, struct timespec *rem) {
	struct timespec req2 = *req;
	struct timespec rem2;
	int ret, e;
	do {
		ret = ::nanosleep(&req2, &rem2);
		e = errno;
		req2 = rem2;
	} while (ret == -1 && e == EINTR && !this_thread::syscalls_interruptable());
	if (ret == -1 && e == EINTR && this_thread::syscalls_interruptable()) {
		throw thread_interrupted();
	}
	errno = e;
	if (ret == 0 && rem) {
		*rem = rem2;
	}
	return ret;
}

pid_t
syscalls::fork() {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::fork()
	);
	return ret;
}

int
syscalls::kill(pid_t pid, int sig) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::kill(pid, sig)
	);
	return ret;
}

pid_t
syscalls::waitpid(pid_t pid, int *status, int options) {
	pid_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::waitpid(pid, status, options)
	);
	return ret;
}

/*************************************
 * boost::this_thread
 *************************************/

thread_specific_ptr<bool> this_thread::_syscalls_interruptable;

bool
this_thread::syscalls_interruptable() {
	return _syscalls_interruptable.get() == NULL || *_syscalls_interruptable;
}

<commit_msg>Fix oxt::syscalls::usleep(): it doesn't sleep for the correct number of milliseconds.<commit_after>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2008 Phusion
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "system_calls.hpp"
#include <boost/thread.hpp>
#include <cerrno>

using namespace boost;
using namespace oxt;

/*************************************
 * oxt
 *************************************/

static void
interruption_signal_handler(int sig) {
	// Do nothing.
}

void
oxt::setup_syscall_interruption_support() {
	struct sigaction action;
	int ret;

	action.sa_handler = interruption_signal_handler;
	action.sa_flags   = 0;
	sigemptyset(&action.sa_mask);
	do {
		ret = sigaction(INTERRUPTION_SIGNAL, &action, NULL);
	} while (ret == -1 && errno == EINTR);
	do {
		ret = siginterrupt(INTERRUPTION_SIGNAL, 1);
	} while (ret == -1 && errno == EINTR);
}

/*************************************
 * Passenger::syscalls
 *************************************/

#define CHECK_INTERRUPTION(error_expression, code) \
	do { \
		int _my_errno; \
		do { \
			code; \
			_my_errno = errno; \
		} while ((error_expression) && _my_errno == EINTR \
			&& !this_thread::syscalls_interruptable()); \
		if ((error_expression) && _my_errno == EINTR && this_thread::syscalls_interruptable()) { \
			throw thread_interrupted(); \
		} \
		errno = _my_errno; \
	} while (false)

ssize_t
syscalls::read(int fd, void *buf, size_t count) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::read(fd, buf, count)
	);
	return ret;
}

ssize_t
syscalls::write(int fd, const void *buf, size_t count) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::write(fd, buf, count)
	);
	return ret;
}

int
syscalls::close(int fd) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::close(fd)
	);
	return ret;
}

int
syscalls::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::accept(sockfd, addr, addrlen)
	);
	return ret;
}

int
syscalls::bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::bind(sockfd, addr, addrlen)
	);
	return ret;
}

int
syscalls::connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::connect(sockfd, serv_addr, addrlen);
	);
	return ret;
}

int
syscalls::listen(int sockfd, int backlog) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::listen(sockfd, backlog)
	);
	return ret;
}

int
syscalls::socket(int domain, int type, int protocol) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::socket(domain, type, protocol)
	);
	return ret;
}

int
syscalls::socketpair(int d, int type, int protocol, int sv[2]) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::socketpair(d, type, protocol, sv)
	);
	return ret;
}

ssize_t
syscalls::recvmsg(int s, struct msghdr *msg, int flags) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		#ifdef _AIX53
			ret = ::nrecvmsg(s, msg, flags)
		#else
			ret = ::recvmsg(s, msg, flags)
		#endif
	);
	return ret;
}

ssize_t
syscalls::sendmsg(int s, const struct msghdr *msg, int flags) {
	ssize_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		#ifdef _AIX53
			ret = ::nsendmsg(s, msg, flags)
		#else
			ret = ::sendmsg(s, msg, flags)
		#endif
	);
	return ret;
}

int
syscalls::setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::setsockopt(s, level, optname, optval, optlen)
	);
	return ret;
}

int
syscalls::shutdown(int s, int how) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::shutdown(s, how)
	);
	return ret;
}

FILE *
syscalls::fopen(const char *path, const char *mode) {
	FILE *ret;
	CHECK_INTERRUPTION(
		ret == NULL,
		ret = ::fopen(path, mode)
	);
	return ret;
}

int
syscalls::fclose(FILE *fp) {
	int ret;
	CHECK_INTERRUPTION(
		ret == EOF,
		ret = ::fclose(fp)
	);
	return ret;
}

int
syscalls::unlink(const char *pathname) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::unlink(pathname)
	);
	return ret;
}

int
syscalls::stat(const char *path, struct stat *buf) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::stat(path, buf)
	);
	return ret;
}

time_t
syscalls::time(time_t *t) {
	time_t ret;
	CHECK_INTERRUPTION(
		ret == (time_t) -1,
		ret = ::time(t)
	);
	return ret;
}

int
syscalls::usleep(useconds_t usec) {
	// We use syscalls::nanosleep() here to reuse the code that sleeps
	// for the remaining amount of time, if a signal was received but
	// system call interruption is disabled.
	struct timespec spec;
	spec.tv_sec = usec / 1000000;
	spec.tv_nsec = usec % 1000000 * 1000;
	return syscalls::nanosleep(&spec, NULL);
}

int
syscalls::nanosleep(const struct timespec *req, struct timespec *rem) {
	struct timespec req2 = *req;
	struct timespec rem2;
	int ret, e;
	do {
		ret = ::nanosleep(&req2, &rem2);
		e = errno;
		req2 = rem2;
	} while (ret == -1 && e == EINTR && !this_thread::syscalls_interruptable());
	if (ret == -1 && e == EINTR && this_thread::syscalls_interruptable()) {
		throw thread_interrupted();
	}
	errno = e;
	if (ret == 0 && rem) {
		*rem = rem2;
	}
	return ret;
}

pid_t
syscalls::fork() {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::fork()
	);
	return ret;
}

int
syscalls::kill(pid_t pid, int sig) {
	int ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::kill(pid, sig)
	);
	return ret;
}

pid_t
syscalls::waitpid(pid_t pid, int *status, int options) {
	pid_t ret;
	CHECK_INTERRUPTION(
		ret == -1,
		ret = ::waitpid(pid, status, options)
	);
	return ret;
}

/*************************************
 * boost::this_thread
 *************************************/

thread_specific_ptr<bool> this_thread::_syscalls_interruptable;

bool
this_thread::syscalls_interruptable() {
	return _syscalls_interruptable.get() == NULL || *_syscalls_interruptable;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: warnbox.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: dr $ $Date: 2002-07-11 10:55:11 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_WARNBOX_HXX
#include "warnbox.hxx"
#endif

#include "scmod.hxx"
#include "inputopt.hxx"
#include "scresid.hxx"
#include "sc.hrc"

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

ScCbWarningBox::ScCbWarningBox( Window* pParent, const String& rMsgStr, bool bDefYes ) :
    WarningBox( pParent, WB_YES_NO | (bDefYes ? WB_DEF_YES : WB_DEF_NO), rMsgStr )
{
    SetDefaultCheckBoxText();
}

sal_Int16 ScCbWarningBox::Execute()
{
    sal_Int16 nRet = (GetStyle() & WB_DEF_YES) ? RET_YES : RET_NO;
    if( IsDialogEnabled() )
    {
        sal_Int16 nRet = WarningBox::Execute();
        if( GetCheckBoxState() )
            DisableDialog();
    }
    return nRet;
}

bool ScCbWarningBox::IsDialogEnabled()
{
    return true;
}

void ScCbWarningBox::DisableDialog()
{
}

// ----------------------------------------------------------------------------

ScReplaceWarnBox::ScReplaceWarnBox( Window* pParent ) :
    ScCbWarningBox( pParent, String( ScResId( STR_REPLCELLSWARN ) ), true )
{
}

bool ScReplaceWarnBox::IsDialogEnabled()
{
    return SC_MOD()->GetInputOptions().GetReplaceCellsWarn() == TRUE;
}

void ScReplaceWarnBox::DisableDialog()
{
    ScModule* pScMod = SC_MOD();
    ScInputOptions aInputOpt( pScMod->GetInputOptions() );
    aInputOpt.SetReplaceCellsWarn( FALSE );
    pScMod->SetInputOptions( aInputOpt );
}

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

<commit_msg>#101160# Execute: set the right return value<commit_after>/*************************************************************************
 *
 *  $RCSfile: warnbox.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: nn $ $Date: 2002-07-16 13:22:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_WARNBOX_HXX
#include "warnbox.hxx"
#endif

#include "scmod.hxx"
#include "inputopt.hxx"
#include "scresid.hxx"
#include "sc.hrc"

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

ScCbWarningBox::ScCbWarningBox( Window* pParent, const String& rMsgStr, bool bDefYes ) :
    WarningBox( pParent, WB_YES_NO | (bDefYes ? WB_DEF_YES : WB_DEF_NO), rMsgStr )
{
    SetDefaultCheckBoxText();
}

sal_Int16 ScCbWarningBox::Execute()
{
    sal_Int16 nRet = (GetStyle() & WB_DEF_YES) ? RET_YES : RET_NO;
    if( IsDialogEnabled() )
    {
        nRet = WarningBox::Execute();
        if( GetCheckBoxState() )
            DisableDialog();
    }
    return nRet;
}

bool ScCbWarningBox::IsDialogEnabled()
{
    return true;
}

void ScCbWarningBox::DisableDialog()
{
}

// ----------------------------------------------------------------------------

ScReplaceWarnBox::ScReplaceWarnBox( Window* pParent ) :
    ScCbWarningBox( pParent, String( ScResId( STR_REPLCELLSWARN ) ), true )
{
}

bool ScReplaceWarnBox::IsDialogEnabled()
{
    return SC_MOD()->GetInputOptions().GetReplaceCellsWarn() == TRUE;
}

void ScReplaceWarnBox::DisableDialog()
{
    ScModule* pScMod = SC_MOD();
    ScInputOptions aInputOpt( pScMod->GetInputOptions() );
    aInputOpt.SetReplaceCellsWarn( FALSE );
    pScMod->SetInputOptions( aInputOpt );
}

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

<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SetupMeshAction.h"
#include "MooseApp.h"
#include "MooseMesh.h"
#include "FileMesh.h"
#include "FEProblem.h"
#include "ActionWarehouse.h"
#include "Factory.h"

registerMooseAction("MooseApp", SetupMeshAction, "setup_mesh");
registerMooseAction("MooseApp", SetupMeshAction, "set_mesh_base");
registerMooseAction("MooseApp", SetupMeshAction, "init_mesh");

template <>
InputParameters
validParams<SetupMeshAction>()
{
  InputParameters params = validParams<MooseObjectAction>();

  // Here we are setting the default type of the mesh to construct to "FileMesh". This is to support
  // the very long-running legacy syntax where only a file parameter is required to determine the
  // type of the "Mesh" block. We are re-adding it though so that we can detect whether or not the
  // user has explicitly set the type in an input file. We do this because we want to support
  // automatically building a "MeshGeneratorMesh" type when MeshGenerators are added to the
  // simulation.
  params.addParam<std::string>(
      "type",
      "FileMesh",
      "A string representing the Moose Object that will be built by this Action");

  params.addParam<bool>("second_order",
                        false,
                        "Converts a first order mesh to a second order "
                        "mesh.  Note: This is NOT needed if you are reading "
                        "an actual first order mesh.");

  params.addParam<std::vector<SubdomainID>>("block_id", "IDs of the block id/name pairs");
  params.addParam<std::vector<SubdomainName>>(
      "block_name", "Names of the block id/name pairs (must correspond with \"block_id\"");

  params.addParam<std::vector<BoundaryID>>("boundary_id", "IDs of the boundary id/name pairs");
  params.addParam<std::vector<BoundaryName>>(
      "boundary_name", "Names of the boundary id/name pairs (must correspond with \"boundary_id\"");

  params.addParam<bool>("construct_side_list_from_node_list",
                        false,
                        "If true, construct side lists from the nodesets in the mesh (i.e. if "
                        "every node on a give side is in a nodeset then add that side to a "
                        "sideset");

  params.addParam<std::vector<std::string>>(
      "displacements",
      "The variables corresponding to the x y z displacements of the mesh.  If "
      "this is provided then the displacements will be taken into account during "
      "the computation. Creation of the displaced mesh can be suppressed even if "
      "this is set by setting 'use_displaced_mesh = false'.");
  params.addParam<bool>(
      "use_displaced_mesh",
      true,
      "Create the displaced mesh if the 'displacements' "
      "parameter is set. If this is 'false', a displaced mesh will not be created, "
      "regardless of whether 'displacements' is set.");
  params.addParam<std::vector<BoundaryName>>("ghosted_boundaries",
                                             "Boundaries to be ghosted if using Nemesis");
  params.addParam<std::vector<Real>>("ghosted_boundaries_inflation",
                                     "If you are using ghosted boundaries you will want to set "
                                     "this value to a vector of amounts to inflate the bounding "
                                     "boxes by.  ie if you are running a 3D problem you might set "
                                     "it to '0.2 0.1 0.4'");

  params.addParam<unsigned int>(
      "uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
  params.addParam<bool>("skip_partitioning",
                        false,
                        "If true the mesh won't be partitioned. This may cause large load "
                        "imbalanced but is currently required if you "
                        "have a simulation containing uniform refinement, adaptivity and stateful "
                        "material properties");

  // groups
  params.addParamNamesToGroup("displacements ghosted_boundaries ghosted_boundaries_inflation",
                              "Advanced");
  params.addParamNamesToGroup("second_order construct_side_list_from_node_list skip_partitioning",
                              "Advanced");
  params.addParamNamesToGroup("block_id block_name boundary_id boundary_name", "Add Names");

  return params;
}

SetupMeshAction::SetupMeshAction(InputParameters params) : MooseObjectAction(params) {}

void
SetupMeshAction::setupMesh(MooseMesh * mesh)
{
  std::vector<BoundaryName> ghosted_boundaries =
      getParam<std::vector<BoundaryName>>("ghosted_boundaries");

  for (const auto & bnd_name : ghosted_boundaries)
    mesh->addGhostedBoundary(mesh->getBoundaryID(bnd_name));

  if (isParamValid("ghosted_boundaries_inflation"))
  {
    std::vector<Real> ghosted_boundaries_inflation =
        getParam<std::vector<Real>>("ghosted_boundaries_inflation");
    mesh->setGhostedBoundaryInflation(ghosted_boundaries_inflation);
  }

  mesh->ghostGhostedBoundaries();

  if (getParam<bool>("second_order"))
    mesh->getMesh().all_second_order(true);

#ifdef LIBMESH_ENABLE_AMR
  unsigned int level = getParam<unsigned int>("uniform_refine");

  // Did they specify extra refinement levels on the command-line?
  level += _app.getParamTempl<unsigned int>("refinements");

  mesh->setUniformRefineLevel(level);
#endif // LIBMESH_ENABLE_AMR

  // Add entity names to the mesh
  if (_pars.isParamValid("block_id") && _pars.isParamValid("block_name"))
  {
    std::vector<SubdomainID> ids = getParam<std::vector<SubdomainID>>("block_id");
    std::vector<SubdomainName> names = getParam<std::vector<SubdomainName>>("block_name");
    std::set<SubdomainName> seen_it;

    if (ids.size() != names.size())
      mooseError("You must supply the same number of block ids and names parameters");

    for (unsigned int i = 0; i < ids.size(); ++i)
    {
      if (seen_it.find(names[i]) != seen_it.end())
        mooseError("The following dynamic block name is not unique: " + names[i]);
      seen_it.insert(names[i]);
      mesh->setSubdomainName(ids[i], names[i]);
    }
  }
  if (_pars.isParamValid("boundary_id") && _pars.isParamValid("boundary_name"))
  {
    std::vector<BoundaryID> ids = getParam<std::vector<BoundaryID>>("boundary_id");
    std::vector<BoundaryName> names = getParam<std::vector<BoundaryName>>("boundary_name");
    std::set<SubdomainName> seen_it;

    if (ids.size() != names.size())
      mooseError("You must supply the same number of boundary ids and names parameters");

    for (unsigned int i = 0; i < ids.size(); ++i)
    {
      if (seen_it.find(names[i]) != seen_it.end())
        mooseError("The following dynamic boundary name is not unique: " + names[i]);
      mesh->setBoundaryName(ids[i], names[i]);
      seen_it.insert(names[i]);
    }
  }

  if (getParam<bool>("construct_side_list_from_node_list"))
    mesh->getMesh().get_boundary_info().build_side_list_from_node_list();

  // Here we can override the partitioning for special cases
  if (getParam<bool>("skip_partitioning"))
    mesh->getMesh().skip_partitioning(getParam<bool>("skip_partitioning"));
}

std::string
SetupMeshAction::modifyParamsForUseSplit(InputParameters & moose_object_params) const
{
  auto split_file = _app.parameters().get<std::string>("split_file");

  // Get the split_file extension, if there is one, and use that to decide
  // between .cpr and .cpa
  std::string split_file_ext;
  auto pos = split_file.rfind(".");
  if (pos != std::string::npos)
    split_file_ext = split_file.substr(pos + 1, std::string::npos);

  // If split_file already has the .cpr or .cpa extension, we go with
  // that, otherwise we strip off the extension and append ".cpr".
  if (split_file != "" && split_file_ext != "cpr" && split_file_ext != "cpa")
    split_file = MooseUtils::stripExtension(split_file) + ".cpr";

  if (_type != "FileMesh")
  {
    if (split_file == "")
    {
      if (_app.processor_id() == 0)
        mooseError("Cannot use split mesh for a non-file mesh without specifying --split-file on "
                   "command line");
    }

    auto new_pars = validParams<FileMesh>();

    // Keep existing parameters where possible
    new_pars.applyParameters(_moose_object_pars);

    new_pars.set<MeshFileName>("file") = split_file;
    new_pars.set<MooseApp *>("_moose_app") = moose_object_params.get<MooseApp *>("_moose_app");
    moose_object_params = new_pars;
  }
  else
  {
    if (split_file != "")
      moose_object_params.set<MeshFileName>("file") = split_file;
    else
      moose_object_params.set<MeshFileName>("file") =
          MooseUtils::stripExtension(moose_object_params.get<MeshFileName>("file")) + ".cpr";
  }

  return "FileMesh";
}

void
SetupMeshAction::act()
{
  // Create the mesh object and tell it to build itself
  if (_current_task == "setup_mesh")
  {
    if (_app.masterMesh())
      _mesh = _app.masterMesh()->safeClone();
    else
    {
      // If the [Mesh] block contains mesh generators, change the default type to construct
      if (_awh.hasActions("add_mesh_generator"))
      {
        if (!_pars.isParamSetByUser("type"))
        {
          _type = "MeshGeneratorMesh";
          auto original_params = _moose_object_pars;
          _moose_object_pars = _factory.getValidParams("MeshGeneratorMesh");
          if (original_params.isParamSetByUser("parallel_type"))
            _moose_object_pars.applySpecificParameters(original_params, {"parallel_type"});
        }
        else if (!_moose_object_pars.get<bool>("_mesh_generator_mesh"))
        {
          mooseWarning("Mesh Generators present but the [Mesh] block is set to construct a \"",
                       _type,
                       "\" mesh, which does not use Mesh Generators in constructing the mesh.");
        }
      }

      // switch non-file meshes to be a file-mesh if using a pre-split mesh configuration.
      if (_app.isUseSplit())
        _type = modifyParamsForUseSplit(_moose_object_pars);

      _mesh = _factory.create<MooseMesh>(_type, "mesh", _moose_object_pars);
    }
  }

  else if (_current_task == "set_mesh_base")
  {
    if (!_app.masterMesh() && !_mesh->hasMeshBase())
    {
      if (_awh.hasActions("add_mesh_generator"))
        _mesh->setMeshBase(_app.getMeshGeneratorMesh());
      else
        _mesh->setMeshBase(_mesh->buildMeshBaseObject());
    }
  }

  else if (_current_task == "init_mesh")
  {
    if (_app.masterMesh())
    {
      if (_app.masterDisplacedMesh())
        _displaced_mesh = _app.masterDisplacedMesh()->safeClone();
    }
    else
    {
      _mesh->init();

      if (isParamValid("displacements") && getParam<bool>("use_displaced_mesh"))
      {
        _displaced_mesh = _mesh->safeClone();
        _displaced_mesh->getMesh().allow_remote_element_removal(
            _mesh->getMesh().allow_remote_element_removal());

        std::vector<std::string> displacements =
            getParam<std::vector<std::string>>("displacements");
        if (displacements.size() < _displaced_mesh->dimension())
          mooseError("Number of displacements must be greater than or equal to the dimension of "
                     "the mesh!");
      }

      setupMesh(_mesh.get());

      if (_displaced_mesh)
        setupMesh(_displaced_mesh.get());
    }
  }
}
<commit_msg>Perform a meaningful check for whether MeshGenerators are present<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SetupMeshAction.h"
#include "MooseApp.h"
#include "MooseMesh.h"
#include "FileMesh.h"
#include "FEProblem.h"
#include "ActionWarehouse.h"
#include "Factory.h"

registerMooseAction("MooseApp", SetupMeshAction, "setup_mesh");
registerMooseAction("MooseApp", SetupMeshAction, "set_mesh_base");
registerMooseAction("MooseApp", SetupMeshAction, "init_mesh");

template <>
InputParameters
validParams<SetupMeshAction>()
{
  InputParameters params = validParams<MooseObjectAction>();

  // Here we are setting the default type of the mesh to construct to "FileMesh". This is to support
  // the very long-running legacy syntax where only a file parameter is required to determine the
  // type of the "Mesh" block. We are re-adding it though so that we can detect whether or not the
  // user has explicitly set the type in an input file. We do this because we want to support
  // automatically building a "MeshGeneratorMesh" type when MeshGenerators are added to the
  // simulation.
  params.addParam<std::string>(
      "type",
      "FileMesh",
      "A string representing the Moose Object that will be built by this Action");

  params.addParam<bool>("second_order",
                        false,
                        "Converts a first order mesh to a second order "
                        "mesh.  Note: This is NOT needed if you are reading "
                        "an actual first order mesh.");

  params.addParam<std::vector<SubdomainID>>("block_id", "IDs of the block id/name pairs");
  params.addParam<std::vector<SubdomainName>>(
      "block_name", "Names of the block id/name pairs (must correspond with \"block_id\"");

  params.addParam<std::vector<BoundaryID>>("boundary_id", "IDs of the boundary id/name pairs");
  params.addParam<std::vector<BoundaryName>>(
      "boundary_name", "Names of the boundary id/name pairs (must correspond with \"boundary_id\"");

  params.addParam<bool>("construct_side_list_from_node_list",
                        false,
                        "If true, construct side lists from the nodesets in the mesh (i.e. if "
                        "every node on a give side is in a nodeset then add that side to a "
                        "sideset");

  params.addParam<std::vector<std::string>>(
      "displacements",
      "The variables corresponding to the x y z displacements of the mesh.  If "
      "this is provided then the displacements will be taken into account during "
      "the computation. Creation of the displaced mesh can be suppressed even if "
      "this is set by setting 'use_displaced_mesh = false'.");
  params.addParam<bool>(
      "use_displaced_mesh",
      true,
      "Create the displaced mesh if the 'displacements' "
      "parameter is set. If this is 'false', a displaced mesh will not be created, "
      "regardless of whether 'displacements' is set.");
  params.addParam<std::vector<BoundaryName>>("ghosted_boundaries",
                                             "Boundaries to be ghosted if using Nemesis");
  params.addParam<std::vector<Real>>("ghosted_boundaries_inflation",
                                     "If you are using ghosted boundaries you will want to set "
                                     "this value to a vector of amounts to inflate the bounding "
                                     "boxes by.  ie if you are running a 3D problem you might set "
                                     "it to '0.2 0.1 0.4'");

  params.addParam<unsigned int>(
      "uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
  params.addParam<bool>("skip_partitioning",
                        false,
                        "If true the mesh won't be partitioned. This may cause large load "
                        "imbalanced but is currently required if you "
                        "have a simulation containing uniform refinement, adaptivity and stateful "
                        "material properties");

  // groups
  params.addParamNamesToGroup("displacements ghosted_boundaries ghosted_boundaries_inflation",
                              "Advanced");
  params.addParamNamesToGroup("second_order construct_side_list_from_node_list skip_partitioning",
                              "Advanced");
  params.addParamNamesToGroup("block_id block_name boundary_id boundary_name", "Add Names");

  return params;
}

SetupMeshAction::SetupMeshAction(InputParameters params) : MooseObjectAction(params) {}

void
SetupMeshAction::setupMesh(MooseMesh * mesh)
{
  std::vector<BoundaryName> ghosted_boundaries =
      getParam<std::vector<BoundaryName>>("ghosted_boundaries");

  for (const auto & bnd_name : ghosted_boundaries)
    mesh->addGhostedBoundary(mesh->getBoundaryID(bnd_name));

  if (isParamValid("ghosted_boundaries_inflation"))
  {
    std::vector<Real> ghosted_boundaries_inflation =
        getParam<std::vector<Real>>("ghosted_boundaries_inflation");
    mesh->setGhostedBoundaryInflation(ghosted_boundaries_inflation);
  }

  mesh->ghostGhostedBoundaries();

  if (getParam<bool>("second_order"))
    mesh->getMesh().all_second_order(true);

#ifdef LIBMESH_ENABLE_AMR
  unsigned int level = getParam<unsigned int>("uniform_refine");

  // Did they specify extra refinement levels on the command-line?
  level += _app.getParamTempl<unsigned int>("refinements");

  mesh->setUniformRefineLevel(level);
#endif // LIBMESH_ENABLE_AMR

  // Add entity names to the mesh
  if (_pars.isParamValid("block_id") && _pars.isParamValid("block_name"))
  {
    std::vector<SubdomainID> ids = getParam<std::vector<SubdomainID>>("block_id");
    std::vector<SubdomainName> names = getParam<std::vector<SubdomainName>>("block_name");
    std::set<SubdomainName> seen_it;

    if (ids.size() != names.size())
      mooseError("You must supply the same number of block ids and names parameters");

    for (unsigned int i = 0; i < ids.size(); ++i)
    {
      if (seen_it.find(names[i]) != seen_it.end())
        mooseError("The following dynamic block name is not unique: " + names[i]);
      seen_it.insert(names[i]);
      mesh->setSubdomainName(ids[i], names[i]);
    }
  }
  if (_pars.isParamValid("boundary_id") && _pars.isParamValid("boundary_name"))
  {
    std::vector<BoundaryID> ids = getParam<std::vector<BoundaryID>>("boundary_id");
    std::vector<BoundaryName> names = getParam<std::vector<BoundaryName>>("boundary_name");
    std::set<SubdomainName> seen_it;

    if (ids.size() != names.size())
      mooseError("You must supply the same number of boundary ids and names parameters");

    for (unsigned int i = 0; i < ids.size(); ++i)
    {
      if (seen_it.find(names[i]) != seen_it.end())
        mooseError("The following dynamic boundary name is not unique: " + names[i]);
      mesh->setBoundaryName(ids[i], names[i]);
      seen_it.insert(names[i]);
    }
  }

  if (getParam<bool>("construct_side_list_from_node_list"))
    mesh->getMesh().get_boundary_info().build_side_list_from_node_list();

  // Here we can override the partitioning for special cases
  if (getParam<bool>("skip_partitioning"))
    mesh->getMesh().skip_partitioning(getParam<bool>("skip_partitioning"));
}

std::string
SetupMeshAction::modifyParamsForUseSplit(InputParameters & moose_object_params) const
{
  auto split_file = _app.parameters().get<std::string>("split_file");

  // Get the split_file extension, if there is one, and use that to decide
  // between .cpr and .cpa
  std::string split_file_ext;
  auto pos = split_file.rfind(".");
  if (pos != std::string::npos)
    split_file_ext = split_file.substr(pos + 1, std::string::npos);

  // If split_file already has the .cpr or .cpa extension, we go with
  // that, otherwise we strip off the extension and append ".cpr".
  if (split_file != "" && split_file_ext != "cpr" && split_file_ext != "cpa")
    split_file = MooseUtils::stripExtension(split_file) + ".cpr";

  if (_type != "FileMesh")
  {
    if (split_file == "")
    {
      if (_app.processor_id() == 0)
        mooseError("Cannot use split mesh for a non-file mesh without specifying --split-file on "
                   "command line");
    }

    auto new_pars = validParams<FileMesh>();

    // Keep existing parameters where possible
    new_pars.applyParameters(_moose_object_pars);

    new_pars.set<MeshFileName>("file") = split_file;
    new_pars.set<MooseApp *>("_moose_app") = moose_object_params.get<MooseApp *>("_moose_app");
    moose_object_params = new_pars;
  }
  else
  {
    if (split_file != "")
      moose_object_params.set<MeshFileName>("file") = split_file;
    else
      moose_object_params.set<MeshFileName>("file") =
          MooseUtils::stripExtension(moose_object_params.get<MeshFileName>("file")) + ".cpr";
  }

  return "FileMesh";
}

void
SetupMeshAction::act()
{
  // Create the mesh object and tell it to build itself
  if (_current_task == "setup_mesh")
  {
    if (_app.masterMesh())
      _mesh = _app.masterMesh()->safeClone();
    else
    {
      // If the [Mesh] block contains mesh generators, change the default type to construct
      if (!_awh.getActionListByName("add_mesh_generator").empty())
      {
        if (!_pars.isParamSetByUser("type"))
        {
          _type = "MeshGeneratorMesh";
          auto original_params = _moose_object_pars;
          _moose_object_pars = _factory.getValidParams("MeshGeneratorMesh");
          if (original_params.isParamSetByUser("parallel_type"))
            _moose_object_pars.applySpecificParameters(original_params, {"parallel_type"});
        }
        else if (!_moose_object_pars.get<bool>("_mesh_generator_mesh"))
        {
          mooseWarning("Mesh Generators present but the [Mesh] block is set to construct a \"",
                       _type,
                       "\" mesh, which does not use Mesh Generators in constructing the mesh.");
        }
      }

      // switch non-file meshes to be a file-mesh if using a pre-split mesh configuration.
      if (_app.isUseSplit())
        _type = modifyParamsForUseSplit(_moose_object_pars);

      _mesh = _factory.create<MooseMesh>(_type, "mesh", _moose_object_pars);
    }
  }

  else if (_current_task == "set_mesh_base")
  {
    if (!_app.masterMesh() && !_mesh->hasMeshBase())
    {
      if (!_awh.getActionListByName("add_mesh_generator").empty())
        _mesh->setMeshBase(_app.getMeshGeneratorMesh());
      else
        _mesh->setMeshBase(_mesh->buildMeshBaseObject());
    }
  }

  else if (_current_task == "init_mesh")
  {
    if (_app.masterMesh())
    {
      if (_app.masterDisplacedMesh())
        _displaced_mesh = _app.masterDisplacedMesh()->safeClone();
    }
    else
    {
      _mesh->init();

      if (isParamValid("displacements") && getParam<bool>("use_displaced_mesh"))
      {
        _displaced_mesh = _mesh->safeClone();
        _displaced_mesh->getMesh().allow_remote_element_removal(
            _mesh->getMesh().allow_remote_element_removal());

        std::vector<std::string> displacements =
            getParam<std::vector<std::string>>("displacements");
        if (displacements.size() < _displaced_mesh->dimension())
          mooseError("Number of displacements must be greater than or equal to the dimension of "
                     "the mesh!");
      }

      setupMesh(_mesh.get());

      if (_displaced_mesh)
        setupMesh(_displaced_mesh.get());
    }
  }
}
<|endoftext|>