<commit_before>#include <cassert>
#include <chrono>
#include <iostream>
#include <set>
#include <utility> // pair

#include <sdd/sdd.hh>

#include "mc/live.hh"
#include "mc/post.hh"
#include "mc/pre.hh"
#include "mc/work.hh"

namespace pnmc { namespace mc {

namespace chrono = std::chrono;

typedef sdd::conf1 sdd_conf;
typedef sdd::SDD<sdd_conf> SDD;
typedef sdd::homomorphism<sdd_conf> homomorphism;

using sdd::Composition;
using sdd::Fixpoint;
using sdd::Sum;
using sdd::ValuesFunction;

/*------------------------------------------------------------------------------------------------*/

struct mk_order_visitor
  : public boost::static_visitor<std::pair<std::string, sdd::order_builder<sdd_conf>>>
{
  using result_type = std::pair<std::string, sdd::order_builder<sdd_conf>>;
  using order_builder = sdd::order_builder<sdd_conf>;

  const conf::pnmc_configuration& conf;

  mk_order_visitor(const conf::pnmc_configuration& c)
    : conf(c)
  {}

  // Place: base case of the recursion, there's no more possible nested hierarchies.
  result_type
  operator()(const pn::place* p)
  const noexcept
  {
    return make_pair(p->id, order_builder());
  }

  // Hierarchy.
  result_type
  operator()(const pn::module_node& m)
  const noexcept
  {
    assert(not m.nested.empty());

    std::deque<result_type> tmp;

    for (const auto& h : m.nested)
    {
      const auto res = boost::apply_visitor(*this, *h);
      tmp.push_back(res);
    }

    std::size_t height = 0;
    for (const auto& p : tmp)
    {
      if (not p.second.empty())
      {
        height += p.second.height();
      }
      else
      {
        height += 1; // place
      }
    }

    sdd::order_builder<sdd_conf> ob;
    if (height <= conf.order_min_height)
    {
      std::string id;
      for (const auto& p : tmp)
      {
        if (not p.second.empty())
        {
          id += p.first;
          ob = p.second << ob;
        }
        else // place
        {
          id += p.first;
          ob.push(p.first, p.second);
        }
      }
      return result_type(id, ob);
    }
    else
    {
      for (const auto& p : tmp)
      {
        ob.push(p.first, p.second);
      }
    }

    return make_pair(m.id , ob);
  }
};

/*------------------------------------------------------------------------------------------------*/

sdd::order<sdd_conf>
mk_order(const conf::pnmc_configuration& conf, const pn::net& net)
{
  if (not conf.order_force_flat and net.modules)
  {
    return sdd::order<sdd_conf>(boost::apply_visitor(mk_order_visitor(conf), *net.modules).second);
  }
  else
  {
    sdd::order_builder<sdd_conf> ob;
    for (const auto& place : net.places())
    {
      ob.push(place.id);
    }
    return sdd::order<sdd_conf>(ob);
  }
}

/*------------------------------------------------------------------------------------------------*/

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  return SDD(order, [&](const std::string& id)
                        -> sdd::values::flat_set<unsigned int>
                       {
                         return {net.places_by_id().find(id)->marking};
                       });
}

/*------------------------------------------------------------------------------------------------*/

homomorphism
transition_relation( const conf::pnmc_configuration& conf, const sdd::order<sdd_conf>& o
                   , const pn::net& net, boost::dynamic_bitset<>& transitions_bitset)
{
  chrono::time_point<chrono::system_clock> start;
  chrono::time_point<chrono::system_clock> end;
  std::size_t elapsed;

  start = chrono::system_clock::now();
  std::set<homomorphism> operands;
  operands.insert(sdd::Id<sdd_conf>());

  for (const auto& transition : net.transitions())
  {
    homomorphism h_t = sdd::Id<sdd_conf>();
    if (conf.compute_dead_transitions)
    {
      if (not transition.post.empty())
      {
        const auto f = ValuesFunction<sdd_conf>( o, transition.post.begin()->first
                                               , live(transition.index, transitions_bitset));
        h_t = sdd::carrier(o, transition.post.begin()->first, f);
      }
    }
    // post actions.
    for (const auto& arc : transition.post)
    {
      homomorphism f = ValuesFunction<sdd_conf>(o, arc.first, post(arc.second));
      h_t = Composition(h_t, sdd::carrier(o, arc.first, f));
    }
    // pre actions.
    for (const auto& arc : transition.pre)
    {
      homomorphism f = ValuesFunction<sdd_conf>(o, arc.first, pre(arc.second));
      h_t = Composition(h_t, sdd::carrier(o, arc.first, f));
    }

    operands.insert(h_t);
  }
  end = chrono::system_clock::now();
  elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();

  if (conf.show_time)
  {
    std::cout << "Transition relation time: " << elapsed << "s" << std::endl;
  }

  start = chrono::system_clock::now();
  const auto res = sdd::rewrite(Fixpoint(Sum<sdd_conf>(o, operands.cbegin(), operands.cend())), o);
  end = chrono::system_clock::now();
  elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();

  if (conf.show_time)
  {
    std::cout << "Rewrite time: " << elapsed << "s" << std::endl;
  }

  return res;
}

/*------------------------------------------------------------------------------------------------*/

SDD
state_space( const conf::pnmc_configuration& conf, const sdd::order<sdd_conf>& o, SDD m
           , homomorphism h)
{
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();
  const auto res = h(o, m);
  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "State space computation time: " << elapsed << "s" << std::endl;
  }
  return res;
}

/*------------------------------------------------------------------------------------------------*/

void
work(const conf::pnmc_configuration& conf, const pn::net& net)
{
  auto manager = sdd::manager<sdd_conf>::init();

  boost::dynamic_bitset<> transitions_bitset(net.transitions().size());

  const sdd::order<sdd_conf>& o = mk_order(conf, net);
  assert(not o.empty() && "Empty order");

  if (conf.order_show)
  {
    std::cout << o << std::endl;
  }
  const SDD m0 = initial_state(o, net);

  const homomorphism h = transition_relation(conf, o, net, transitions_bitset);
  if (conf.show_relation)
  {
    std::cout << h << std::endl;
  }

  const SDD m = state_space(conf, o, m0, h);

  const auto n = sdd::count_combinations(m);
  std::cout << n.template convert_to<long double>() << " states" << std::endl;

  if (conf.compute_dead_transitions)
  {
    std::deque<std::string> dead_transitions;
    for (std::size_t i = 0; i < net.transitions().size(); ++i)
    {
      if (not transitions_bitset[i])
      {
        dead_transitions.push_back(net.get_transition_by_index(i).id);
      }
    }

    if (not dead_transitions.empty())
    {
      std::cout << dead_transitions.size() << " dead transition(s): ";
      std::copy( dead_transitions.cbegin(), std::prev(dead_transitions.cend())
               , std::ostream_iterator<std::string>(std::cout, ","));
      std::cout << *std::prev(dead_transitions.cend()) << std::endl;
    }
    else
    {
      std::cout << "No dead transitions" << std::endl;
    }
  }

  if (conf.show_hash_tables_stats)
  {
    std::cout << manager << std::endl;
  }
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::mc
<commit_msg>Use artificial identifiers.<commit_after>#include <cassert>
#include <chrono>
#include <iostream>
#include <set>
#include <utility> // pair

#include <sdd/sdd.hh>

#include "mc/live.hh"
#include "mc/post.hh"
#include "mc/pre.hh"
#include "mc/work.hh"

namespace pnmc { namespace mc {

namespace chrono = std::chrono;

typedef sdd::conf1 sdd_conf;
typedef sdd::SDD<sdd_conf> SDD;
typedef sdd::homomorphism<sdd_conf> homomorphism;

using sdd::Composition;
using sdd::Fixpoint;
using sdd::Sum;
using sdd::ValuesFunction;

/*------------------------------------------------------------------------------------------------*/

struct mk_order_visitor
  : public boost::static_visitor<std::pair<std::string, sdd::order_builder<sdd_conf>>>
{
  using order_identifier = sdd::order_identifier<sdd_conf>;
  using result_type = std::pair<order_identifier, sdd::order_builder<sdd_conf>>;
  using order_builder = sdd::order_builder<sdd_conf>;

  const conf::pnmc_configuration& conf;
  mutable unsigned int artificial_id_counter;

  mk_order_visitor(const conf::pnmc_configuration& c)
    : conf(c), artificial_id_counter(0)
  {}

  // Place: base case of the recursion, there's no more possible nested hierarchies.
  result_type
  operator()(const pn::place* p)
  const noexcept
  {
    return std::make_pair(order_identifier(p->id), order_builder());
  }

  // Hierarchy.
  result_type
  operator()(const pn::module_node& m)
  const noexcept
  {
    assert(not m.nested.empty());

    std::deque<result_type> tmp;

    for (const auto& h : m.nested)
    {
      const auto res = boost::apply_visitor(*this, *h);
      tmp.push_back(res);
    }

    std::size_t height = 0;
    for (const auto& p : tmp)
    {
      if (not p.second.empty())
      {
        height += p.second.height();
      }
      else
      {
        height += 1; // place
      }
    }

    order_builder ob;
    if (height <= conf.order_min_height)
    {
      order_identifier id;
      for (const auto& p : tmp)
      {
        if (not p.second.empty())
        {
          ob = p.second << ob;
        }
        else // place
        {
          ob.push(p.first, p.second);
        }
      }
      return result_type(id, ob);
    }
    else
    {
      for (const auto& p : tmp)
      {
        ob.push(p.first, p.second);
      }
    }

    return std::make_pair(order_identifier(m.id) , ob);
  }
};

/*------------------------------------------------------------------------------------------------*/

sdd::order<sdd_conf>
mk_order(const conf::pnmc_configuration& conf, const pn::net& net)
{
  if (not conf.order_force_flat and net.modules)
  {
    return sdd::order<sdd_conf>(boost::apply_visitor(mk_order_visitor(conf), *net.modules).second);
  }
  else
  {
    sdd::order_builder<sdd_conf> ob;
    for (const auto& place : net.places())
    {
      ob.push(place.id);
    }
    return sdd::order<sdd_conf>(ob);
  }
}

/*------------------------------------------------------------------------------------------------*/

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  return SDD(order, [&](const std::string& id)
                        -> sdd::values::flat_set<unsigned int>
                       {
                         return {net.places_by_id().find(id)->marking};
                       });
}

/*------------------------------------------------------------------------------------------------*/

homomorphism
transition_relation( const conf::pnmc_configuration& conf, const sdd::order<sdd_conf>& o
                   , const pn::net& net, boost::dynamic_bitset<>& transitions_bitset)
{
  chrono::time_point<chrono::system_clock> start;
  chrono::time_point<chrono::system_clock> end;
  std::size_t elapsed;

  start = chrono::system_clock::now();
  std::set<homomorphism> operands;
  operands.insert(sdd::Id<sdd_conf>());

  for (const auto& transition : net.transitions())
  {
    homomorphism h_t = sdd::Id<sdd_conf>();
    if (conf.compute_dead_transitions)
    {
      if (not transition.post.empty())
      {
        const auto f = ValuesFunction<sdd_conf>( o, transition.post.begin()->first
                                               , live(transition.index, transitions_bitset));
        h_t = sdd::carrier(o, transition.post.begin()->first, f);
      }
    }
    // post actions.
    for (const auto& arc : transition.post)
    {
      homomorphism f = ValuesFunction<sdd_conf>(o, arc.first, post(arc.second));
      h_t = Composition(h_t, sdd::carrier(o, arc.first, f));
    }
    // pre actions.
    for (const auto& arc : transition.pre)
    {
      homomorphism f = ValuesFunction<sdd_conf>(o, arc.first, pre(arc.second));
      h_t = Composition(h_t, sdd::carrier(o, arc.first, f));
    }

    operands.insert(h_t);
  }
  end = chrono::system_clock::now();
  elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();

  if (conf.show_time)
  {
    std::cout << "Transition relation time: " << elapsed << "s" << std::endl;
  }

  start = chrono::system_clock::now();
  const auto res = sdd::rewrite(Fixpoint(Sum<sdd_conf>(o, operands.cbegin(), operands.cend())), o);
  end = chrono::system_clock::now();
  elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();

  if (conf.show_time)
  {
    std::cout << "Rewrite time: " << elapsed << "s" << std::endl;
  }

  return res;
}

/*------------------------------------------------------------------------------------------------*/

SDD
state_space( const conf::pnmc_configuration& conf, const sdd::order<sdd_conf>& o, SDD m
           , homomorphism h)
{
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();
  const auto res = h(o, m);
  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "State space computation time: " << elapsed << "s" << std::endl;
  }
  return res;
}

/*------------------------------------------------------------------------------------------------*/

void
work(const conf::pnmc_configuration& conf, const pn::net& net)
{
  auto manager = sdd::manager<sdd_conf>::init();

  boost::dynamic_bitset<> transitions_bitset(net.transitions().size());

  const sdd::order<sdd_conf>& o = mk_order(conf, net);
  assert(not o.empty() && "Empty order");

  if (conf.order_show)
  {
    std::cout << o << std::endl;
  }
  const SDD m0 = initial_state(o, net);

  const homomorphism h = transition_relation(conf, o, net, transitions_bitset);
  if (conf.show_relation)
  {
    std::cout << h << std::endl;
  }

  const SDD m = state_space(conf, o, m0, h);

  const auto n = sdd::count_combinations(m);
  std::cout << n.template convert_to<long double>() << " states" << std::endl;

  if (conf.compute_dead_transitions)
  {
    std::deque<std::string> dead_transitions;
    for (std::size_t i = 0; i < net.transitions().size(); ++i)
    {
      if (not transitions_bitset[i])
      {
        dead_transitions.push_back(net.get_transition_by_index(i).id);
      }
    }

    if (not dead_transitions.empty())
    {
      std::cout << dead_transitions.size() << " dead transition(s): ";
      std::copy( dead_transitions.cbegin(), std::prev(dead_transitions.cend())
               , std::ostream_iterator<std::string>(std::cout, ","));
      std::cout << *std::prev(dead_transitions.cend()) << std::endl;
    }
    else
    {
      std::cout << "No dead transitions" << std::endl;
    }
  }

  if (conf.show_hash_tables_stats)
  {
    std::cout << manager << std::endl;
  }
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::mc
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "core/platform/graphics/chromium/Canvas2DLayerBridge.h"

#include "GrContext.h"
#include "SkDevice.h"
#include "SkSurface.h"
#include "core/platform/chromium/TraceEvent.h"
#include "core/platform/graphics/GraphicsContext3D.h"
#include "core/platform/graphics/GraphicsLayer.h"
#include "core/platform/graphics/chromium/Canvas2DLayerManager.h"
#include "core/platform/graphics/gpu/SharedGraphicsContext3D.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebGraphicsContext3D.h"

using WebKit::WebExternalTextureLayer;
using WebKit::WebGraphicsContext3D;

namespace WebCore {

static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& size)
{
    ASSERT(!context3D->webContext()->isContextLost());
    GrContext* gr = context3D->grContext();
    if (!gr)
        return 0;
    gr->resetContext();
    SkImage::Info info;
    info.fWidth = size.width();
    info.fHeight = size.height();
    info.fColorType = SkImage::kPMColor_ColorType;
    info.fAlphaType = SkImage::kPremul_AlphaType;
    return SkSurface::NewRenderTarget(gr, info);
}

PassOwnPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(PassRefPtr<GraphicsContext3D> context, const IntSize& size, OpacityMode opacityMode)
{
    TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
    SkAutoTUnref<SkSurface> surface(createSurface(context.get(), size));
    if (!surface.get())
        return PassOwnPtr<Canvas2DLayerBridge>();
    SkDeferredCanvas* canvas = new SkDeferredCanvas(surface);
    OwnPtr<Canvas2DLayerBridge> layerBridge = adoptPtr(new Canvas2DLayerBridge(context, canvas, opacityMode));
    return layerBridge.release();
}

Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode)
    : m_canvas(canvas)
    , m_context(context)
    , m_bytesAllocated(0)
    , m_didRecordDrawCommand(false)
    , m_surfaceIsValid(true)
    , m_framesPending(0)
    , m_rateLimitingEnabled(false)
    , m_next(0)
    , m_prev(0)
    , m_lastImageId(0)
{
    ASSERT(m_canvas);
    // Used by browser tests to detect the use of a Canvas2DLayerBridge.
    TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
    m_canvas->setNotificationClient(this);
    m_layer = adoptPtr(WebKit::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
    m_layer->setOpaque(opacityMode == Opaque);
    GraphicsLayer::registerContentsLayer(m_layer->layer());
    m_layer->setRateLimitContext(m_rateLimitingEnabled);
    m_canvas->setNotificationClient(this);
}

Canvas2DLayerBridge::~Canvas2DLayerBridge()
{
    GraphicsLayer::unregisterContentsLayer(m_layer->layer());
    Canvas2DLayerManager::get().layerToBeDestroyed(this);
    m_canvas->setNotificationClient(0);
    m_mailboxes.clear();
    m_layer->clearTexture();
    m_layer.clear();
}

void Canvas2DLayerBridge::limitPendingFrames()
{
    if (m_didRecordDrawCommand) {
        m_framesPending++;
        m_didRecordDrawCommand = false;
        if (m_framesPending > 1) {
            // Turn on the rate limiter if this layer tends to accumulate a
            // non-discardable multi-frame backlog of draw commands.
            setRateLimitingEnabled(true);
        }
        if (m_rateLimitingEnabled) {
            flush();
        }
    }
}

void Canvas2DLayerBridge::prepareForDraw()
{
    ASSERT(m_layer);
    if (!isValid()) {
        if (m_canvas) {
            // drop pending commands because there is no surface to draw to
            m_canvas->silentFlush();
        }
        return;
    }
    m_context->makeContextCurrent();
}

void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated)
{
    intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
    m_bytesAllocated = bytesAllocated;
    Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta);
}

size_t Canvas2DLayerBridge::storageAllocatedForRecording()
{
    return m_canvas->storageAllocatedForRecording();
}

void Canvas2DLayerBridge::flushedDrawCommands()
{
    storageAllocatedForRecordingChanged(storageAllocatedForRecording());
    m_framesPending = 0;
}

void Canvas2DLayerBridge::skippedPendingDrawCommands()
{
    // Stop triggering the rate limiter if SkDeferredCanvas is detecting
    // and optimizing overdraw.
    setRateLimitingEnabled(false);
    flushedDrawCommands();
}

void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled)
{
    if (m_rateLimitingEnabled != enabled) {
        m_rateLimitingEnabled = enabled;
        m_layer->setRateLimitContext(m_rateLimitingEnabled);
    }
}

size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree)
{
    size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree);
    if (bytesFreed)
        Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr_t)bytesFreed));
    m_bytesAllocated -= bytesFreed;
    return bytesFreed;
}

void Canvas2DLayerBridge::flush()
{
    if (m_canvas->hasPendingCommands()) {
        TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
        m_canvas->flush();
    }
}

WebGraphicsContext3D* Canvas2DLayerBridge::context()
{
    return isValid() ? m_context->webContext() : 0;
}

bool Canvas2DLayerBridge::isValid()
{
    ASSERT(m_layer);
    if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) {
        // Attempt to recover.
        m_layer->clearTexture();
        RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
        if (!sharedContext || sharedContext->webContext()->isContextLost()) {
            m_surfaceIsValid = false;
            return false;
        }
        m_context = sharedContext;
        IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
        SkAutoTUnref<SkSurface> surface(createSurface(m_context.get(), size));
        if (surface.get()) {
            m_canvas->setSurface(surface.get());
            m_surfaceIsValid = true;
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        } else {
            // Surface allocation failed. Set m_surfaceIsValid to false to
            // trigger subsequent retry.
            m_surfaceIsValid = false;
            return false;
        }
    }
    return true;

}

bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox, WebKit::WebExternalBitmap* bitmap)
{
    ASSERT(!bitmap);
    if (!isValid())
        return false;
    // Release to skia textures that were previouosly released by the
    // compositor. We do this before acquiring the next snapshot in
    // order to cap maximum gpu memory consumption.
    m_context->makeContextCurrent();
    flush();
    Vector<MailboxInfo>::iterator mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
        if (mailboxInfo->m_status == MailboxReleased) {
            if (mailboxInfo->m_mailbox.syncPoint) {
                context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
                mailboxInfo->m_mailbox.syncPoint = 0;
            }
            // Invalidate texture state in case the compositor altered it since the copy-on-write.
            mailboxInfo->m_image->getTexture()->invalidateCachedState();
            mailboxInfo->m_image.reset(0);
            mailboxInfo->m_status = MailboxAvailable;
        }
    }
    SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot());
    // Early exit if canvas was not drawn to since last prepareMailbox
    if (image->uniqueID() == m_lastImageId)
        return false;
    m_lastImageId = image->uniqueID();

    mailboxInfo = createMailboxInfo();
    mailboxInfo->m_status = MailboxInUse;
    mailboxInfo->m_image.swap(&image);
    // Because of texture sharing with the compositor, we must invalidate
    // the state cached in skia so that the deferred copy on write
    // in SkSurface_Gpu does not make any false assumptions.
    mailboxInfo->m_image->getTexture()->invalidateCachedState();

    ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
    ASSERT(mailboxInfo->m_image.get());
    ASSERT(mailboxInfo->m_image->getTexture());

    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
    context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, mailboxInfo->m_mailbox.name);
    context()->flush();
    mailboxInfo->m_mailbox.syncPoint = context()->insertSyncPoint();
    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
    // Because we are changing the texture binding without going through skia,
    // we must dirty the context.
    m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState);

    *outMailbox = mailboxInfo->m_mailbox;
    return true;
}

Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() {
    MailboxInfo* mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
        if (mailboxInfo->m_status == MailboxAvailable) {
            return mailboxInfo;
        }
    }

    // No available mailbox: create one.
    m_mailboxes.grow(m_mailboxes.size() + 1);
    mailboxInfo = &m_mailboxes.last();
    context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name);
    // Worst case, canvas is triple buffered.  More than 3 active mailboxes
    // means there is a problem.
    // For the single-threaded case, this value needs to be at least
    // kMaxSwapBuffersPending+1 (in render_widget.h).
    // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2.
    // TODO(piman): fix this.
    ASSERT(m_mailboxes.size() <= 4);
    ASSERT(mailboxInfo < m_mailboxes.end());
    return mailboxInfo;
}

void Canvas2DLayerBridge::mailboxReleased(const WebKit::WebExternalTextureMailbox& mailbox)
{
    Vector<MailboxInfo>::iterator mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
         if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.name))) {
             mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
             ASSERT(mailboxInfo->m_status == MailboxInUse);
             mailboxInfo->m_status = MailboxReleased;
             return;
         }
     }
     ASSERT_NOT_REACHED();
}

WebKit::WebLayer* Canvas2DLayerBridge::layer()
{
    ASSERT(m_layer);
    return m_layer->layer();
}

void Canvas2DLayerBridge::contextAcquired()
{
    Canvas2DLayerManager::get().layerDidDraw(this);
    m_didRecordDrawCommand = true;
}

unsigned Canvas2DLayerBridge::backBufferTexture()
{
    if (!isValid())
        return 0;
    contextAcquired();
    m_canvas->flush();
    m_context->flush();
    GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->getDevice()->accessRenderTarget());
    if (renderTarget) {
        return renderTarget->asTexture()->getTextureHandle();
    }
    return 0;
}

Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
    // This copy constructor should only be used for Vector reallocation
    // Assuming 'other' is to be destroyed, we swap m_image ownership
    // rather than do a refcount dance.
    memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
    m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image));
    m_status = other.m_status;
}

}
<commit_msg>Removed duplicated line of code in Canvas2DLayerBridge due to merge conflict resolution error<commit_after>/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "core/platform/graphics/chromium/Canvas2DLayerBridge.h"

#include "GrContext.h"
#include "SkDevice.h"
#include "SkSurface.h"
#include "core/platform/chromium/TraceEvent.h"
#include "core/platform/graphics/GraphicsContext3D.h"
#include "core/platform/graphics/GraphicsLayer.h"
#include "core/platform/graphics/chromium/Canvas2DLayerManager.h"
#include "core/platform/graphics/gpu/SharedGraphicsContext3D.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebGraphicsContext3D.h"

using WebKit::WebExternalTextureLayer;
using WebKit::WebGraphicsContext3D;

namespace WebCore {

static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& size)
{
    ASSERT(!context3D->webContext()->isContextLost());
    GrContext* gr = context3D->grContext();
    if (!gr)
        return 0;
    gr->resetContext();
    SkImage::Info info;
    info.fWidth = size.width();
    info.fHeight = size.height();
    info.fColorType = SkImage::kPMColor_ColorType;
    info.fAlphaType = SkImage::kPremul_AlphaType;
    return SkSurface::NewRenderTarget(gr, info);
}

PassOwnPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(PassRefPtr<GraphicsContext3D> context, const IntSize& size, OpacityMode opacityMode)
{
    TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
    SkAutoTUnref<SkSurface> surface(createSurface(context.get(), size));
    if (!surface.get())
        return PassOwnPtr<Canvas2DLayerBridge>();
    SkDeferredCanvas* canvas = new SkDeferredCanvas(surface);
    OwnPtr<Canvas2DLayerBridge> layerBridge = adoptPtr(new Canvas2DLayerBridge(context, canvas, opacityMode));
    return layerBridge.release();
}

Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode)
    : m_canvas(canvas)
    , m_context(context)
    , m_bytesAllocated(0)
    , m_didRecordDrawCommand(false)
    , m_surfaceIsValid(true)
    , m_framesPending(0)
    , m_rateLimitingEnabled(false)
    , m_next(0)
    , m_prev(0)
    , m_lastImageId(0)
{
    ASSERT(m_canvas);
    // Used by browser tests to detect the use of a Canvas2DLayerBridge.
    TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
    m_layer = adoptPtr(WebKit::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
    m_layer->setOpaque(opacityMode == Opaque);
    GraphicsLayer::registerContentsLayer(m_layer->layer());
    m_layer->setRateLimitContext(m_rateLimitingEnabled);
    m_canvas->setNotificationClient(this);
}

Canvas2DLayerBridge::~Canvas2DLayerBridge()
{
    GraphicsLayer::unregisterContentsLayer(m_layer->layer());
    Canvas2DLayerManager::get().layerToBeDestroyed(this);
    m_canvas->setNotificationClient(0);
    m_mailboxes.clear();
    m_layer->clearTexture();
    m_layer.clear();
}

void Canvas2DLayerBridge::limitPendingFrames()
{
    if (m_didRecordDrawCommand) {
        m_framesPending++;
        m_didRecordDrawCommand = false;
        if (m_framesPending > 1) {
            // Turn on the rate limiter if this layer tends to accumulate a
            // non-discardable multi-frame backlog of draw commands.
            setRateLimitingEnabled(true);
        }
        if (m_rateLimitingEnabled) {
            flush();
        }
    }
}

void Canvas2DLayerBridge::prepareForDraw()
{
    ASSERT(m_layer);
    if (!isValid()) {
        if (m_canvas) {
            // drop pending commands because there is no surface to draw to
            m_canvas->silentFlush();
        }
        return;
    }
    m_context->makeContextCurrent();
}

void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated)
{
    intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
    m_bytesAllocated = bytesAllocated;
    Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta);
}

size_t Canvas2DLayerBridge::storageAllocatedForRecording()
{
    return m_canvas->storageAllocatedForRecording();
}

void Canvas2DLayerBridge::flushedDrawCommands()
{
    storageAllocatedForRecordingChanged(storageAllocatedForRecording());
    m_framesPending = 0;
}

void Canvas2DLayerBridge::skippedPendingDrawCommands()
{
    // Stop triggering the rate limiter if SkDeferredCanvas is detecting
    // and optimizing overdraw.
    setRateLimitingEnabled(false);
    flushedDrawCommands();
}

void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled)
{
    if (m_rateLimitingEnabled != enabled) {
        m_rateLimitingEnabled = enabled;
        m_layer->setRateLimitContext(m_rateLimitingEnabled);
    }
}

size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree)
{
    size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree);
    if (bytesFreed)
        Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr_t)bytesFreed));
    m_bytesAllocated -= bytesFreed;
    return bytesFreed;
}

void Canvas2DLayerBridge::flush()
{
    if (m_canvas->hasPendingCommands()) {
        TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
        m_canvas->flush();
    }
}

WebGraphicsContext3D* Canvas2DLayerBridge::context()
{
    return isValid() ? m_context->webContext() : 0;
}

bool Canvas2DLayerBridge::isValid()
{
    ASSERT(m_layer);
    if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) {
        // Attempt to recover.
        m_layer->clearTexture();
        RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
        if (!sharedContext || sharedContext->webContext()->isContextLost()) {
            m_surfaceIsValid = false;
            return false;
        }
        m_context = sharedContext;
        IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
        SkAutoTUnref<SkSurface> surface(createSurface(m_context.get(), size));
        if (surface.get()) {
            m_canvas->setSurface(surface.get());
            m_surfaceIsValid = true;
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        } else {
            // Surface allocation failed. Set m_surfaceIsValid to false to
            // trigger subsequent retry.
            m_surfaceIsValid = false;
            return false;
        }
    }
    return true;

}

bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox, WebKit::WebExternalBitmap* bitmap)
{
    ASSERT(!bitmap);
    if (!isValid())
        return false;
    // Release to skia textures that were previouosly released by the
    // compositor. We do this before acquiring the next snapshot in
    // order to cap maximum gpu memory consumption.
    m_context->makeContextCurrent();
    flush();
    Vector<MailboxInfo>::iterator mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
        if (mailboxInfo->m_status == MailboxReleased) {
            if (mailboxInfo->m_mailbox.syncPoint) {
                context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
                mailboxInfo->m_mailbox.syncPoint = 0;
            }
            // Invalidate texture state in case the compositor altered it since the copy-on-write.
            mailboxInfo->m_image->getTexture()->invalidateCachedState();
            mailboxInfo->m_image.reset(0);
            mailboxInfo->m_status = MailboxAvailable;
        }
    }
    SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot());
    // Early exit if canvas was not drawn to since last prepareMailbox
    if (image->uniqueID() == m_lastImageId)
        return false;
    m_lastImageId = image->uniqueID();

    mailboxInfo = createMailboxInfo();
    mailboxInfo->m_status = MailboxInUse;
    mailboxInfo->m_image.swap(&image);
    // Because of texture sharing with the compositor, we must invalidate
    // the state cached in skia so that the deferred copy on write
    // in SkSurface_Gpu does not make any false assumptions.
    mailboxInfo->m_image->getTexture()->invalidateCachedState();

    ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
    ASSERT(mailboxInfo->m_image.get());
    ASSERT(mailboxInfo->m_image->getTexture());

    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
    m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
    context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, mailboxInfo->m_mailbox.name);
    context()->flush();
    mailboxInfo->m_mailbox.syncPoint = context()->insertSyncPoint();
    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
    // Because we are changing the texture binding without going through skia,
    // we must dirty the context.
    m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState);

    *outMailbox = mailboxInfo->m_mailbox;
    return true;
}

Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() {
    MailboxInfo* mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
        if (mailboxInfo->m_status == MailboxAvailable) {
            return mailboxInfo;
        }
    }

    // No available mailbox: create one.
    m_mailboxes.grow(m_mailboxes.size() + 1);
    mailboxInfo = &m_mailboxes.last();
    context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name);
    // Worst case, canvas is triple buffered.  More than 3 active mailboxes
    // means there is a problem.
    // For the single-threaded case, this value needs to be at least
    // kMaxSwapBuffersPending+1 (in render_widget.h).
    // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2.
    // TODO(piman): fix this.
    ASSERT(m_mailboxes.size() <= 4);
    ASSERT(mailboxInfo < m_mailboxes.end());
    return mailboxInfo;
}

void Canvas2DLayerBridge::mailboxReleased(const WebKit::WebExternalTextureMailbox& mailbox)
{
    Vector<MailboxInfo>::iterator mailboxInfo;
    for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
         if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.name))) {
             mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
             ASSERT(mailboxInfo->m_status == MailboxInUse);
             mailboxInfo->m_status = MailboxReleased;
             return;
         }
     }
     ASSERT_NOT_REACHED();
}

WebKit::WebLayer* Canvas2DLayerBridge::layer()
{
    ASSERT(m_layer);
    return m_layer->layer();
}

void Canvas2DLayerBridge::contextAcquired()
{
    Canvas2DLayerManager::get().layerDidDraw(this);
    m_didRecordDrawCommand = true;
}

unsigned Canvas2DLayerBridge::backBufferTexture()
{
    if (!isValid())
        return 0;
    contextAcquired();
    m_canvas->flush();
    m_context->flush();
    GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->getDevice()->accessRenderTarget());
    if (renderTarget) {
        return renderTarget->asTexture()->getTextureHandle();
    }
    return 0;
}

Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
    // This copy constructor should only be used for Vector reallocation
    // Assuming 'other' is to be destroyed, we swap m_image ownership
    // rather than do a refcount dance.
    memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
    m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image));
    m_status = other.m_status;
}

}
<|endoftext|>


<commit_before>//===------------------------ memory.cpp ----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define _LIBCPP_BUILDING_MEMORY
#include "memory"
#include "mutex"

_LIBCPP_BEGIN_NAMESPACE_STD

namespace
{

template <class T>
inline T
increment(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, 1);
}

template <class T>
inline T
decrement(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, -1);
}

}  // namespace

const allocator_arg_t allocator_arg = allocator_arg_t();

bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}

const char*
bad_weak_ptr::what() const _NOEXCEPT
{
    return "bad_weak_ptr";
}

__shared_count::~__shared_count()
{
}

void
__shared_count::__add_shared() _NOEXCEPT
{
    increment(__shared_owners_);
}

bool
__shared_count::__release_shared() _NOEXCEPT
{
    if (decrement(__shared_owners_) == -1)
    {
        __on_zero_shared();
        return true;
    }
    return false;
}

__shared_weak_count::~__shared_weak_count()
{
}

void
__shared_weak_count::__add_shared() _NOEXCEPT
{
    __shared_count::__add_shared();
}

void
__shared_weak_count::__add_weak() _NOEXCEPT
{
    increment(__shared_weak_owners_);
}

void
__shared_weak_count::__release_shared() _NOEXCEPT
{
    if (__shared_count::__release_shared())
        __release_weak();
}

void
__shared_weak_count::__release_weak() _NOEXCEPT
{
    if (decrement(__shared_weak_owners_) == -1)
        __on_zero_shared_weak();
}

__shared_weak_count*
__shared_weak_count::lock() _NOEXCEPT
{
    long object_owners = __shared_owners_;
    while (object_owners != -1)
    {
        if (__sync_bool_compare_and_swap(&__shared_owners_,
                                         object_owners,
                                         object_owners+1))
            return this;
        object_owners = __shared_owners_;
    }
    return 0;
}

#ifndef _LIBCPP_NO_RTTI

const void*
__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
{
    return 0;
}

#endif  // _LIBCPP_NO_RTTI

static const std::size_t __sp_mut_count = 16;
static mutex mut_back[__sp_mut_count];

_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
   : _(p)
{
}

void
__sp_mut::lock() _NOEXCEPT
{
    reinterpret_cast<mutex*>(_)->lock();
}

void
__sp_mut::unlock() _NOEXCEPT
{
    reinterpret_cast<mutex*>(_)->unlock();
}

__sp_mut&
__get_sp_mut(const void* p)
{
    static __sp_mut muts[__sp_mut_count]
    {
        &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
        &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
        &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
        &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
    };
    return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
}

void
declare_reachable(void*)
{
}

void
declare_no_pointers(char*, size_t)
{
}

void
undeclare_no_pointers(char*, size_t)
{
}

pointer_safety
get_pointer_safety() _NOEXCEPT
{
    return pointer_safety::relaxed;
}

void*
__undeclare_reachable(void* p)
{
    return p;
}

void*
align(size_t alignment, size_t size, void*& ptr, size_t& space)
{
    void* r = nullptr;
    if (size <= space)
    {
        char* p1 = static_cast<char*>(ptr);
        char* p2 = (char*)((size_t)(p1 + (alignment - 1)) & -alignment);
        size_t d = static_cast<size_t>(p2 - p1);
        if (d <= space - size)
        {
            r = p2;
            ptr = r;
            space -= d;
        }
    }
    return r;
}

_LIBCPP_END_NAMESPACE_STD
<commit_msg>Despite my pathological distrust of spin locks, the number just don't lie.  I've put a small spin in __sp_mut::lock() on std::mutex::try_lock(), which is testing quite well.  In my experience, putting in a yield for every failed iteration is also a major performance booster.  This change makes one of the performance tests I was using (a highly contended one) run about 20 times faster.<commit_after>//===------------------------ memory.cpp ----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define _LIBCPP_BUILDING_MEMORY
#include "memory"
#include "mutex"
#include "thread"

_LIBCPP_BEGIN_NAMESPACE_STD

namespace
{

template <class T>
inline T
increment(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, 1);
}

template <class T>
inline T
decrement(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, -1);
}

}  // namespace

const allocator_arg_t allocator_arg = allocator_arg_t();

bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}

const char*
bad_weak_ptr::what() const _NOEXCEPT
{
    return "bad_weak_ptr";
}

__shared_count::~__shared_count()
{
}

void
__shared_count::__add_shared() _NOEXCEPT
{
    increment(__shared_owners_);
}

bool
__shared_count::__release_shared() _NOEXCEPT
{
    if (decrement(__shared_owners_) == -1)
    {
        __on_zero_shared();
        return true;
    }
    return false;
}

__shared_weak_count::~__shared_weak_count()
{
}

void
__shared_weak_count::__add_shared() _NOEXCEPT
{
    __shared_count::__add_shared();
}

void
__shared_weak_count::__add_weak() _NOEXCEPT
{
    increment(__shared_weak_owners_);
}

void
__shared_weak_count::__release_shared() _NOEXCEPT
{
    if (__shared_count::__release_shared())
        __release_weak();
}

void
__shared_weak_count::__release_weak() _NOEXCEPT
{
    if (decrement(__shared_weak_owners_) == -1)
        __on_zero_shared_weak();
}

__shared_weak_count*
__shared_weak_count::lock() _NOEXCEPT
{
    long object_owners = __shared_owners_;
    while (object_owners != -1)
    {
        if (__sync_bool_compare_and_swap(&__shared_owners_,
                                         object_owners,
                                         object_owners+1))
            return this;
        object_owners = __shared_owners_;
    }
    return 0;
}

#ifndef _LIBCPP_NO_RTTI

const void*
__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
{
    return 0;
}

#endif  // _LIBCPP_NO_RTTI

static const std::size_t __sp_mut_count = 16;
static mutex mut_back[__sp_mut_count];

_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
   : _(p)
{
}

void
__sp_mut::lock() _NOEXCEPT
{
    mutex& m = *static_cast<mutex*>(_);
    unsigned count = 0;
    while (!m.try_lock())
    {
        if (++count > 16)
        {
            m.lock();
            break;
        }
        this_thread::yield();
    }
}

void
__sp_mut::unlock() _NOEXCEPT
{
    static_cast<mutex*>(_)->unlock();
}

__sp_mut&
__get_sp_mut(const void* p)
{
    static __sp_mut muts[__sp_mut_count]
    {
        &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
        &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
        &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
        &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
    };
    return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
}

void
declare_reachable(void*)
{
}

void
declare_no_pointers(char*, size_t)
{
}

void
undeclare_no_pointers(char*, size_t)
{
}

pointer_safety
get_pointer_safety() _NOEXCEPT
{
    return pointer_safety::relaxed;
}

void*
__undeclare_reachable(void* p)
{
    return p;
}

void*
align(size_t alignment, size_t size, void*& ptr, size_t& space)
{
    void* r = nullptr;
    if (size <= space)
    {
        char* p1 = static_cast<char*>(ptr);
        char* p2 = (char*)((size_t)(p1 + (alignment - 1)) & -alignment);
        size_t d = static_cast<size_t>(p2 - p1);
        if (d <= space - size)
        {
            r = p2;
            ptr = r;
            space -= d;
        }
    }
    return r;
}

_LIBCPP_END_NAMESPACE_STD
<|endoftext|>


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

  Program:   KWSys - Kitware System Library
  Module:    DynamicLoader.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)

#include KWSYS_HEADER(Configure.hxx)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "DynamicLoader.hxx.in"
# include "Configure.hxx.in"
#endif

// This file is actually 3 different implementations.
// 1. HP machines which uses shl_load
// 2. Power PC MAC which uses GetSharedLibrary
// 3. Windows which uses LoadLibrary
// 4. Most unix systems which use dlopen (default )
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
DynamicLoader::DynamicLoader()
{
}

//----------------------------------------------------------------------------
DynamicLoader::~DynamicLoader()
{
}

}

// ---------------------------------------------------------------
// 1. Implementation for HPUX  machines
#ifdef __hpux
#include <dl.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return !shl_unload(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction
DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* addr;
  int status;

  status = shl_findsym (&lib, sym, TYPE_PROCEDURE, &addr);
  void* result = (status < 0) ? (void*)0 : addr;

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".sl";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  // TODO: Need implementation with errno/strerror
  /* If successful, shl_findsym returns an integer (int) value zero. If
   * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
   * If any other errors occur, shl_findsym returns -1 and sets errno to one
   * of these values (defined in <errno.h>):
   * ENOEXEC
   * A format error was detected in the specified library.
   * ENOSYM
   * A symbol on which sym depends could not be found.
   * EINVAL
   * The specified handle is invalid.
   */

  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //__hpux

// ---------------------------------------------------------------
// 2. Implementation for Mac OS X 10.2.x and earlier
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <mach-o/dyld.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  NSObjectFileImageReturnCode rc;
  NSObjectFileImage image = 0;

  rc = NSCreateObjectFileImageFromFile(libname, &image);
  if(!image)
    {
    return 0;
    }
  return NSLinkModule(image, libname, NSLINKMODULE_OPTION_BINDNOW);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary( LibHandle lib)
{
  DYLD_BOOL success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  return success;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle /* lib */, const char* sym)
{
  void *result=0;
  if(NSIsSymbolNameDefined(sym))
    {
    NSSymbol symbol= NSLookupAndBindSymbol(sym);
    if(symbol)
      {
      result = NSAddressOfSymbol(symbol);
      }
    }
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dylib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

// ---------------------------------------------------------------
// 3. Implementation for Windows win32 code
#ifdef _WIN32
#include <windows.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname)
{
  LibHandle lh;
#ifdef UNICODE
  wchar_t libn[MB_CUR_MAX];
  mbstowcs(libn, libname, MB_CUR_MAX);
  lh = LoadLibrary(libn);
#else
  lh = LoadLibrary(libname);
#endif
  return lh;
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return (int)FreeLibrary(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result;
#ifdef UNICODE
  wchar_t wsym[MB_CUR_MAX];
  mbstowcs(wsym, sym, MB_CUR_MAX);
  result = GetProcAddress(lib, wsym);
#else
  result = (void*)GetProcAddress(lib, sym);
#endif
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dll";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  LPVOID lpMsgBuf;

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL
    );

  static char* str = 0;
  delete [] str;
  str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  // Free the buffer.
  LocalFree( lpMsgBuf );
  return str;
}

} // namespace KWSYS_NAMESPACE

#endif //_WIN32

// ---------------------------------------------------------------
// 4. Implementation for default UNIX machines.
// if nothing has been defined then use this
#ifndef DYNAMICLOADER_DEFINED
#define DYNAMICLOADER_DEFINED 1
// Setup for most unix machines
#include <dlfcn.h>

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return dlopen(libname, RTLD_LAZY);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  if (lib)
    {
    // The function dlclose() returns 0 on success, and non-zero on error.
    return !(int)dlclose(lib);
    }
  // else
  return 0;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* result = dlsym(lib, sym);

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".so";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return dlerror();
}

} // namespace KWSYS_NAMESPACE

#endif
<commit_msg>COMP: Fix compilation on MacOSX<commit_after>/*=========================================================================

  Program:   KWSys - Kitware System Library
  Module:    DynamicLoader.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)

#include KWSYS_HEADER(Configure.hxx)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "DynamicLoader.hxx.in"
# include "Configure.hxx.in"
#endif

// This file is actually 3 different implementations.
// 1. HP machines which uses shl_load
// 2. Power PC MAC which uses GetSharedLibrary
// 3. Windows which uses LoadLibrary
// 4. Most unix systems which use dlopen (default )
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
DynamicLoader::DynamicLoader()
{
}

//----------------------------------------------------------------------------
DynamicLoader::~DynamicLoader()
{
}

}

// ---------------------------------------------------------------
// 1. Implementation for HPUX  machines
#ifdef __hpux
#include <dl.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return !shl_unload(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction
DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* addr;
  int status;

  status = shl_findsym (&lib, sym, TYPE_PROCEDURE, &addr);
  void* result = (status < 0) ? (void*)0 : addr;

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".sl";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  // TODO: Need implementation with errno/strerror
  /* If successful, shl_findsym returns an integer (int) value zero. If
   * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
   * If any other errors occur, shl_findsym returns -1 and sets errno to one
   * of these values (defined in <errno.h>):
   * ENOEXEC
   * A format error was detected in the specified library.
   * ENOSYM
   * A symbol on which sym depends could not be found.
   * EINVAL
   * The specified handle is invalid.
   */

  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //__hpux

// ---------------------------------------------------------------
// 2. Implementation for Mac OS X 10.2.x and earlier
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <mach-o/dyld.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  NSObjectFileImageReturnCode rc;
  NSObjectFileImage image = 0;

  rc = NSCreateObjectFileImageFromFile(libname, &image);
  if(!image)
    {
    return 0;
    }
  return NSLinkModule(image, libname, NSLINKMODULE_OPTION_BINDNOW);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary( LibHandle lib)
{
  bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  return success;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle /* lib */, const char* sym)
{
  void *result=0;
  if(NSIsSymbolNameDefined(sym))
    {
    NSSymbol symbol= NSLookupAndBindSymbol(sym);
    if(symbol)
      {
      result = NSAddressOfSymbol(symbol);
      }
    }
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dylib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

// ---------------------------------------------------------------
// 3. Implementation for Windows win32 code
#ifdef _WIN32
#include <windows.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname)
{
  LibHandle lh;
#ifdef UNICODE
  wchar_t libn[MB_CUR_MAX];
  mbstowcs(libn, libname, MB_CUR_MAX);
  lh = LoadLibrary(libn);
#else
  lh = LoadLibrary(libname);
#endif
  return lh;
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return (int)FreeLibrary(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result;
#ifdef UNICODE
  wchar_t wsym[MB_CUR_MAX];
  mbstowcs(wsym, sym, MB_CUR_MAX);
  result = GetProcAddress(lib, wsym);
#else
  result = (void*)GetProcAddress(lib, sym);
#endif
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dll";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  LPVOID lpMsgBuf;

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL
    );

  static char* str = 0;
  delete [] str;
  str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  // Free the buffer.
  LocalFree( lpMsgBuf );
  return str;
}

} // namespace KWSYS_NAMESPACE

#endif //_WIN32

// ---------------------------------------------------------------
// 4. Implementation for default UNIX machines.
// if nothing has been defined then use this
#ifndef DYNAMICLOADER_DEFINED
#define DYNAMICLOADER_DEFINED 1
// Setup for most unix machines
#include <dlfcn.h>

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return dlopen(libname, RTLD_LAZY);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  if (lib)
    {
    // The function dlclose() returns 0 on success, and non-zero on error.
    return !(int)dlclose(lib);
    }
  // else
  return 0;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* result = dlsym(lib, sym);

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".so";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return dlerror();
}

} // namespace KWSYS_NAMESPACE

#endif
<|endoftext|>


<commit_before>#include "OptionsFilename.h"
#include <stdexcept>

namespace
{
std::string filename;
bool filenameSet = false;
}

const std::string& getOptionsFilename()
{
    return filename;
}

void setOptionsFilename(const std::string & optionsFilename)
{
    if (filenameSet)
        throw std::runtime_error("Options filename already set");
    filename = optionsFilename;
    filenameSet = true;
}
<commit_msg>Use a full if/else block around an exception throw<commit_after>#include "OptionsFilename.h"
#include <stdexcept>

namespace
{
std::string filename;
bool filenameSet = false;
}

const std::string& getOptionsFilename()
{
    return filename;
}

void setOptionsFilename(const std::string & optionsFilename)
{
    if (filenameSet)
    {
        throw std::runtime_error("Options filename already set");
    }
    else
    {
        filename = optionsFilename;
        filenameSet = true;
    }
}
<|endoftext|>


<commit_before>#include "ArchiveExtractor.h"
#include "FileEntry.h"
#include <archive.h>
#include <archive_entry.h>
#include <wx/dir.h>
#include <wx/log.h>
#include <wx/stdpaths.h>

Entry *ArchiveExtractor::Create(const wxFileName &filename,
                                std::function<bool()> updateFnc) {
  wxFile inputFile(filename.GetFullPath());
  auto strTempDir = wxStandardPaths::Get().GetTempDir();

  wxFileName tempDirName(strTempDir + wxFileName::GetPathSeparator() +
                             "__ZPV__" + wxFileName::GetPathSeparator() +
                             filename.GetFullName(),
                         "");

  if (tempDirName.DirExists())
    tempDirName.Rmdir(wxPATH_RMDIR_RECURSIVE);

  if (!tempDirName.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL))
    return nullptr;

  archive_entry *entry;
  int r;

  auto a = archive_read_new();
  archive_read_support_format_all(a);

  if ((r = archive_read_open_fd(a, inputFile.fd(), 10240)))
    return nullptr;

  bool success = true;
  while ((r = archive_read_next_header(a, &entry)) != ARCHIVE_EOF) {
    success = updateFnc();
    if (!success)
      break;
    if (archive_entry_size(entry) < 0) {
      continue;
    }
    auto entryPathName = archive_entry_pathname_w(entry);

    auto entryType = archive_entry_filetype(entry);
    if (entryType != AE_IFREG && entryType != AE_IFDIR)
      continue;

    wxFileName entryFilename(entryPathName);
    wxFileName entryInTemp(tempDirName.GetFullPath() +
                           entryFilename.GetFullPath());

    entryInTemp.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);

    if (entryType == AE_IFREG) {
      wxFile targetFile(entryInTemp.GetFullPath(), wxFile::write);
      auto result = archive_read_data_into_fd(a, targetFile.fd());
      targetFile.Close();

      if (result < ARCHIVE_WARN)
        wxRemoveFile(entryInTemp.GetFullPath());
    }
  }
  archive_read_close(a);
  archive_read_free(a);

  if (!success)
    return nullptr;
  return FileEntry::Create(tempDirName, updateFnc);
}
<commit_msg>Fix the issue that the loading stuck when the extractor cannot read the file.<commit_after>#include "ArchiveExtractor.h"
#include "FileEntry.h"
#include <archive.h>
#include <archive_entry.h>
#include <wx/dir.h>
#include <wx/log.h>
#include <wx/stdpaths.h>

Entry *ArchiveExtractor::Create(const wxFileName &filename,
                                std::function<bool()> updateFnc) {
  wxFile inputFile(filename.GetFullPath());
  auto strTempDir = wxStandardPaths::Get().GetTempDir();

  wxFileName tempDirName(strTempDir + wxFileName::GetPathSeparator() +
                             "__ZPV__" + wxFileName::GetPathSeparator() +
                             filename.GetFullName(),
                         "");

  if (tempDirName.DirExists())
    tempDirName.Rmdir(wxPATH_RMDIR_RECURSIVE);

  if (!tempDirName.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL))
    return nullptr;

  archive_entry *entry;
  int r;

  auto a = archive_read_new();
  archive_read_support_format_all(a);

  if ((r = archive_read_open_fd(a, inputFile.fd(), 10240)))
    return nullptr;

  bool success = true;
  while ((r = archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
    success = updateFnc();
    if (!success)
      break;
    if (archive_entry_size(entry) < 0) {
      continue;
    }
    auto entryPathName = archive_entry_pathname_w(entry);

    auto entryType = archive_entry_filetype(entry);
    if (entryType != AE_IFREG && entryType != AE_IFDIR)
      continue;

    wxFileName entryFilename(entryPathName);
    wxFileName entryInTemp(tempDirName.GetFullPath() +
                           entryFilename.GetFullPath());

    entryInTemp.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);

    if (entryType == AE_IFREG) {
      wxFile targetFile(entryInTemp.GetFullPath(), wxFile::write);
      auto result = archive_read_data_into_fd(a, targetFile.fd());
      targetFile.Close();

      if (result < ARCHIVE_WARN)
        wxRemoveFile(entryInTemp.GetFullPath());
    }
  }
  archive_read_close(a);
  archive_read_free(a);

  if (!success)
    return nullptr;
  return FileEntry::Create(tempDirName, updateFnc);
}
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file observation_density.hpp
 * \date June 2015
 * \author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__MODEL__OBSERVATION__OBSERVATION_DENSITY_HPP
#define FL__MODEL__OBSERVATION__OBSERVATION_DENSITY_HPP

#include <fl/util/types.hpp>
#include <fl/util/traits.hpp>

namespace fl
{

template <
    typename Obsrv,
    typename State,
    int BatchSize = Eigen::Dynamic
>
class ObservationDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1> StateArray;
    typedef Eigen::Array<Real,  BatchSize, 1>  ValueArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual Real log_probability(const Obsrv& obsrv,
                                 const State& state) const = 0;

    /**
     * \return Dimension of the state variable $\f$x\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the measurement \f$h(x, w)\f$
     */
    virtual int obsrv_dimension() const = 0;

    virtual Real probability(const Obsrv& obsrv,
                             const State& state) const
    {
        return std::exp(log_probability(obsrv, state));
    }

    virtual ValueArray log_probabilities(const Obsrv& obsrv,
                                         const StateArray& states)
    {
        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(obsrv, states[i]);
        }

        return probs;
    }

    virtual ValueArray probabilities(const Obsrv& obsrv,
                                     const StateArray& states)
    {
        return log_probabilities(obsrv, states).exp();
    }
};

template <
    typename Obsrv,
    typename State,
    int BatchSize = Eigen::Dynamic
>
class SwitchingObservationDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1>  StateArray;
    typedef Eigen::Array<Real, BatchSize, 1>   ValueArray;
    typedef Eigen::Array<int, BatchSize, 1>    IndexArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual Real log_probability(const Obsrv& obsrv,
                                          const State& state,
                                          const int&   index) const = 0;

    /**
     * \return Dimension of the state variable $\f$x\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the measurement \f$h(x, w)\f$
     */
    virtual int obsrv_dimension() const = 0;

    virtual Real probability(const Obsrv& obsrv,
                             const State& state,
                             const int&   index) const
    {
        return std::exp(log_probability(obsrv, state, index));
    }

    virtual ValueArray log_probabilities(const Obsrv& obsrv,
                                         const StateArray& states,
                                         const IndexArray& indices)
    {
        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(obsrv, states[i], indices[i]);
        }

        return probs;
    }

    virtual ValueArray probabilities(const Obsrv& obsrv,
                                     const StateArray& states,
                                     const IndexArray& indices)
    {
        return log_probabilities(obsrv, states, indices).exp();
    }
};

}

#endif
<commit_msg>formatting<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file observation_density.hpp
 * \date June 2015
 * \author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__MODEL__OBSERVATION__OBSERVATION_DENSITY_HPP
#define FL__MODEL__OBSERVATION__OBSERVATION_DENSITY_HPP

#include <fl/util/types.hpp>
#include <fl/util/traits.hpp>

namespace fl
{

template <
    typename Obsrv,
    typename State,
    int BatchSize = Eigen::Dynamic
>
class ObservationDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1> StateArray;
    typedef Eigen::Array<Real,  BatchSize, 1> ValueArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual Real log_probability(const Obsrv& obsrv,
                                 const State& state) const = 0;

    /**
     * \return Dimension of the state variable $\f$x\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the measurement \f$h(x, w)\f$
     */
    virtual int obsrv_dimension() const = 0;

    virtual Real probability(const Obsrv& obsrv,
                             const State& state) const
    {
        return std::exp(log_probability(obsrv, state));
    }

    virtual ValueArray log_probabilities(const Obsrv& obsrv,
                                         const StateArray& states)
    {
        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(obsrv, states[i]);
        }

        return probs;
    }

    virtual ValueArray probabilities(const Obsrv& obsrv,
                                     const StateArray& states)
    {
        return log_probabilities(obsrv, states).exp();
    }
};

template <
    typename Obsrv,
    typename State,
    int BatchSize = Eigen::Dynamic
>
class SwitchingObservationDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1>  StateArray;
    typedef Eigen::Array<Real, BatchSize, 1>   ValueArray;
    typedef Eigen::Array<int, BatchSize, 1>    IndexArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual Real log_probability(const Obsrv& obsrv,
                                          const State& state,
                                          const int&   index) const = 0;

    /**
     * \return Dimension of the state variable $\f$x\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the measurement \f$h(x, w)\f$
     */
    virtual int obsrv_dimension() const = 0;

    virtual Real probability(const Obsrv& obsrv,
                             const State& state,
                             const int&   index) const
    {
        return std::exp(log_probability(obsrv, state, index));
    }

    virtual ValueArray log_probabilities(const Obsrv& obsrv,
                                         const StateArray& states,
                                         const IndexArray& indices)
    {
        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(obsrv, states[i], indices[i]);
        }

        return probs;
    }

    virtual ValueArray probabilities(const Obsrv& obsrv,
                                     const StateArray& states,
                                     const IndexArray& indices)
    {
        return log_probabilities(obsrv, states, indices).exp();
    }
};

}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP

#include <mapnik/segment.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/geometry.hpp>

#include <algorithm>
#include <deque>

namespace mapnik {

template <typename F1, typename F2, typename F3>
void render_building_symbolizer(mapnik::feature_impl &feature,
                                double height,
                                F1 face_func, F2 frame_func, F3 roof_func)
{
    // FIXME
    /*
    for (auto const& geom : feature.paths())
    {
        if (geom.size() > 2)
        {

            const std::unique_ptr<geometry_type> frame(new geometry_type(geometry_type::types::LineString));
            const std::unique_ptr<geometry_type> roof(new geometry_type(geometry_type::types::Polygon));
            std::deque<segment_t> face_segments;
            double x0 = 0;
            double y0 = 0;
            double x,y;
            vertex_adapter va(geom);
            va.rewind(0);
            for (unsigned cm = va.vertex(&x, &y); cm != SEG_END;
                 cm = va.vertex(&x, &y))
            {
                if (cm == SEG_MOVETO)
                {
                    frame->move_to(x,y);
                }
                else if (cm == SEG_LINETO)
                {
                    frame->line_to(x,y);
                    face_segments.push_back(segment_t(x0,y0,x,y));
                }
                else if (cm == SEG_CLOSE)
                {
                    frame->close_path();
                }
                x0 = x;
                y0 = y;
            }

            std::sort(face_segments.begin(),face_segments.end(), y_order);
            for (auto const& seg : face_segments)
            {
                const std::unique_ptr<geometry_type> faces(new geometry_type(geometry_type::types::Polygon));
                faces->move_to(std::get<0>(seg),std::get<1>(seg));
                faces->line_to(std::get<2>(seg),std::get<3>(seg));
                faces->line_to(std::get<2>(seg),std::get<3>(seg) + height);
                faces->line_to(std::get<0>(seg),std::get<1>(seg) + height);

                face_func(*faces);
                //
                frame->move_to(std::get<0>(seg),std::get<1>(seg));
                frame->line_to(std::get<0>(seg),std::get<1>(seg)+height);

            }

            va.rewind(0);
            for (unsigned cm = va.vertex(&x, &y); cm != SEG_END;
                 cm = va.vertex(&x, &y))
            {
                if (cm == SEG_MOVETO)
                {
                    frame->move_to(x,y+height);
                    roof->move_to(x,y+height);
                }
                else if (cm == SEG_LINETO)
                {
                    frame->line_to(x,y+height);
                    roof->line_to(x,y+height);
                }
                else if (cm == SEG_CLOSE)
                {
                    frame->close_path();
                    roof->close_path();
                }
            }

            frame_func(*frame);
            roof_func(*roof);
        }
    }
    */
}

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
<commit_msg>building_symbolizer - update to mapnik-geometry<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP

#include <mapnik/segment.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/geometry_impl.hpp>
#include <mapnik/geometry_type.hpp>
#include <mapnik/geometry.hpp>

#include <algorithm>
#include <deque>

namespace mapnik {

namespace detail {

template <typename F1, typename F2, typename F3>
void make_building(new_geometry::polygon const& poly, double height, F1 const& face_func, F2 const& frame_func, F3 const& roof_func)
{
    const std::unique_ptr<geometry_type> frame(new geometry_type(geometry_type::types::LineString));
    const std::unique_ptr<geometry_type> roof(new geometry_type(geometry_type::types::Polygon));
    std::deque<segment_t> face_segments;
    double x0 = 0;
    double y0 = 0;
    double x,y;
    new_geometry::polygon_vertex_adapter va(poly);
    va.rewind(0);
    for (unsigned cm = va.vertex(&x, &y); cm != SEG_END;
         cm = va.vertex(&x, &y))
    {
        if (cm == SEG_MOVETO)
        {
            frame->move_to(x,y);
        }
        else if (cm == SEG_LINETO)
        {
            frame->line_to(x,y);
            face_segments.push_back(segment_t(x0,y0,x,y));
        }
        else if (cm == SEG_CLOSE)
        {
            frame->close_path();
        }
        x0 = x;
        y0 = y;
    }

    std::sort(face_segments.begin(),face_segments.end(), y_order);
    for (auto const& seg : face_segments)
    {
        const std::unique_ptr<geometry_type> faces(new geometry_type(geometry_type::types::Polygon));
        faces->move_to(std::get<0>(seg),std::get<1>(seg));
        faces->line_to(std::get<2>(seg),std::get<3>(seg));
        faces->line_to(std::get<2>(seg),std::get<3>(seg) + height);
        faces->line_to(std::get<0>(seg),std::get<1>(seg) + height);

        face_func(*faces);
        //
        frame->move_to(std::get<0>(seg),std::get<1>(seg));
        frame->line_to(std::get<0>(seg),std::get<1>(seg)+height);
    }

    va.rewind(0);
    for (unsigned cm = va.vertex(&x, &y); cm != SEG_END;
         cm = va.vertex(&x, &y))
    {
        if (cm == SEG_MOVETO)
        {
            frame->move_to(x,y+height);
            roof->move_to(x,y+height);
        }
        else if (cm == SEG_LINETO)
        {
            frame->line_to(x,y+height);
            roof->line_to(x,y+height);
        }
        else if (cm == SEG_CLOSE)
        {
            frame->close_path();
            roof->close_path();
        }
    }

    frame_func(*frame);
    roof_func(*roof);
}

} // ns detail

template <typename F1, typename F2, typename F3>
void render_building_symbolizer(mapnik::feature_impl const& feature,
                                double height,
                                F1 face_func, F2 frame_func, F3 roof_func)
{

    auto const& geom = feature.get_geometry();
    if (geom.is<new_geometry::polygon>())
    {
        auto const& poly = geom.get<new_geometry::polygon>();
        detail::make_building(poly, height, face_func, frame_func, roof_func);
    }
    else if (geom.is<new_geometry::multi_polygon>())
    {
        auto const& multi_poly = geom.get<new_geometry::multi_polygon>();
        for (auto const& poly : multi_poly)
        {
            detail::make_building(poly, height, face_func, frame_func, roof_func);
        }
    }
}

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#ifdef TRITON_PYTHON_BINDINGS

#include <architecture.hpp>
#include <pythonBindings.hpp>
#include <pythonUtils.hpp>

/*! \page py_ARCH_page ARCH
    \brief [**python api**] All information about the ARCH python namespace.

\tableofcontents

\section ARCH_py_description Description

The ARCH namespace contains all kinds of architecture supported by Triton.

\section ARCH_py_api Python API - Items of the ARCH namespace

- **ARCH.X86**
- **ARCH.X86_64**

*/

namespace triton {
  namespace bindings {
    namespace python {

      void initArchNamespace(PyObject* archDict) {
        PyDict_SetItemString(archDict, "X86", PyLong_FromUint32(triton::arch::ARCH_X86));
        #if defined(__x86_64__) || defined(_M_X64)
        PyDict_SetItemString(archDict, "X86_64", PyLong_FromUint32(triton::arch::ARCH_X86_64));
        #endif
      }

    }; /* python namespace */
  }; /* bindings namespace */
}; /* triton namespace */

#endif /* TRITON_PYTHON_BINDINGS */
<commit_msg>#346 in progress: Export ARCH.X86_64 for x86 machine into Python namespace<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#ifdef TRITON_PYTHON_BINDINGS

#include <architecture.hpp>
#include <pythonBindings.hpp>
#include <pythonUtils.hpp>

/*! \page py_ARCH_page ARCH
    \brief [**python api**] All information about the ARCH python namespace.

\tableofcontents

\section ARCH_py_description Description

The ARCH namespace contains all kinds of architecture supported by Triton.

\section ARCH_py_api Python API - Items of the ARCH namespace

- **ARCH.X86**
- **ARCH.X86_64**

*/

namespace triton {
  namespace bindings {
    namespace python {

      void initArchNamespace(PyObject* archDict) {
        PyDict_SetItemString(archDict, "X86", PyLong_FromUint32(triton::arch::ARCH_X86));
        PyDict_SetItemString(archDict, "X86_64", PyLong_FromUint32(triton::arch::ARCH_X86_64));
      }

    }; /* python namespace */
  }; /* bindings namespace */
}; /* triton namespace */

#endif /* TRITON_PYTHON_BINDINGS */
<|endoftext|>


<commit_before>#include "notify.h"
#include "log.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>

string Notify::ApiKey="";
string Notify::ApiUrl="";

void Notify::notify(int message) {
	int * type=new int();
	*type=message;
	pthread_t notifier_thread;
	if(pthread_create(&notifier_thread, NULL, Notify::send, type)) {
		Log::logger->log("NOTIFY",ERROR) << "Can't create notifier thread " << strerror (errno) << endl;
		return;
	}
	if(pthread_detach(notifier_thread)) {
		Log::logger->log("NOTIFY",ERROR) << "Can't detach notifier thread " << strerror (errno) << endl;
	}
}

void *Notify::send(void *message) {
	Log::logger->log("NOTIFY",DEBUG) << "Notifier thread started " << endl;
	int * type=(int *) message;
	CURL *curl;
	CURLcode res;
	struct curl_slist *list = NULL;

	curl = curl_easy_init();
	if(curl) {
		string apikey="apikey: "+Notify::ApiKey;
		list = curl_slist_append(list, apikey.c_str());
		curl_easy_setopt(curl, CURLOPT_URL, Notify::ApiUrl.c_str());
		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
		curl_easy_setopt(curl, CURLOPT_POST, 1L);
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);

		res = curl_easy_perform(curl);
		if(res != CURLE_OK) {
			Log::logger->log("NOTIFY",ERROR) << "Failed to send notification " << curl_easy_strerror(res) <<endl;
		}
		curl_easy_cleanup(curl);
	}
	delete type;
}
<commit_msg>add content type<commit_after>#include "notify.h"
#include "log.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>

string Notify::ApiKey="";
string Notify::ApiUrl="";

void Notify::notify(int message) {
	int * type=new int();
	*type=message;
	pthread_t notifier_thread;
	if(pthread_create(&notifier_thread, NULL, Notify::send, type)) {
		Log::logger->log("NOTIFY",ERROR) << "Can't create notifier thread " << strerror (errno) << endl;
		return;
	}
	if(pthread_detach(notifier_thread)) {
		Log::logger->log("NOTIFY",ERROR) << "Can't detach notifier thread " << strerror (errno) << endl;
	}
}

void *Notify::send(void *message) {
	Log::logger->log("NOTIFY",DEBUG) << "Notifier thread started " << endl;
	int * type=(int *) message;
	CURL *curl;
	CURLcode res;
	struct curl_slist *list = NULL;

	curl = curl_easy_init();
	if(curl) {
		string apikey="apikey: "+Notify::ApiKey;
		list = curl_slist_append(list, apikey.c_str());
		list = curl_slist_append(list, "Content-Type: application/json");
		curl_easy_setopt(curl, CURLOPT_URL, Notify::ApiUrl.c_str());
		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
		curl_easy_setopt(curl, CURLOPT_POST, 1L);
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);

		res = curl_easy_perform(curl);
		if(res != CURLE_OK) {
			Log::logger->log("NOTIFY",ERROR) << "Failed to send notification " << curl_easy_strerror(res) <<endl;
		}
		curl_easy_cleanup(curl);
	}
	delete type;
}
<|endoftext|>