<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// simple_optimizer.cpp
//
// Identification: /peloton/src/optimizer/simple_optimizer.cpp
//
// Copyright (c) 2016, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "optimizer/simple_optimizer.h"
#include "parser/peloton/abstract_parse.h"
#include "planner/abstract_plan.h"
#include "planner/drop_plan.h"
#include "planner/seq_scan_plan.h"

#include "common/logger.h"

#include <memory>

namespace peloton {
namespace planner {
class AbstractPlan;
}
namespace optimizer {

SimpleOptimizer::SimpleOptimizer() {
}
;

SimpleOptimizer::~SimpleOptimizer() {
}
;

std::shared_ptr<planner::AbstractPlan> SimpleOptimizer::BuildPlanTree(
    const std::unique_ptr<parser::AbstractParse>& parse_tree) {

  std::shared_ptr<planner::AbstractPlan> plan_tree;
  if (parse_tree.get() == nullptr)
    return plan_tree;

  std::unique_ptr<planner::AbstractPlan> child_plan = nullptr;

  // TODO: Transform the parse tree

  // One to one Mapping
  auto parse_item_node_type = parse_tree->GetParseNodeType();

  switch (parse_item_node_type) {
    case PARSE_NODE_TYPE_DROP: {
      std::unique_ptr<planner::AbstractPlan> child_DropPlan(
          new planner::DropPlan("department-table"));
      child_plan = std::move(child_DropPlan);
    }
      break;

    case PARSE_NODE_TYPE_SCAN: {
      std::unique_ptr<planner::AbstractPlan> child_SeqScanPlan(
          new planner::SeqScanPlan());
      child_plan = std::move(child_SeqScanPlan);
    }
      break;

    default:
      LOG_INFO("Unsupported Parse Node Type");
  }

// Need to recurse and give base case. for every child in parse tree.

  if (child_plan != nullptr) {
    if (plan_tree != nullptr)
      plan_tree->AddChild(std::move(child_plan));
    else
      plan_tree = std::move(child_plan);
  }

  auto &children = parse_tree->GetChildren();
  for (auto &child : children) {
    std::shared_ptr<planner::AbstractPlan> child_parse(BuildPlanTree(child));
    child_plan = std::move(child_parse);
  }
  return plan_tree;
}

}  // namespace optimizer
}  // namespace peloton
<commit_msg>Additional fix for SimpleOptimizer<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// simple_optimizer.cpp
//
// Identification: /peloton/src/optimizer/simple_optimizer.cpp
//
// Copyright (c) 2016, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "optimizer/simple_optimizer.h"
#include "parser/peloton/abstract_parse.h"
#include "planner/abstract_plan.h"
#include "planner/drop_plan.h"
#include "planner/seq_scan_plan.h"

#include "common/logger.h"

#include <memory>

namespace peloton {
namespace planner {
class AbstractPlan;
}
namespace optimizer {

SimpleOptimizer::SimpleOptimizer() {
}
;

SimpleOptimizer::~SimpleOptimizer() {
}
;

std::shared_ptr<planner::AbstractPlan> SimpleOptimizer::BuildPlanTree(
    const std::unique_ptr<parser::AbstractParse>& parse_tree) {

  std::shared_ptr<planner::AbstractPlan> plan_tree;
  if (parse_tree.get() == nullptr)
    return plan_tree;

  std::unique_ptr<planner::AbstractPlan> child_plan = nullptr;

  // TODO: Transform the parse tree

  // One to one Mapping
  auto parse_item_node_type = parse_tree->GetParseNodeType();

  switch (parse_item_node_type) {
    case PARSE_NODE_TYPE_DROP: {
      std::unique_ptr<planner::AbstractPlan> child_DropPlan(
          new planner::DropPlan("department-table"));
      child_plan = std::move(child_DropPlan);
    }
      break;

    case PARSE_NODE_TYPE_SCAN: {
      std::unique_ptr<planner::AbstractPlan> child_SeqScanPlan(
          new planner::SeqScanPlan());
      child_plan = std::move(child_SeqScanPlan);
    }
      break;

    default:
      LOG_INFO("Unsupported Parse Node Type");
  }

// Need to recurse and give base case. for every child in parse tree.

  if (child_plan != nullptr) {
    if (plan_tree != nullptr)
      plan_tree->AddChild(std::move(child_plan));
    else
      plan_tree = std::move(child_plan);
  }

  auto &children = parse_tree->GetChildren();
  for (auto &child : children) {
    auto holder = BuildPlanTree(child)
    std::unique_ptr<planner::AbstractPlan> child_parse(std::move(holder));
    child_plan = std::move(child_parse);
  }
  return plan_tree;
}

}  // namespace optimizer
}  // namespace peloton
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <qi/anyobject.hpp>
#include "transportserver.hpp"
#include <qi/messaging/serviceinfo.hpp>
#include <qi/type/objecttypebuilder.hpp>
#include "server.hpp"
#include "objectregistrar.hpp"
#include <qi/os.hpp>
#include <boost/thread/mutex.hpp>
#include "servicedirectoryclient.hpp"
#include "session_p.hpp"
#include <qi/scoped.hpp>

qiLogCategory("qimessaging.objectregistrar");

namespace qi {

  BoundService::~BoundService()
  {
    // if we own the object, destroy it asynchronously because it may hold the
    // last reference to Session which leads to a deadlock (Session can't be
    // destroyed because it is calling us)
    if (object.unique())
      qi::async(boost::bind(&qi::detail::hold<qi::AnyObject>, object));
  }

  ObjectRegistrar::ObjectRegistrar(ServiceDirectoryClient *sdClient, bool enforceAuth)
    : Server(enforceAuth)
    , _sdClient(sdClient)
    , _id(qi::os::generateUuid())
  {
    _server.endpointsChanged.connect(boost::bind(&ObjectRegistrar::updateServiceInfo, this));
  }

  ObjectRegistrar::~ObjectRegistrar()
  {
    _dying = true;
    qi::Trackable<Server>::destroy();
  }

  void ObjectRegistrar::close()
  {
    BoundServiceMap services;
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      services = _services;
    }
    for (BoundServiceMap::reverse_iterator iter = services.rbegin();
        iter != services.rend();
        ++iter)
      unregisterService(iter->first);
    Server::close();
  }

  void serviceReady(qi::Future<void> fut, qi::Promise<unsigned int> result, unsigned int idx) {
    if (fut.hasError()) {
      result.setError(fut.error());
      return;
    }
    result.setValue(idx);
  }

  void ObjectRegistrar::updateServiceInfo()
  {
    qi::ServiceInfo si;
    si.setProcessId(qi::os::getpid());
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(Server::endpoints());
    si.setSessionId(_id);

    boost::mutex::scoped_lock sl(_servicesMutex);
    std::map<unsigned, BoundService>::iterator it = _services.begin();
    if (it != _services.end()) {
      BoundService& bs = it->second;
      si.setServiceId(bs.id);
      si.setName(bs.name);
      _sdClient->updateServiceInfo(si);
    }
  }

  void ObjectRegistrar::onFutureFinished(qi::Future<unsigned int> fut, int id, qi::Promise<unsigned int> result)
  {
    auto eraseRequest = scoped([id, this]{
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      _registerServiceRequest.erase(id);
    });

    if (fut.hasError()) {
      result.setError(fut.error());
      return;
    }
    qi::ServiceInfo              si;
    RegisterServiceMap::iterator it;

    {
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      it = _registerServiceRequest.find(id);
      if (it != _registerServiceRequest.end())
        si = it->second.second;
    }
    unsigned int idx = fut.value();
    si.setServiceId(idx);
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundService bs;
      bs.id          = idx;
      bs.object      = it->second.first;
      bs.serviceInfo = si;
      bs.name        = si.name();
      BoundServiceMap::iterator it;
      it = _services.find(idx);
      if (it != _services.end()) {
        qiLogError() << "A service is already registered with that id:" << idx;
        result.setError("Service already registered.");
        return;
      }
      _services[idx] = bs;
      //todo register the object on the server (find a better way)
      Server::addObject(idx, bs.object);
    }

    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      _serviceNameToIndex[si.name()] = idx;
    }

    // ack the Service directory to tell that we are ready
    qi::Future<void> fut2 = _sdClient->serviceReady(idx);
    fut2.connect(boost::bind(&serviceReady, _1, result, idx));
  }

  qi::Future<unsigned int> ObjectRegistrar::registerService(const std::string &name, qi::AnyObject obj)
  {
    if (Server::endpoints().empty()) {
      qiLogError() << "Could not register service: " << name << " because the current server has not endpoint";
      return qi::Future<unsigned int>();
    }
    qi::ServiceInfo si;
    si.setName(name);
    si.setProcessId(qi::os::getpid());
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(Server::endpoints());
    si.setSessionId(_id);

    int id = ++_registerServiceRequestIndex;
    {
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      _registerServiceRequest[id] = std::make_pair(obj, si);
    }

    qi::Promise<unsigned int> prom;
    qi::Future<unsigned int>  future;
    future = _sdClient->registerService(si);
    future.connect(boost::bind<void>(&ObjectRegistrar::onFutureFinished, this, _1, id, prom));

    return prom.future();
  };

  qi::Future<void> ObjectRegistrar::unregisterService(unsigned int idx)
  {
    qi::Future<void> future = _sdClient->unregisterService(idx);

    std::string name;
    {
      // Create a local variable to keep the underlying bound anyobject alive outside the map.
      // It allows us to remove the iterator map without deleting the underlying anyobject
      BoundService serviceToRemove;
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(idx);
      if (it != _services.end())
      {
        name = it->second.name;
        if (!it->second.object.unique())
        {
          qiLogVerbose() << "Some references to service #" << idx
                                             << " are still held!";
        }
        serviceToRemove = std::move(it->second);
        _services.erase(it);
      }
      else
      {
        qiLogVerbose() << "Can't find name associated to id:" << idx;
      }
      Server::removeObject(idx);
    }
    if (!name.empty())
    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      ServiceNameToIndexMap::iterator it = _serviceNameToIndex.find(name);
      if (it != _serviceNameToIndex.end())
        _serviceNameToIndex.erase(it);
      else
        qiLogVerbose() << "Can't find idx associated to name :" << name;
    }
    return future;
  }

  std::vector<qi::ServiceInfo> ObjectRegistrar::registeredServices() {
    std::vector<qi::ServiceInfo> ssi;
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.begin();
      for (; it != _services.end(); ++it) {
        //drop 0 => it's the server itself.
        if (it->first == 0)
          continue;
        ssi.push_back(it->second.serviceInfo);
      }
    }
    return ssi;
  }

  //return 0 on error (0 is the server which have no name)
  unsigned int ObjectRegistrar::objectId(const std::string &name)
  {
    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      ServiceNameToIndexMap::iterator it;
      it = _serviceNameToIndex.find(name);
      if (it != _serviceNameToIndex.end())
        return it->second;
    }
    return 0;
  }

  qi::ServiceInfo ObjectRegistrar::registeredService(const std::string &service) {
    unsigned int serviceId = objectId(service);

    if (!serviceId)
      return qi::ServiceInfo();

    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(serviceId);
      if (it != _services.end())
        return it->second.serviceInfo;
    }
    return qi::ServiceInfo();
  }

  qi::AnyObject ObjectRegistrar::registeredServiceObject(const std::string &service) {
    unsigned int serviceId = objectId(service);
    if (!serviceId)
      return qi::AnyObject();

    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(serviceId);
      if (it != _services.end())
        return it->second.object;
    }
    return AnyObject();
  }

  void ObjectRegistrar::registerSocket(MessageSocketPtr socket)
  {
    onTransportServerNewConnection(socket, false);
  }

  void ObjectRegistrar::open()
  {
    Server::open();
  }

}
<commit_msg>messaging: Fixes lifetime issues in ObjectRegistrar<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/
#include <qi/anyobject.hpp>
#include "transportserver.hpp"
#include <qi/messaging/serviceinfo.hpp>
#include <qi/type/objecttypebuilder.hpp>
#include "server.hpp"
#include "objectregistrar.hpp"
#include <qi/os.hpp>
#include <boost/thread/mutex.hpp>
#include "servicedirectoryclient.hpp"
#include "session_p.hpp"
#include <qi/scoped.hpp>

qiLogCategory("qimessaging.objectregistrar");

namespace qi {

  BoundService::~BoundService()
  {
    // if we own the object, destroy it asynchronously because it may hold the
    // last reference to Session which leads to a deadlock (Session can't be
    // destroyed because it is calling us)
    if (object.unique())
      qi::async(boost::bind(&qi::detail::hold<qi::AnyObject>, object));
  }

  ObjectRegistrar::ObjectRegistrar(ServiceDirectoryClient *sdClient, bool enforceAuth)
    : Server(enforceAuth)
    , _sdClient(sdClient)
    , _id(qi::os::generateUuid())
  {
    _server.endpointsChanged.connect(track(boost::bind(&ObjectRegistrar::updateServiceInfo, this),
                                           static_cast<Trackable<Server>*>(this)));
  }

  ObjectRegistrar::~ObjectRegistrar()
  {
    _dying = true;
    qi::Trackable<Server>::destroy();
  }

  void ObjectRegistrar::close()
  {
    BoundServiceMap services;
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      services = _services;
    }
    for (BoundServiceMap::reverse_iterator iter = services.rbegin();
        iter != services.rend();
        ++iter)
      unregisterService(iter->first);
    Server::close();
  }

  void serviceReady(qi::Future<void> fut, qi::Promise<unsigned int> result, unsigned int idx) {
    if (fut.hasError()) {
      result.setError(fut.error());
      return;
    }
    result.setValue(idx);
  }

  void ObjectRegistrar::updateServiceInfo()
  {
    qi::ServiceInfo si;
    si.setProcessId(qi::os::getpid());
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(Server::endpoints());
    si.setSessionId(_id);

    boost::mutex::scoped_lock sl(_servicesMutex);
    std::map<unsigned, BoundService>::iterator it = _services.begin();
    if (it != _services.end()) {
      BoundService& bs = it->second;
      si.setServiceId(bs.id);
      si.setName(bs.name);
      _sdClient->updateServiceInfo(si);
    }
  }

  void ObjectRegistrar::onFutureFinished(qi::Future<unsigned int> fut, int id, qi::Promise<unsigned int> result)
  {
    auto eraseRequest = scoped([id, this]{
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      _registerServiceRequest.erase(id);
    });

    if (fut.hasError()) {
      result.setError(fut.error());
      return;
    }
    qi::ServiceInfo              si;
    RegisterServiceMap::iterator it;

    {
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      it = _registerServiceRequest.find(id);
      if (it != _registerServiceRequest.end())
        si = it->second.second;
    }
    unsigned int idx = fut.value();
    si.setServiceId(idx);
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundService bs;
      bs.id          = idx;
      bs.object      = it->second.first;
      bs.serviceInfo = si;
      bs.name        = si.name();
      BoundServiceMap::iterator it;
      it = _services.find(idx);
      if (it != _services.end()) {
        qiLogError() << "A service is already registered with that id:" << idx;
        result.setError("Service already registered.");
        return;
      }
      _services[idx] = bs;
      //todo register the object on the server (find a better way)
      Server::addObject(idx, bs.object);
    }

    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      _serviceNameToIndex[si.name()] = idx;
    }

    // ack the Service directory to tell that we are ready
    qi::Future<void> fut2 = _sdClient->serviceReady(idx);
    fut2.connect(boost::bind(&serviceReady, _1, result, idx));
  }

  qi::Future<unsigned int> ObjectRegistrar::registerService(const std::string &name, qi::AnyObject obj)
  {
    if (Server::endpoints().empty()) {
      qiLogError() << "Could not register service: " << name << " because the current server has not endpoint";
      return qi::Future<unsigned int>();
    }
    qi::ServiceInfo si;
    si.setName(name);
    si.setProcessId(qi::os::getpid());
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(Server::endpoints());
    si.setSessionId(_id);

    int id = ++_registerServiceRequestIndex;
    {
      boost::mutex::scoped_lock sl(_registerServiceRequestMutex);
      _registerServiceRequest[id] = std::make_pair(obj, si);
    }

    qi::Promise<unsigned int> prom;
    qi::Future<unsigned int>  future;
    future = _sdClient->registerService(si);
    future.connect(track(boost::bind<void>(&ObjectRegistrar::onFutureFinished, this, _1, id, prom),
                         static_cast<Trackable<Server>*>(this)));

    return prom.future();
  };

  qi::Future<void> ObjectRegistrar::unregisterService(unsigned int idx)
  {
    qi::Future<void> future = _sdClient->unregisterService(idx);

    std::string name;
    {
      // Create a local variable to keep the underlying bound anyobject alive outside the map.
      // It allows us to remove the iterator map without deleting the underlying anyobject
      BoundService serviceToRemove;
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(idx);
      if (it != _services.end())
      {
        name = it->second.name;
        if (!it->second.object.unique())
        {
          qiLogVerbose() << "Some references to service #" << idx
                                             << " are still held!";
        }
        serviceToRemove = std::move(it->second);
        _services.erase(it);
      }
      else
      {
        qiLogVerbose() << "Can't find name associated to id:" << idx;
      }
      Server::removeObject(idx);
    }
    if (!name.empty())
    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      ServiceNameToIndexMap::iterator it = _serviceNameToIndex.find(name);
      if (it != _serviceNameToIndex.end())
        _serviceNameToIndex.erase(it);
      else
        qiLogVerbose() << "Can't find idx associated to name :" << name;
    }
    return future;
  }

  std::vector<qi::ServiceInfo> ObjectRegistrar::registeredServices() {
    std::vector<qi::ServiceInfo> ssi;
    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.begin();
      for (; it != _services.end(); ++it) {
        //drop 0 => it's the server itself.
        if (it->first == 0)
          continue;
        ssi.push_back(it->second.serviceInfo);
      }
    }
    return ssi;
  }

  //return 0 on error (0 is the server which have no name)
  unsigned int ObjectRegistrar::objectId(const std::string &name)
  {
    {
      boost::mutex::scoped_lock sl(_serviceNameToIndexMutex);
      ServiceNameToIndexMap::iterator it;
      it = _serviceNameToIndex.find(name);
      if (it != _serviceNameToIndex.end())
        return it->second;
    }
    return 0;
  }

  qi::ServiceInfo ObjectRegistrar::registeredService(const std::string &service) {
    unsigned int serviceId = objectId(service);

    if (!serviceId)
      return qi::ServiceInfo();

    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(serviceId);
      if (it != _services.end())
        return it->second.serviceInfo;
    }
    return qi::ServiceInfo();
  }

  qi::AnyObject ObjectRegistrar::registeredServiceObject(const std::string &service) {
    unsigned int serviceId = objectId(service);
    if (!serviceId)
      return qi::AnyObject();

    {
      boost::mutex::scoped_lock sl(_servicesMutex);
      BoundServiceMap::iterator it = _services.find(serviceId);
      if (it != _services.end())
        return it->second.object;
    }
    return AnyObject();
  }

  void ObjectRegistrar::registerSocket(MessageSocketPtr socket)
  {
    onTransportServerNewConnection(socket, false);
  }

  void ObjectRegistrar::open()
  {
    Server::open();
  }

}
<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <math.h>
#include <iostream>

#include "angle.hpp"
#include "global_config.hpp"
#include "error.hpp"

// Hide all of these constants from the rest of the world
namespace {
    mocc::float_t mu_base[] = {0.577350269189626, 0.350021000000000,
        0.266636000000000, 0.218218218218218, 0.192450089729876,
        0.174077655955702, 0.161575000000000, 0.149071198499989};

    mocc::float_t w_unique[] = {
        1.0,
        1.0/3.0,
        0.1761262, 0.1572071,
        0.1209876, 0.0907408, 0.0925925,
        0.0893043, 0.0725281, 0.0450455, 0.0539274,
        0.0707734, 0.0558760, 0.0373436, 0.0502654, 0.0258553,
        0.0580031, 0.0488943, 0.0228095, 0.0393955, 0.0380920, 0.0258382, 0.0082759,
        0.0489967, 0.0413235, 0.0203158, 0.0265468, 0.0378883, 0.0135404, 0.0326129, 0.0103825
    };

    int w_offset[] = {0, 1, 2, 4, 7, 11, 16, 23};

    int w_map[] = {
        1,
        1, 1, 1,
        1, 2, 2, 1, 2, 1,
        1, 2, 2, 2, 3, 2, 1, 2, 2, 1,
        1, 2, 2, 3, 4, 3, 2, 4, 4, 2, 1, 2, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 3, 6, 7, 6, 3, 2, 5, 6, 6, 5, 2, 1, 2, 3, 4, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 4, 7, 8, 7, 4, 3, 6, 8, 8, 6, 3, 2, 5, 6, 7, 6, 5, 2, 1, 2, 3, 4, 4, 3, 2, 1
    };

    int w_map_offset[] = { 0, 1, 4, 10, 20, 35, 63 };
}

// Produce a vector of angles matching the level-symmetric quadrature of order
// 'order'
std::vector<mocc::Angle> GenSn( int order ){

    std::cout << "Generating Sn quadrature of order " << order << std::endl;

    if( order%2 != 0 ) {
        Error("Sn quadrature order must be even.");
    }
    if( order > 16 ) {
        Error("Max supported Sn quadrature order is 16.");
    }

    // n is the number of base cosines to use
    const int n = order/2;

    // set up the list of base cosines
    mocc::VecF mu;
    mu.push_back(mu_base[n-1]);
    if( order > 2) {
        const mocc::float_t delta_mu = 2.0 * ( 1.0 -
                3.0*(mu[0]*mu[0]) ) / (mocc::float_t)(order-2);
        for (int i=1; i<n; i++) {
            mu.push_back( sqrt(mu[0]*mu[0] + i*delta_mu) );
        }
    }

    // Alias the w_unique array to get a slice for the order we are interested
    // in.
    mocc::float_t* weights = &w_unique[w_offset[n-1]];
    // Alias into the w_map to get our indices
    int* map = &w_map[w_map_offset[n-1]];

    // Apply the permutations of the base cosines to get actual angles. We will
    // do this once for the first octant, then reflect around.
    std::vector<mocc::Angle> angles;
    int k=0;
    for( int i=0; i<n; i++ ) {
        for( int j=0; j<=i; j++ ) {

            mocc::Angle angle( mu[i-j],
                               mu[j],
                               mu[n-i-1] );

            // Look up and apply the proper weight
            angle.weight = weights[map[k]-1];
std::cout << angle.weight << std::endl;

            angles.push_back(angle);
            k++;
        }
    }

    return angles;

}
<commit_msg>Fix bug in angle construction in LS quadrature<commit_after>#pragma once

#include <vector>
#include <math.h>
#include <iostream>

#include "angle.hpp"
#include "global_config.hpp"
#include "error.hpp"

// Hide all of these constants from the rest of the world
namespace {
    mocc::float_t mu_base[] = {0.577350269189626, 0.350021000000000,
        0.266636000000000, 0.218218218218218, 0.192450089729876,
        0.174077655955702, 0.161575000000000, 0.149071198499989};

    mocc::float_t w_unique[] = {
        1.0,
        1.0/3.0,
        0.1761262, 0.1572071,
        0.1209876, 0.0907408, 0.0925925,
        0.0893043, 0.0725281, 0.0450455, 0.0539274,
        0.0707734, 0.0558760, 0.0373436, 0.0502654, 0.0258553,
        0.0580031, 0.0488943, 0.0228095, 0.0393955, 0.0380920, 0.0258382, 0.0082759,
        0.0489967, 0.0413235, 0.0203158, 0.0265468, 0.0378883, 0.0135404, 0.0326129, 0.0103825
    };

    int w_offset[] = {0, 1, 2, 4, 7, 11, 16, 23};

    int w_map[] = {
        1,
        1, 1, 1,
        1, 2, 2, 1, 2, 1,
        1, 2, 2, 2, 3, 2, 1, 2, 2, 1,
        1, 2, 2, 3, 4, 3, 2, 4, 4, 2, 1, 2, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 3, 6, 7, 6, 3, 2, 5, 6, 6, 5, 2, 1, 2, 3, 4, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 4, 7, 8, 7, 4, 3, 6, 8, 8, 6, 3, 2, 5, 6, 7, 6, 5, 2, 1, 2, 3, 4, 4, 3, 2, 1
    };

    int w_map_offset[] = { 0, 1, 4, 10, 20, 35, 63 };
}

// Produce a vector of angles matching the level-symmetric quadrature of order
// 'order'
std::vector<mocc::Angle> GenSn( int order ){

    std::cout << "Generating Sn quadrature of order " << order << std::endl;

    if( order%2 != 0 ) {
        Error("Sn quadrature order must be even.");
    }
    if( order > 16 ) {
        Error("Max supported Sn quadrature order is 16.");
    }

    // n is the number of base cosines to use
    const int n = order/2;

    // set up the list of base cosines
    mocc::VecF mu;
    mu.push_back(mu_base[n-1]);
    cout << mu[0] << " " << mu_base[0] << endl;
    if( order > 2) {
        const mocc::float_t delta_mu = 2.0 * ( 1.0 -
                3.0*(mu[0]*mu[0]) ) / (mocc::float_t)(order-2);
        for (int i=1; i<n; i++) {
            mu.push_back( sqrt(mu[0]*mu[0] + i*delta_mu) );
        }
    }

    // Alias the w_unique array to get a slice for the order we are interested
    // in.
    mocc::float_t* weights = &w_unique[w_offset[n-1]];
    // Alias into the w_map to get our indices
    int* map = &w_map[w_map_offset[n-1]];

    // Apply the permutations of the base cosines to get actual angles. We will
    // do this once for the first octant, then reflect around.
    std::vector<mocc::Angle> angles;
    int k=0;
    for( int i=0; i<n; i++ ) {
        for( int j=0; j<=i; j++ ) {
            mocc::Angle angle( mu[i-j],
                               mu[j],
                               mu[n-i-1],
                               weights[map[k]-1]);

            // Look up and apply the proper weight
//            angle.weight = weights[map[k]-1];

            angles.push_back(angle);
            k++;
        }
    }

    return angles;

}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <list>
#include <thread>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
using namespace::boost::asio;

#define DUMP_VAR(x) std::cout << __func__ << #x << "=<" << x <<">" << std::endl;

std::list<std::string> gCarCommand;

std::mutex mtx;
std::condition_variable cv;

void push_command(const std::string &cmd)
{
   std::unique_lock<std::mutex> lock(mtx);
   if("init"==cmd) {
      gCarCommand.clear();
   }
   if("top"==cmd) {
      gCarCommand.push_back("a.speed:40000\n");
      gCarCommand.push_back("a.turn:fwd\n");
      gCarCommand.push_back("b.speed:40000\n");
      gCarCommand.push_back("b.turn:fwd\n");
      gCarCommand.push_back("c.speed:40000\n");
      gCarCommand.push_back("c.turn:fwd\n");
      gCarCommand.push_back("d.speed:40000\n");
      gCarCommand.push_back("d.turn:fwd\n");
      gCarCommand.push_back("run\n");
   }
   cv.notify_one();
}

void read_dummy()
{
  ::system("cat /dev/ttyUSB0");
}

void handle_read_content(){
   static int i = 0;
   DUMP_VAR(i++);
}

void car_uart_main(void)
{
    io_service io_;
    serial_port port_( io_, "/dev/ttyUSB0" );
    port_.set_option( serial_port_base::baud_rate(115200));
    //std::thread thr_read(read_dummy);
    //thr_read.detach();
    while(true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock);
        if(false == gCarCommand.empty()) {
           for(auto cmd:gCarCommand) {
              boost::asio::write(port_, boost::asio::buffer(cmd.c_str(), cmd.size()));
              boost::asio::streambuf b;
              boost::asio::async_read(port_,streambuf,boost::bind(&handle_read_content));
           }
           gCarCommand.clear();
        }
    }
}

<commit_msg>Update car.entry.cpp<commit_after>#include <string>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <list>
#include <thread>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
using namespace::boost::asio;

#define DUMP_VAR(x) std::cout << __func__ << #x << "=<" << x <<">" << std::endl;

std::list<std::string> gCarCommand;

std::mutex mtx;
std::condition_variable cv;

void push_command(const std::string &cmd)
{
   std::unique_lock<std::mutex> lock(mtx);
   if("init"==cmd) {
      gCarCommand.clear();
   }
   if("top"==cmd) {
      gCarCommand.push_back("a.speed:10000\n");
      gCarCommand.push_back("a.turn:fwd\n");
      gCarCommand.push_back("b.speed:10000\n");
      gCarCommand.push_back("b.turn:fwd\n");
      gCarCommand.push_back("c.speed:10000\n");
      gCarCommand.push_back("c.turn:fwd\n");
      gCarCommand.push_back("d.speed:10000\n");
      gCarCommand.push_back("d.turn:fwd\n");
      gCarCommand.push_back("run\n");
   }
   if("buttom"==cmd) {
      gCarCommand.push_back("a.speed:10000\n");
      gCarCommand.push_back("a.turn:rev\n");
      gCarCommand.push_back("b.speed:10000\n");
      gCarCommand.push_back("b.turn:rev\n");
      gCarCommand.push_back("c.speed:10000\n");
      gCarCommand.push_back("c.turn:rev\n");
      gCarCommand.push_back("d.speed:10000\n");
      gCarCommand.push_back("d.turn:rev\n");
      gCarCommand.push_back("run\n");
   }
   if("left"==cmd) {
      gCarCommand.push_back("a.speed:10000\n");
      gCarCommand.push_back("a.turn:fwd\n");
      gCarCommand.push_back("b.speed:10000\n");
      gCarCommand.push_back("b.turn:rev\n");
      gCarCommand.push_back("c.speed:10000\n");
      gCarCommand.push_back("c.turn:fwd\n");
      gCarCommand.push_back("d.speed:10000\n");
      gCarCommand.push_back("d.turn:rev\n");
      gCarCommand.push_back("run\n");
   }
   if("left"==cmd) {
      gCarCommand.push_back("a.speed:10000\n");
      gCarCommand.push_back("a.turn:rev\n");
      gCarCommand.push_back("b.speed:10000\n");
      gCarCommand.push_back("b.turn:fwd\n");
      gCarCommand.push_back("c.speed:10000\n");
      gCarCommand.push_back("c.turn:rev\n");
      gCarCommand.push_back("d.speed:10000\n");
      gCarCommand.push_back("d.turn:fwd\n");
      gCarCommand.push_back("run\n");
   }
   if("stop"==cmd) {
      gCarCommand.push_back("stop\n");
   }
   cv.notify_one();
}

void read_dummy()
{
  ::system("cat /dev/ttyUSB0");
}

void handle_read_content(){
   static int i = 0;
   DUMP_VAR(i++);
}

void car_uart_main(void)
{
    io_service io_;
    serial_port port_( io_, "/dev/ttyUSB0" );
    port_.set_option( serial_port_base::baud_rate(115200));
    //std::thread thr_read(read_dummy);
    //thr_read.detach();
    while(true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock);
        if(false == gCarCommand.empty()) {
           for(auto cmd:gCarCommand) {
              boost::asio::write(port_, boost::asio::buffer(cmd.c_str(), cmd.size()));
              boost::asio::streambuf b;
              boost::asio::async_read(port_,streambuf,boost::bind(&handle_read_content));
           }
           gCarCommand.clear();
        }
    }
}

<|endoftext|>


<commit_before>/************************************************************************************
This source file is part of the Theora Video Playback Library
For latest info, see http://libtheoraplayer.sourceforge.net/
*************************************************************************************
Copyright (c) 2008-2012 Kresimir Spes (kspes@cateia.com)
This program is free software; you can redistribute it and/or modify it under
the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php
*************************************************************************************/
#define THEORAUTIL_NOMACROS
#include <theoraplayer/TheoraException.h>
#undef exception_cls
#include <theoraplayer/TheoraDataSource.h>
#include <theoraplayer/TheoraPlayer.h>
#include <theoraplayer/TheoraTimer.h>
#include <april/RenderSystem.h>
#include <april/Texture.h>
#include <aprilui/aprilui.h>
#include <aprilui/Dataset.h>
#include <aprilui/NullImage.h>
#include <aprilui/Texture.h>
#include <xal/AudioManager.h>
#include <xal/Player.h>
#include "aprilvideo.h"

namespace aprilvideo
{
	static TheoraVideoManager* gVideoManager = NULL;
	static int gRefCount = 0, gNumWorkerThreads = 1;
	hstr logTag = "aprilvideo", defaultFileExtension = ".ogv";

	static int _nextPow2(int x)
	{
		int y;
		for (y = 1; y < x; y *= 2);
		return y;
	}

	class AudioVideoTimer : public TheoraTimer
	{
		float mSyncOffset;
		xal::Player* mPlayer;
		float mT;
		bool mDisabledAudio;
	public:
		AudioVideoTimer(xal::Player* player, float sync_offset)
		{
			mSyncOffset = sync_offset;
			mPlayer = player;
			mT = 0;
			static hstr audiosystem = xal::mgr->getName(); // Disabled" audio system doesn't sync audio & video
			mDisabledAudio = (audiosystem == "Disabled");
		}

		void update(float time_increase)
		{
			if (!mDisabledAudio)
			{
				if (mPlayer->isPlaying())
					mTime = mPlayer->getTimePosition() - mSyncOffset;
				else
					mTime += time_increase;
			}
			else
			{
				mT += time_increase;
				mTime = mT - mSyncOffset;
			}
		}
	};

	VideoObject::VideoObject(chstr name, grect rect) : aprilui::ImageBox(name, rect)
	{
		mUsingAVFoundation = 0;
		mUseAlpha = 0;
		mPrevDoneFlag = 0;
		mLoop = 1;
		mSpeed = 1.0f;
		mClip = NULL;
		mVideoImage = NULL;
		mTexture = NULL;
		mTimer = NULL;
		mSound = NULL;
		mAudioPlayer = NULL;
		mAudioSyncOffset = 0;
		gRefCount++;
		mAlphaPauseTreshold = 0;
		mPrevFrameNumber = 0;
		mSeeked = 0;
		if (!gVideoManager)
		{
			gVideoManager = new TheoraVideoManager(gNumWorkerThreads);
			std::vector<std::string> lst = gVideoManager->getSupportedDecoders();
			foreach (std::string, it, lst)
			{
				if (*it == "AVFoundation") defaultFileExtension = ".mp4";
			}
		}
	}

	aprilui::Object* VideoObject::createInstance(chstr name, grect rect)
	{
		return new VideoObject(name, rect);
	}

	void VideoObject::notifyEvent(chstr name, void* params)
	{
		if (name == "AttachToObject")
		{
			if (mImage != mVideoImage)
			{
				mImage = mDataset->getImage("null");
			}
		}
		ImageBox::notifyEvent(name, params);
	}

	void VideoObject::destroyResources()
	{
		if (mVideoImage)
		{
			delete mVideoImage;
			mVideoImage = NULL;
			mImage = mDataset->getImage("null");
		}
		if (mTexture)
		{
			delete mTexture;
			mTexture = NULL;
		}
		if (mClip)
		{
			gVideoManager->destroyVideoClip(mClip);
			mClip = NULL;
		}
		if (mAudioPlayer)
		{
			xal::mgr->destroyPlayer(mAudioPlayer);
			mAudioPlayer = NULL;
		}
		if (mSound)
		{
			xal::mgr->destroySound(mSound);
			mSound = NULL;
		}

		if (mTimer)
		{
			delete mTimer;
			mTimer = NULL;
		}
	}

	VideoObject::~VideoObject()
	{
		gRefCount--;
		destroyResources();
		if (gRefCount <= 0 && gVideoManager)
		{
			delete gVideoManager;
			gVideoManager = NULL;
		}
	}

	void VideoObject::update(float k)
	{
		ImageBox::update(k);
		if (mClip == NULL && mClipName != "")
		{
			destroyResources();
			hstr path = mDataset->getFilePath() + "/video/" + mClipName;
			if (!path.ends_with(".ogg") && !path.ends_with(".ogv") && !path.ends_with(".mp4")) path += defaultFileExtension;

			mUsingAVFoundation = path.ends_with(".mp4");
			try
			{
				TheoraOutputMode mode;
				if (april::rendersys->getName() == "OpenGL")
				{
					if (mUseAlpha)
					{
						mode = TH_RGBA;
					}
					else
					{
						mode = mUsingAVFoundation ? TH_BGRX : TH_RGB;
					}
				}
				else
				{
					mode = mUseAlpha ? TH_BGRA : TH_BGRX;
				}

				mClip = gVideoManager->createVideoClip(path, mode, 16);
			}
			catch (_TheoraGenericException& e)
			{
				throw hl_exception(e.getErrorText());
			}
			if (mClip->getWidth() == 0) throw hl_exception("Failed to load video file: " + path);
			mClip->setAutoRestart(mLoop);

			float w = mClip->getWidth(), h = mClip->getHeight();
			april::Texture* tex = april::rendersys->createTexture(_nextPow2(w), _nextPow2(h), mUsingAVFoundation ? april::Texture::FORMAT_BGRA : april::Texture::FORMAT_ARGB);
			mTexture = new aprilui::Texture(tex->getFilename(), tex);
			mVideoImage = new aprilui::Image(mTexture, "video_img", grect(0, 0, w, h));
			mClip->waitForCache(4 / 16.0f, 0.5f);

			if (mAudioName != "")
			{
				if (!xal::mgr->hasCategory("video"))
				{
					xal::mgr->createCategory("video", xal::STREAMED, xal::DISK);
				}
				mSound = xal::mgr->createSound(mDataset->getFilePath() + "/video/" + mAudioName, "video");

				mAudioPlayer = xal::mgr->createPlayer(mAudioName.replace(".ogg", ""));
				mTimer = new AudioVideoTimer(mAudioPlayer, mAudioSyncOffset);
				mClip->setTimer(mTimer);

				mAudioPlayer->play();
			}
			else if (mSpeed != 1.0f) mClip->setPlaybackSpeed(mSpeed);
		}

		if (mClip)
		{
			if (!mLoop)
			{
				bool done = mClip->isDone();
				if (mPrevDoneFlag == 0 && done == 1) triggerEvent("PlaybackDone");
				mPrevDoneFlag = done;
			}
			mClip->update(k);
			//mClip->decodedAudioCheck();
			bool should_pause = mAlphaPauseTreshold == 0 ? !isVisible() : getAlpha() <= mAlphaPauseTreshold;
			if (should_pause && !mClip->isPaused()) mClip->pause();
			else if (!should_pause && mClip->isPaused()) mClip->play();

			TheoraVideoFrame* f = mClip->getNextFrame();
			if (f)
			{
				mImage = mVideoImage;
				grect r = mImage->getSrcRect();
				r.w = f->getWidth();
				r.h = f->getHeight();
				mImage->setSrcRect(r);
				if (april::rendersys->getName() == "DirectX9") mTexture->getRenderTexture()->clear();
				int bpp = mUsingAVFoundation ? 4 : 3 + mUseAlpha;
				mTexture->getRenderTexture()->write(0, 0, f->getBuffer(), r.w, r.h, bpp);
				mClip->popFrame();
				if (mLoop)
				{
					int number = f->getFrameNumber();
					if (mSeeked) mSeeked = 0;
					else if (number < mPrevFrameNumber)
					{
						triggerEvent("PlaybackDone");
					}
					mPrevFrameNumber = number;
				}
			}
		}
	}

	void VideoObject::setAlphaTreshold(int treshold)
	{
		mAlphaPauseTreshold = hclamp(treshold, 0, 255);
	}

	bool VideoObject::setProperty(chstr name,chstr value)
	{
		if      (name == "video") mClipName = value;
		else if (name == "video_alpha") mUseAlpha = value;
		else if (name == "alpha_pause_treshold") setAlphaTreshold(value);
		else if (name == "loop")  mLoop = value;
		else if (name == "speed") mSpeed = value;
		else if (name == "time")
		{
			if (!mClip && mClipName != "") update(0); // try to create the clip if it hasn't been created already
			if (mClip)
			{
				float time = value;
				mSeeked = 1;
				mClip->seek(time);
			}
			else hlog::warn(logTag, "VideoObject ignoring 'time' param, mClip is NULL");
		}
		else if (name == "audio")
		{
			mAudioName = value;
		}
		else if (name == "sync_offset")
		{
			mAudioSyncOffset = value;
		}
		else return aprilui::ImageBox::setProperty(name, value);
		return 1;
	}

	hstr VideoObject::getProperty(chstr name, bool* property_exists)
	{
		*property_exists = true;
		if      (name == "video") return mClipName;
		else if (name == "video_alpha") return mUseAlpha ? "1" : "0";
		else if (name == "alpha_pause_treshold") return mAlphaPauseTreshold;
		else if (name == "loop")  return mLoop ? "1" : "0";
		else if (name == "speed") return mSpeed;
		else if (name == "time") return mClip ? hstr(mClip->getTimePosition()) : hstr("0");
		else if (name == "duration") return mClip ? hstr(mClip->getDuration()) : hstr("0");
		else if (name == "audio")  return mAudioName;
		else if (name == "sync_offset")  return mAudioSyncOffset;
		*property_exists = false;
		return ImageBox::getProperty(name, property_exists);
	}

	static void theoraLogMessage(std::string log)
	{
		hlog::write("aprilvideo", log);
	}

	void init(int num_worker_threads)
	{
		TheoraVideoManager::setLogFunction(theoraLogMessage);
		gNumWorkerThreads = num_worker_threads;
		APRILUI_REGISTER_OBJECT_TYPE(VideoObject);
	}

	void destroy()
	{

	}
}
<commit_msg>aprilvideo: bugfixes and improvements<commit_after>/************************************************************************************
This source file is part of the Theora Video Playback Library
For latest info, see http://libtheoraplayer.sourceforge.net/
*************************************************************************************
Copyright (c) 2008-2012 Kresimir Spes (kspes@cateia.com)
This program is free software; you can redistribute it and/or modify it under
the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php
*************************************************************************************/
#define THEORAUTIL_NOMACROS
#include <theoraplayer/TheoraException.h>
#undef exception_cls
#include <theoraplayer/TheoraDataSource.h>
#include <theoraplayer/TheoraPlayer.h>
#include <theoraplayer/TheoraTimer.h>
#include <april/RenderSystem.h>
#include <april/Platform.h>
#include <april/Texture.h>
#include <aprilui/aprilui.h>
#include <aprilui/Dataset.h>
#include <aprilui/NullImage.h>
#include <aprilui/Texture.h>
#include <xal/AudioManager.h>
#include <xal/Player.h>
#include "aprilvideo.h"

namespace aprilvideo
{
	static TheoraVideoManager* gVideoManager = NULL;
	static int gRefCount = 0, gNumWorkerThreads = 1;
	hstr logTag = "aprilvideo", defaultFileExtension = ".ogv";

	static int _nextPow2(int x)
	{
		int y;
		for (y = 1; y < x; y *= 2);
		return y;
	}

	class AudioVideoTimer : public TheoraTimer
	{
		float mSyncOffset;
		xal::Player* mPlayer;
		float mT;
		bool mDisabledAudio;
	public:
		AudioVideoTimer(xal::Player* player, float sync_offset)
		{
			mSyncOffset = sync_offset;
			mPlayer = player;
			mT = 0;
			static hstr audiosystem = xal::mgr->getName(); // Disabled" audio system doesn't sync audio & video
			mDisabledAudio = (audiosystem == "Disabled");
		}

		void update(float time_increase)
		{
			if (!mDisabledAudio)
			{
				if (mPlayer->isPlaying())
					mTime = mPlayer->getTimePosition() - mSyncOffset;
				else
					mTime += time_increase;
			}
			else
			{
				mT += time_increase;
				mTime = mT - mSyncOffset;
			}
		}
	};

	VideoObject::VideoObject(chstr name, grect rect) : aprilui::ImageBox(name, rect)
	{
		mUsingAVFoundation = 0;
		mUseAlpha = 0;
		mPrevDoneFlag = 0;
		mLoop = 1;
		mSpeed = 1.0f;
		mClip = NULL;
		mVideoImage = NULL;
		mTexture = NULL;
		mTimer = NULL;
		mSound = NULL;
		mAudioPlayer = NULL;
		mAudioSyncOffset = 0;
		gRefCount++;
		mAlphaPauseTreshold = 0;
		mPrevFrameNumber = 0;
		mSeeked = 0;
		if (!gVideoManager)
		{
			gVideoManager = new TheoraVideoManager(gNumWorkerThreads);
			std::vector<std::string> lst = gVideoManager->getSupportedDecoders();
			foreach (std::string, it, lst)
			{
				if (*it == "AVFoundation") defaultFileExtension = ".mp4";
			}
		}
	}

	aprilui::Object* VideoObject::createInstance(chstr name, grect rect)
	{
		return new VideoObject(name, rect);
	}

	void VideoObject::notifyEvent(chstr name, void* params)
	{
		if (name == "AttachToObject")
		{
			if (mImage != mVideoImage)
			{
				mImage = mDataset->getImage("null");
			}
		}
		ImageBox::notifyEvent(name, params);
	}

	void VideoObject::destroyResources()
	{
		if (mVideoImage)
		{
			delete mVideoImage;
			mVideoImage = NULL;
			mImage = mDataset->getImage("null");
		}
		if (mTexture)
		{
			delete mTexture;
			mTexture = NULL;
		}
		if (mClip)
		{
			gVideoManager->destroyVideoClip(mClip);
			mClip = NULL;
		}
		if (mAudioPlayer)
		{
			xal::mgr->destroyPlayer(mAudioPlayer);
			mAudioPlayer = NULL;
		}
		if (mSound)
		{
			xal::mgr->destroySound(mSound);
			mSound = NULL;
		}

		if (mTimer)
		{
			delete mTimer;
			mTimer = NULL;
		}
	}

	VideoObject::~VideoObject()
	{
		gRefCount--;
		destroyResources();
		if (gRefCount <= 0 && gVideoManager)
		{
			delete gVideoManager;
			gVideoManager = NULL;
		}
	}

	void VideoObject::update(float k)
	{
		ImageBox::update(k);
		if (mClip == NULL && mClipName != "")
		{
			destroyResources();
			hstr path = mDataset->getFilePath() + "/video/" + mClipName;
			if (!path.ends_with(".ogg") && !path.ends_with(".ogv") && !path.ends_with(".mp4")) path += defaultFileExtension;

			mUsingAVFoundation = path.ends_with(".mp4");
			try
			{
				TheoraOutputMode mode;
				if (april::rendersys->getName() == "OpenGL")
				{
					if (mUseAlpha)
					{
						mode = TH_RGBA;
					}
					else
					{
						mode = mUsingAVFoundation ? TH_BGRX : TH_RGB;
					}
				}
				else
				{
					mode = mUseAlpha ? TH_BGRA : TH_BGRX;
				}

				mClip = gVideoManager->createVideoClip(path, mode, april::getSystemInfo().ram < 512 ? 8 : 16);
			}
			catch (_TheoraGenericException& e)
			{
				throw hl_exception(e.getErrorText());
			}
			if (mClip->getWidth() == 0) throw hl_exception("Failed to load video file: " + path);
			mClip->setAutoRestart(mLoop);

			float w = mClip->getWidth(), h = mClip->getHeight();
			april::Texture* tex = april::rendersys->createTexture(_nextPow2(w), _nextPow2(h), mUsingAVFoundation ? april::Texture::FORMAT_BGRA : april::Texture::FORMAT_ARGB);
			mTexture = new aprilui::Texture(tex->getFilename(), tex);
			mVideoImage = new aprilui::Image(mTexture, "video_img", grect(0, 0, w, h));
			mClip->waitForCache(4 / 16.0f, 0.5f);

			if (mAudioName != "")
			{
				if (!xal::mgr->hasCategory("video"))
				{
					xal::mgr->createCategory("video", xal::ON_DEMAND, xal::DISK);
				}
				mSound = xal::mgr->createSound(mDataset->getFilePath() + "/video/" + mAudioName, "video");

				mAudioPlayer = xal::mgr->createPlayer(mAudioName.replace(".ogg", ""));
				mTimer = new AudioVideoTimer(mAudioPlayer, mAudioSyncOffset);
				mClip->setTimer(mTimer);

				mAudioPlayer->play();
			}
			else if (mSpeed != 1.0f) mClip->setPlaybackSpeed(mSpeed);
		}

		if (mClip)
		{
			if (!mLoop)
			{
				bool done = mClip->isDone();
				if (mPrevDoneFlag == 0 && done == 1) triggerEvent("PlaybackDone");
				mPrevDoneFlag = done;
			}
			mClip->update(k);
			//mClip->decodedAudioCheck();
			bool should_pause = mAlphaPauseTreshold == 0 ? !isVisible() : getAlpha() <= mAlphaPauseTreshold;
			if (should_pause && !mClip->isPaused()) mClip->pause();
			else if (!should_pause && mClip->isPaused()) mClip->play();

			TheoraVideoFrame* f = mClip->getNextFrame();
			if (f)
			{
				mImage = mVideoImage;
				grect r = mImage->getSrcRect();
				r.w = f->getWidth();
				r.h = f->getHeight();
				mImage->setSrcRect(r);
				if (april::rendersys->getName() == "DirectX9") mTexture->getRenderTexture()->clear();
				int bpp = mUsingAVFoundation ? 4 : 3 + mUseAlpha;
				mTexture->getRenderTexture()->write(0, 0, f->getBuffer(), r.w, r.h, bpp);
				mClip->popFrame();
				if (mLoop)
				{
					int number = f->getFrameNumber();
					if (mSeeked) mSeeked = 0;
					else if (number < mPrevFrameNumber)
					{
						triggerEvent("PlaybackDone");
					}
					mPrevFrameNumber = number;
				}
			}
		}
	}

	void VideoObject::setAlphaTreshold(int treshold)
	{
		mAlphaPauseTreshold = hclamp(treshold, 0, 255);
	}

	bool VideoObject::setProperty(chstr name,chstr value)
	{
		if      (name == "video") mClipName = value;
		else if (name == "video_alpha") mUseAlpha = value;
		else if (name == "alpha_pause_treshold") setAlphaTreshold(value);
		else if (name == "loop")  mLoop = value;
		else if (name == "speed") mSpeed = value;
		else if (name == "time")
		{
			if (!mClip && mClipName != "") update(0); // try to create the clip if it hasn't been created already
			if (mClip)
			{
				float time = value;
				mSeeked = 1;
				mClip->seek(time);
			}
			else hlog::warn(logTag, "VideoObject ignoring 'time' param, mClip is NULL");
		}
		else if (name == "audio")
		{
			mAudioName = value;
		}
		else if (name == "sync_offset")
		{
			mAudioSyncOffset = value;
		}
		else return aprilui::ImageBox::setProperty(name, value);
		return 1;
	}

	hstr VideoObject::getProperty(chstr name, bool* property_exists)
	{
		*property_exists = true;
		if      (name == "video") return mClipName;
		else if (name == "video_alpha") return mUseAlpha ? "1" : "0";
		else if (name == "alpha_pause_treshold") return mAlphaPauseTreshold;
		else if (name == "loop")  return mLoop ? "1" : "0";
		else if (name == "speed") return mSpeed;
		else if (name == "time") return mClip ? hstr(mClip->getTimePosition()) : hstr("0");
		else if (name == "duration") return mClip ? hstr(mClip->getDuration()) : hstr("0");
		else if (name == "audio")  return mAudioName;
		else if (name == "sync_offset")  return mAudioSyncOffset;
		*property_exists = false;
		return ImageBox::getProperty(name, property_exists);
	}

	static void theoraLogMessage(std::string log)
	{
		hlog::write("aprilvideo", log);
	}

	void init(int num_worker_threads)
	{
		TheoraVideoManager::setLogFunction(theoraLogMessage);
		gNumWorkerThreads = num_worker_threads;
		APRILUI_REGISTER_OBJECT_TYPE(VideoObject);
	}

	void destroy()
	{

	}
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_TEST_SPACES_RT_HH
#define DUNE_GDT_TEST_SPACES_RT_HH

#include "spaces.hh"

template< class SpaceType >
class RT_Space
  : public SpaceBase< SpaceType >
{};

#endif // DUNE_GDT_TEST_SPACES_RT_HH
<commit_msg>[test.spaces_rt] add signature and 2d simplicial check<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_TEST_SPACES_RT_HH
#define DUNE_GDT_TEST_SPACES_RT_HH

#include <dune/common/unused.hh>

#include <dune/stuff/common/ranges.hh>

#include <dune/gdt/spaces/rt/interface.hh>

#include "spaces.hh"

template< class SpaceType >
class RT_Space
  : public SpaceBase< SpaceType >
{
  template< class T, int d, class R, int r, int rC >
  void matches_signature(const Dune::GDT::Spaces::RTInterface< T, d, R, r, rC >& /*space*/)
  {
    static_assert(Dune::GDT::is_rt_space< SpaceType >::value, "");
    static_assert(std::is_same< typename SpaceType::Traits, T >::value, "");
    static_assert(std::is_same< typename SpaceType::RangeFieldType, R >::value, "");
    static_assert(d == SpaceType::dimDomain, "");
    static_assert(r == SpaceType::dimRange, "");
    static_assert(rC == SpaceType::dimRangeCols, "");
  }

public:
  void matches_raviart_thomas_signature()
  {
    matches_signature(this->space_);
  }
};

template< class SpaceType >
class RT_2d_simplicial_Space
  : public RT_Space< SpaceType >
{
public:
  void fulfills_raviart_thomas_2d_simplicial_interface()
  {
    for (const auto& entity : DSC::entityRange(this->space_.grid_view()))
      auto DUNE_UNUSED(local_DoF_indices) = this->space_.local_DoF_indices(entity);
  }
}; // class RT_2d_simplicial_Space

#endif // DUNE_GDT_TEST_SPACES_RT_HH
<|endoftext|>


<commit_before>/**
 * @file    src/mod_rfid.c
 * @brief
 *
 * @addtogroup
 * @{
 */

#include "mod_rfid.h"

#if MOD_RFID

#include "ch_tools.h"
#include "watchdog.h"
#include "module_init_cpp.h"

#include "qhal.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

namespace tmb_musicplayer
{
template <>
ModuleRFID ModuleRFIDSingelton::instance = tmb_musicplayer::ModuleRFID();

/**
 * @brief
 */

ModuleRFID::ModuleRFID() :
        m_detectedCard(false),
        m_mfrcDriver(NULL)
{

}

ModuleRFID::~ModuleRFID()
{

}

void ModuleRFID::Init()
{
    m_mfrcDriver = &RFID1;
    watchdog_register(WATCHDOG_MOD_RFID);
}

void ModuleRFID::Start()
{
    chDbgAssert(m_mfrcDriver != NULL, "No driver set!!");

    m_detectedCard = false;

    BaseClass::Start();
}

void ModuleRFID::Shutdown()
{
    BaseClass::Shutdown();

    m_mfrcDriver = NULL;
}

void ModuleRFID::RegisterListener(chibios_rt::EvtListener* listener, eventmask_t mask)
{
    m_evtSource.registerMask(listener, mask);
}

void ModuleRFID::UnregisterListener(chibios_rt::EvtListener* listener)
{
    m_evtSource.unregister(listener);
}

bool ModuleRFID::GetCurrentCardId(MifareUID& id)
{
    bool detected = false;
    m_mutex.lock();
    if (m_detectedCard == true)
    {
        memcpy(&id, &m_cardID, sizeof(m_cardID));
        detected = true;
    }
    m_mutex.unlock();
    return detected;
}

void ModuleRFID::ThreadMain()
{
    chRegSetThreadName("rfidreader");

    m_detectedCard = false;

    SetRFIDDetectLed(false);
    while (!chThdShouldTerminateX())
    {
        watchdog_reload(WATCHDOG_MOD_RFID);
        bool lastDetectState = m_detectedCard;
        m_mutex.lock();
        MIFARE_Status_t status = MifareCheck(m_mfrcDriver, &m_cardID);
        m_detectedCard = status == MIFARE_OK;
        if (m_detectedCard == false)
        {
            /*reset cardid*/
            m_cardID.size = 0;
        }
        m_mutex.unlock();

        if (m_detectedCard == true)
        {
            if (lastDetectState == false)
            {
                SetRFIDDetectLed(true);
                m_evtSource.broadcastFlags(CardDetected);
            }
        }
        else
        {
          if (lastDetectState == true)
          {
              SetRFIDDetectLed(false);
              m_evtSource.broadcastFlags(CardLost);
          }
        }

        chibios_rt::BaseThread::sleep(MS2ST(100));
    }
}

void ModuleRFID::SetRFIDDetectLed(bool on)
{
#if HAL_USE_LED
    if (on == true)
    {
        ledOn(LED_RFID);
    }
    else
    {
        ledOff(LED_RFID);
    }
#endif /* HAL_USE_LED */

}

}

MODULE_INITCALL(1, qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Init,
        qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Start,
        qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Shutdown)

#endif
/** @} */
<commit_msg>mod_rfid: thead higher module order number<commit_after>/**
 * @file    src/mod_rfid.c
 * @brief
 *
 * @addtogroup
 * @{
 */

#include "mod_rfid.h"

#if MOD_RFID

#include "ch_tools.h"
#include "watchdog.h"
#include "module_init_cpp.h"

#include "qhal.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

namespace tmb_musicplayer
{
template <>
ModuleRFID ModuleRFIDSingelton::instance = tmb_musicplayer::ModuleRFID();

/**
 * @brief
 */

ModuleRFID::ModuleRFID() :
        m_detectedCard(false),
        m_mfrcDriver(NULL)
{

}

ModuleRFID::~ModuleRFID()
{

}

void ModuleRFID::Init()
{
    m_mfrcDriver = &RFID1;
    watchdog_register(WATCHDOG_MOD_RFID);
}

void ModuleRFID::Start()
{
    chDbgAssert(m_mfrcDriver != NULL, "No driver set!!");

    m_detectedCard = false;

    BaseClass::Start();
}

void ModuleRFID::Shutdown()
{
    BaseClass::Shutdown();

    m_mfrcDriver = NULL;
}

void ModuleRFID::RegisterListener(chibios_rt::EvtListener* listener, eventmask_t mask)
{
    m_evtSource.registerMask(listener, mask);
}

void ModuleRFID::UnregisterListener(chibios_rt::EvtListener* listener)
{
    m_evtSource.unregister(listener);
}

bool ModuleRFID::GetCurrentCardId(MifareUID& id)
{
    bool detected = false;
    m_mutex.lock();
    if (m_detectedCard == true)
    {
        memcpy(&id, &m_cardID, sizeof(m_cardID));
        detected = true;
    }
    m_mutex.unlock();
    return detected;
}

void ModuleRFID::ThreadMain()
{
    chRegSetThreadName("rfidreader");

    m_detectedCard = false;

    SetRFIDDetectLed(false);
    while (!chThdShouldTerminateX())
    {
        watchdog_reload(WATCHDOG_MOD_RFID);
        bool lastDetectState = m_detectedCard;
        m_mutex.lock();
        MIFARE_Status_t status = MifareCheck(m_mfrcDriver, &m_cardID);
        m_detectedCard = status == MIFARE_OK;
        if (m_detectedCard == false)
        {
            /*reset cardid*/
            m_cardID.size = 0;
        }
        m_mutex.unlock();

        if (m_detectedCard == true)
        {
            if (lastDetectState == false)
            {
                SetRFIDDetectLed(true);
                m_evtSource.broadcastFlags(CardDetected);
            }
        }
        else
        {
          if (lastDetectState == true)
          {
              SetRFIDDetectLed(false);
              m_evtSource.broadcastFlags(CardLost);
          }
        }

        chibios_rt::BaseThread::sleep(MS2ST(100));
    }
}

void ModuleRFID::SetRFIDDetectLed(bool on)
{
#if HAL_USE_LED
    if (on == true)
    {
        ledOn(LED_RFID);
    }
    else
    {
        ledOff(LED_RFID);
    }
#endif /* HAL_USE_LED */

}

}

MODULE_INITCALL(6, qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Init,
        qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Start,
        qos::ModuleInit<tmb_musicplayer::ModuleRFIDSingelton>::Shutdown)

#endif
/** @} */
<|endoftext|>


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

/**
 * @file battery.cpp
 *
 * Library calls for battery functionality.
 *
 * @author Julian Oes <julian@oes.ch>
 */

#include "battery.h"

Battery::Battery() :
	SuperBlock(NULL, ""),
	_param_v_empty(this, "BAT_V_EMPTY", false),
	_param_v_full(this, "BAT_V_CHARGED", false),
	_param_n_cells(this, "BAT_N_CELLS", false),
	_param_capacity(this, "BAT_CAPACITY", false),
	_param_v_load_drop(this, "BAT_V_LOAD_DROP", false),
	_voltage_filtered_v(0.0f),
	_throttle_filtered(0.0f),
	_discharged_mah(0.0f),
	_remaining(1.0f),
	_warning(battery_status_s::BATTERY_WARNING_NONE),
	_last_timestamp(0)
{
	/* load initial params */
	updateParams();
}

Battery::~Battery()
{
}

void
Battery::reset(battery_status_s *battery_status)
{
	battery_status->voltage_v = 0.0f;
	battery_status->voltage_filtered_v = 0.0f;
	battery_status->current_a = -1.0f;
	battery_status->discharged_mah = -1.0f;
	battery_status->cell_count = _param_n_cells.get();
	// TODO: check if it is sane to reset warning to NONE
	battery_status->warning = battery_status_s::BATTERY_WARNING_NONE;
}

void
Battery::updateBatteryStatus(hrt_abstime timestamp, float voltage_v, float current_a, float throttle_normalized,
			     battery_status_s *battery_status)
{
	battery_status->timestamp = timestamp;
	filterVoltage(voltage_v);
	sumDischarged(timestamp, current_a);
	estimateRemaining(voltage_v, throttle_normalized);
	determineWarning();

	if (_voltage_filtered_v > 2.1f) {
		battery_status->voltage_v = voltage_v;
		battery_status->voltage_filtered_v = _voltage_filtered_v;
		battery_status->current_a = current_a;
		battery_status->discharged_mah = _discharged_mah;
		battery_status->cell_count = _param_n_cells.get();
		battery_status->warning = _warning;

	} else {
		reset(battery_status);
	}
}

void
Battery::filterVoltage(float voltage_v)
{
	// TODO: inspect that filter performance
	const float filtered_next = _voltage_filtered_v * 0.999f + voltage_v * 0.001f;

	if (PX4_ISFINITE(filtered_next)) {
		_voltage_filtered_v = filtered_next;
	}
}

void
Battery::sumDischarged(hrt_abstime timestamp, float current_a)
{
	// Ignore first update because we don't know dT.
	if (_last_timestamp != 0) {
		_discharged_mah = current_a * (timestamp - _last_timestamp) * 1.0e-3f / 3600.0f;
	}

	_last_timestamp = timestamp;
}

void
Battery::estimateRemaining(float voltage_v, float throttle_normalized)
{
	// XXX this time constant needs to become tunable but really, the right fix are smart batteries.
	const float filtered_next = _throttle_filtered * 0.97f + throttle_normalized * 0.03f;

	if (PX4_ISFINITE(filtered_next)) {
		_throttle_filtered = filtered_next;
	}

	/* remaining charge estimate based on voltage and internal resistance (drop under load) */
	const float bat_v_empty_dynamic = _param_v_empty.get() - (_param_v_load_drop.get() * _throttle_filtered);
	/* the range from full to empty is the same for batteries under load and without load,
	 * since the voltage drop applies to both the full and empty state
	 */
	const float voltage_range = (_param_v_full.get() - _param_v_empty.get());
	const float remaining_voltage = (voltage_v - (_param_n_cells.get() * bat_v_empty_dynamic))
					/ (_param_n_cells.get() * voltage_range);

	if (_param_capacity.get() > 0.0f) {
		/* if battery capacity is known, use discharged current for estimate, but don't show more than voltage estimate */
		_remaining = fminf(remaining_voltage, 1.0f - _discharged_mah / _param_capacity.get());

	} else {
		/* else use voltage */
		_remaining = remaining_voltage;
	}

	/* limit to sane values */
	_remaining = (_remaining < 0.0f) ? 0.0f : _remaining;
	_remaining = (_remaining > 1.0f) ? 1.0f : _remaining;
}

void
Battery::determineWarning()
{
	// TODO: Determine threshold or make params.
	if (_remaining < 0.18f) {
		_warning = battery_status_s::BATTERY_WARNING_LOW;

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

/**
 * @file battery.cpp
 *
 * Library calls for battery functionality.
 *
 * @author Julian Oes <julian@oes.ch>
 */

#include "battery.h"

Battery::Battery() :
	SuperBlock(NULL, ""),
	_param_v_empty(this, "BAT_V_EMPTY", false),
	_param_v_full(this, "BAT_V_CHARGED", false),
	_param_n_cells(this, "BAT_N_CELLS", false),
	_param_capacity(this, "BAT_CAPACITY", false),
	_param_v_load_drop(this, "BAT_V_LOAD_DROP", false),
	_voltage_filtered_v(0.0f),
	_throttle_filtered(0.0f),
	_discharged_mah(0.0f),
	_remaining(1.0f),
	_warning(battery_status_s::BATTERY_WARNING_NONE),
	_last_timestamp(0)
{
	/* load initial params */
	updateParams();
}

Battery::~Battery()
{
}

void
Battery::reset(battery_status_s *battery_status)
{
	battery_status->voltage_v = 0.0f;
	battery_status->voltage_filtered_v = 0.0f;
	battery_status->current_a = -1.0f;
	battery_status->discharged_mah = -1.0f;
	battery_status->remaining = 0.0f;
	battery_status->cell_count = _param_n_cells.get();
	// TODO: check if it is sane to reset warning to NONE
	battery_status->warning = battery_status_s::BATTERY_WARNING_NONE;
}

void
Battery::updateBatteryStatus(hrt_abstime timestamp, float voltage_v, float current_a, float throttle_normalized,
			     battery_status_s *battery_status)
{
	battery_status->timestamp = timestamp;
	filterVoltage(voltage_v);
	sumDischarged(timestamp, current_a);
	estimateRemaining(voltage_v, throttle_normalized);
	determineWarning();

	if (_voltage_filtered_v > 2.1f) {
		battery_status->voltage_v = voltage_v;
		battery_status->voltage_filtered_v = _voltage_filtered_v;
		battery_status->current_a = current_a;
		battery_status->discharged_mah = _discharged_mah;
		battery_status->cell_count = _param_n_cells.get();
		battery_status->warning = _warning;
		battery_status->remaining = _remaining;

	} else {
		reset(battery_status);
	}
}

void
Battery::filterVoltage(float voltage_v)
{
	// TODO: inspect that filter performance
	const float filtered_next = _voltage_filtered_v * 0.999f + voltage_v * 0.001f;

	if (PX4_ISFINITE(filtered_next)) {
		_voltage_filtered_v = filtered_next;
	}
}

void
Battery::sumDischarged(hrt_abstime timestamp, float current_a)
{
	// Not a valid measurement
	if (current_a < 0.0f) {
		// Because the measurement was invalid we need to stop integration
		// and re-initialize with the next valid measurement
		_last_timestamp = 0;
		return;
	}

	// Ignore first update because we don't know dT.
	if (_last_timestamp != 0) {
		_discharged_mah = current_a * (timestamp - _last_timestamp) * 1.0e-3f / 3600.0f;
	}

	_last_timestamp = timestamp;
}

void
Battery::estimateRemaining(float voltage_v, float throttle_normalized)
{
	// XXX this time constant needs to become tunable but really, the right fix are smart batteries.
	const float filtered_next = _throttle_filtered * 0.97f + throttle_normalized * 0.03f;

	if (PX4_ISFINITE(filtered_next)) {
		_throttle_filtered = filtered_next;
	}

	/* remaining charge estimate based on voltage and internal resistance (drop under load) */
	const float bat_v_empty_dynamic = _param_v_empty.get() - (_param_v_load_drop.get() * _throttle_filtered);
	/* the range from full to empty is the same for batteries under load and without load,
	 * since the voltage drop applies to both the full and empty state
	 */
	const float voltage_range = (_param_v_full.get() - _param_v_empty.get());
	const float remaining_voltage = (voltage_v - (_param_n_cells.get() * bat_v_empty_dynamic))
					/ (_param_n_cells.get() * voltage_range);

	if (_param_capacity.get() > 0.0f) {
		/* if battery capacity is known, use discharged current for estimate, but don't show more than voltage estimate */
		_remaining = fminf(remaining_voltage, 1.0f - _discharged_mah / _param_capacity.get());

	} else {
		/* else use voltage */
		_remaining = remaining_voltage;
	}

	/* limit to sane values */
	_remaining = (_remaining < 0.0f) ? 0.0f : _remaining;
	_remaining = (_remaining > 1.0f) ? 1.0f : _remaining;
}

void
Battery::determineWarning()
{
	// TODO: Determine threshold or make params.
	if (_remaining < 0.18f) {
		_warning = battery_status_s::BATTERY_WARNING_LOW;

	} else if (_remaining < 0.09f) {
		_warning = battery_status_s::BATTERY_WARNING_CRITICAL;
	}
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _MSGNODEI_HXX
#define _MSGNODEI_HXX

#include <svl/eitem.hxx>
#include <tools/string.hxx>
#include <svl/poolitem.hxx>

struct SfxMsgAttachFile {
    String  aFile;
    String  aName;

    int                 operator==( const SfxMsgAttachFile& rRec ) const
                        {
                            if( aName == rRec.aName && aFile == rRec.aFile )
                                return sal_True;
                            return sal_False;
                        }

                        SfxMsgAttachFile( const String& rFile, const String& rName)
                            : aName( rName ), aFile( rFile ) {}

                        SfxMsgAttachFile( const SfxMsgAttachFile& rRec )
                            : aName( rRec.aName), aFile( rRec.aFile ) {}
};

enum SfxMsgReceiverRole
{
    MSG_RECEIVER_TO = 0,
    MSG_RECEIVER_CC,
    MSG_RECEIVER_BCC,
    MSG_RECEIVER_NEWSGROUP
};

struct SfxMsgReceiver {
    String              aName;
    SfxMsgReceiverRole  eRole;

    int                 operator==( const SfxMsgReceiver& rRec ) const
                        {
                            if( aName == rRec.aName && eRole == rRec.eRole )
                                return sal_True;
                            return sal_False;
                        }

                        SfxMsgReceiver( const String& rName, SfxMsgReceiverRole _eRole )
                            : aName( rName ), eRole( _eRole ) {}

                        SfxMsgReceiver( const SfxMsgReceiver& rRec )
                            : aName( rRec.aName), eRole( rRec.eRole ) {}
};

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

class SfxMsgReceiverList_Impl : public List
{
    sal_uIntPtr             nRef;
                    ~SfxMsgReceiverList_Impl();
    SfxMsgReceiverList_Impl& operator=( const SfxMsgReceiverList_Impl&); //n.i.
public:
                    SfxMsgReceiverList_Impl();
                    SfxMsgReceiverList_Impl(const SfxMsgReceiverList_Impl&);

    void            Load( SvStream& );
    void            Store( SvStream& ) const;
    void            IncRef() { nRef++; }
    void            DecRef() { nRef--; if( !nRef ) delete this; }
    sal_uIntPtr         GetRefCount() const { return nRef; }
    int             operator==( const SfxMsgReceiverList_Impl& ) const;
};

class SfxMsgReceiverListItem : public SfxPoolItem
{
    void                    Disconnect();
protected:
    SfxMsgReceiverList_Impl* pImp;
public:
                            TYPEINFO();

                            SfxMsgReceiverListItem();
                            SfxMsgReceiverListItem( sal_uInt16 nWhich );
                            SfxMsgReceiverListItem( sal_uInt16 nWhich, SvStream& rStream );
                            SfxMsgReceiverListItem( const SfxMsgReceiverListItem& rItem );
                            ~SfxMsgReceiverListItem();

    virtual int             operator==( const SfxPoolItem& ) const;

    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    XubString &rText ) const;

    sal_uInt16                  Count() const;
    SfxMsgReceiver*         GetObject( sal_uInt16 nPos );
    void                    Remove( sal_uInt16 nPos );
    void                    Add( const SfxMsgReceiver& );

    virtual SfxPoolItem*    Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*    Create( SvStream &, sal_uInt16 nVersion ) const;
    virtual SvStream&       Store( SvStream &, sal_uInt16 nItemVersion ) const;
};

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

class SfxMsgAttachFileList_Impl : public List
{
    sal_uIntPtr             nRef;
                    ~SfxMsgAttachFileList_Impl();
    SfxMsgAttachFileList_Impl& operator=( const SfxMsgAttachFileList_Impl&); //n.i.

public:
                    SfxMsgAttachFileList_Impl();
                    SfxMsgAttachFileList_Impl(const SfxMsgAttachFileList_Impl&);

    int             operator==( const SfxMsgAttachFileList_Impl& rRec ) const;
    SfxMsgAttachFile* GetReceiver(sal_uIntPtr nPos) { return (SfxMsgAttachFile*)List::GetObject(nPos); }
    void            Load( SvStream& );
    void            Store( SvStream& ) const;
    void            IncRef() { nRef++; }
    void            DecRef() { nRef--; if( !nRef ) delete this; }
    sal_uIntPtr         GetRefCount() const { return nRef; }
};

class SfxMsgAttachFileListItem : public SfxPoolItem
{
protected:
    SfxMsgAttachFileList_Impl* pImp;
    void                    Disconnect();
public:
                            TYPEINFO();

                            SfxMsgAttachFileListItem();
                            SfxMsgAttachFileListItem( sal_uInt16 nWhich );
                            SfxMsgAttachFileListItem( sal_uInt16 nWhich, SvStream& rStream );
                            SfxMsgAttachFileListItem( const SfxMsgAttachFileListItem& rItem );
                            ~SfxMsgAttachFileListItem();

    virtual int             operator==( const SfxPoolItem& ) const;

    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    XubString &rText ) const;

    sal_uInt16                  Count() const;
    SfxMsgAttachFile*       GetObject( sal_uInt16 nPos );
    void                    Remove( sal_uInt16 nPos );
    void                    Add( const SfxMsgAttachFile& );

    virtual SfxPoolItem*    Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*    Create( SvStream &, sal_uInt16 nVersion ) const;
    virtual SvStream&       Store( SvStream &, sal_uInt16 nItemVersion ) const;
};

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

enum SfxMsgPriority
{
    MSG_PRIORITY_LOW = 0,
    MSG_PRIORITY_NORMAL,
    MSG_PRIORITY_URGENT
};
#define SFXMSGPRIORITYCOUNT 3

class SfxMsgPriorityItem : public SfxEnumItem
{
public:
    TYPEINFO();

    SfxMsgPriorityItem( sal_uInt16 nWhich, SfxMsgPriority = MSG_PRIORITY_NORMAL);

    virtual SfxPoolItem*        Clone( SfxItemPool* pPool=0 ) const;
    virtual SfxPoolItem*        Create( SvStream&, sal_uInt16 ) const;
    virtual SvStream&           Store( SvStream&, sal_uInt16 ) const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePresentation,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresentationMetric,
                                    String &rText ) const;
    virtual sal_uInt16              GetValueCount() const;
    virtual String              GetValueTextByPos( sal_uInt16 nPos ) const;

    inline SfxMsgPriorityItem& operator=(const SfxMsgPriorityItem& rPrio)
    {
        SetValue( rPrio.GetValue() );
        return *this;
    }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Remove an unused header.<commit_after><|endoftext|>


<commit_before><commit_msg>Resolves: #i121507# Added comma to whitespace list<commit_after><|endoftext|>


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

#include "config.h"
#include "bindings/core/v8/ScriptStreamer.h"

#include "bindings/core/v8/ScriptStreamerThread.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "core/dom/PendingScript.h"
#include "core/frame/Settings.h"
#include "platform/Task.h"
#include "public/platform/Platform.h"

#include <gtest/gtest.h>
#include <v8.h>

namespace blink {

namespace {

class ScriptStreamingTest : public testing::Test {
public:
    ScriptStreamingTest()
        : m_scope(v8::Isolate::GetCurrent())
        , m_settings(Settings::create())
        , m_resourceRequest("http://www.streaming-test.com/")
        , m_resource(new ScriptResource(m_resourceRequest, "text/utf-8"))
        , m_pendingScript(0, m_resource) // Takes ownership of m_resource.
    {
        m_settings->setV8ScriptStreamingEnabled(true);
        m_resource->setLoading(true);
    }

    ScriptState* scriptState() const { return m_scope.scriptState(); }
    v8::Isolate* isolate() const { return m_scope.isolate(); }

protected:
    void appendData(const char* data)
    {
        m_resource->appendData(data, strlen(data));
        // Yield control to the background thread, so that V8 gets a change to
        // process the data before the main thread adds more. Note that we
        // cannot fully control in what kind of chunks the data is passed to V8
        // (if the V8 is not requesting more data between two appendData calls,
        // V8 will get both chunks together).
        WTF::yield();
    }

    void appendPadding()
    {
        for (int i = 0; i < 10; ++i) {
            appendData(" /* this is padding to make the script long enough, so "
                "that V8's buffer gets filled and it starts processing "
                "the data */ ");
        }
    }

    void finish()
    {
        m_resource->finish();
        m_resource->setLoading(false);
    }

    void processTasksUntilStreamingComplete()
    {
        while (ScriptStreamerThread::shared()->isRunningTask()) {
            WebThread* currentThread = blink::Platform::current()->currentThread();
            currentThread->postTask(new Task(WTF::bind(&WebThread::exitRunLoop, currentThread)));
            currentThread->enterRunLoop();
        }
    }

    V8TestingScope m_scope;
    OwnPtr<Settings> m_settings;
    // The Resource and PendingScript where we stream from. These don't really
    // fetch any data outside the test; the test controls the data by calling
    // ScriptResource::appendData.
    ResourceRequest m_resourceRequest;
    ScriptResource* m_resource;
    PendingScript m_pendingScript;
};

class TestScriptResourceClient : public ScriptResourceClient {
public:
    TestScriptResourceClient()
        : m_finished(false) { }

    virtual void notifyFinished(Resource*) OVERRIDE { m_finished = true; }

    bool finished() const { return m_finished; }

private:
    bool m_finished;
};

TEST_F(ScriptStreamingTest, CompilingStreamedScript)
{
    // Test that we can successfully compile a streamed script.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);

    appendData("function foo() {");
    appendPadding();
    appendData("return 5; }");
    appendPadding();
    appendData("foo();");
    EXPECT_FALSE(client.finished());
    finish();

    // Process tasks on the main thread until the streaming background thread
    // has completed its tasks.
    processTasksUntilStreamingComplete();
    EXPECT_TRUE(client.finished());
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    EXPECT_TRUE(sourceCode.streamer());
    v8::TryCatch tryCatch;
    v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, isolate());
    EXPECT_FALSE(script.IsEmpty());
    EXPECT_FALSE(tryCatch.HasCaught());
}

TEST_F(ScriptStreamingTest, CompilingStreamedScriptWithParseError)
{
    // Test that scripts with parse errors are handled properly. In those cases,
    // the V8 side typically finished before loading finishes: make sure we
    // handle it gracefully.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");
    appendData("this is the part which will be a parse error");
    // V8 won't realize the parse error until it actually starts parsing the
    // script, and this happens only when its buffer is filled.
    appendPadding();

    EXPECT_FALSE(client.finished());

    // Force the V8 side to finish before the loading.
    processTasksUntilStreamingComplete();
    EXPECT_FALSE(client.finished());

    finish();
    EXPECT_TRUE(client.finished());

    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    EXPECT_TRUE(sourceCode.streamer());
    v8::TryCatch tryCatch;
    v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, isolate());
    EXPECT_TRUE(script.IsEmpty());
    EXPECT_TRUE(tryCatch.HasCaught());
}

TEST_F(ScriptStreamingTest, CancellingStreaming)
{
    // Test that the upper layers (PendingScript and up) can be ramped down
    // while streaming is ongoing, and ScriptStreamer handles it gracefully.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");

    // In general, we cannot control what the background thread is doing
    // (whether it's parsing or waiting for more data). In this test, we have
    // given it so little data that it's surely waiting for more.

    // Simulate cancelling the network load (e.g., because the user navigated
    // away).
    EXPECT_FALSE(client.finished());
    m_pendingScript.stopWatchingForLoad(&client);
    m_pendingScript = PendingScript(); // This will destroy m_resource.
    m_resource = 0;

    // The V8 side will complete too. This should not crash. We don't receive
    // any results from the streaming and the client doesn't get notified.
    processTasksUntilStreamingComplete();
    EXPECT_FALSE(client.finished());
}

TEST_F(ScriptStreamingTest, SuppressingStreaming)
{
    // If we notice during streaming that there is a code cache, streaming
    // is suppressed (V8 doesn't parse while the script is loading), and the
    // upper layer (ScriptResourceClient) should get a notification when the
    // script is loaded.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");
    appendPadding();

    m_resource->setCachedMetadata(V8ScriptRunner::tagForCodeCache(), "X", 1, Resource::CacheLocally);

    appendPadding();
    finish();
    processTasksUntilStreamingComplete();
    EXPECT_TRUE(client.finished());

    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    // ScriptSourceCode doesn't refer to the streamer, since we have suppressed
    // the streaming and resumed the non-streaming code path for script
    // compilation.
    EXPECT_FALSE(sourceCode.streamer());
}

} // namespace

} // namespace blink
<commit_msg>Fix Oilpan build after r182048.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "bindings/core/v8/ScriptStreamer.h"

#include "bindings/core/v8/ScriptStreamerThread.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "core/dom/PendingScript.h"
#include "core/frame/Settings.h"
#include "platform/Task.h"
#include "public/platform/Platform.h"

#include <gtest/gtest.h>
#include <v8.h>

namespace blink {

namespace {

class ScriptStreamingTest : public testing::Test {
public:
    ScriptStreamingTest()
        : m_scope(v8::Isolate::GetCurrent())
        , m_settings(Settings::create())
        , m_resourceRequest("http://www.streaming-test.com/")
        , m_resource(new ScriptResource(m_resourceRequest, "text/utf-8"))
        , m_pendingScript(0, m_resource) // Takes ownership of m_resource.
    {
        m_settings->setV8ScriptStreamingEnabled(true);
        m_resource->setLoading(true);
    }

    ScriptState* scriptState() const { return m_scope.scriptState(); }
    v8::Isolate* isolate() const { return m_scope.isolate(); }

    void trace(Visitor* visitor)
    {
        visitor->trace(m_pendingScript);
    }

protected:
    void appendData(const char* data)
    {
        m_resource->appendData(data, strlen(data));
        // Yield control to the background thread, so that V8 gets a change to
        // process the data before the main thread adds more. Note that we
        // cannot fully control in what kind of chunks the data is passed to V8
        // (if the V8 is not requesting more data between two appendData calls,
        // V8 will get both chunks together).
        WTF::yield();
    }

    void appendPadding()
    {
        for (int i = 0; i < 10; ++i) {
            appendData(" /* this is padding to make the script long enough, so "
                "that V8's buffer gets filled and it starts processing "
                "the data */ ");
        }
    }

    void finish()
    {
        m_resource->finish();
        m_resource->setLoading(false);
    }

    void processTasksUntilStreamingComplete()
    {
        while (ScriptStreamerThread::shared()->isRunningTask()) {
            WebThread* currentThread = blink::Platform::current()->currentThread();
            currentThread->postTask(new Task(WTF::bind(&WebThread::exitRunLoop, currentThread)));
            currentThread->enterRunLoop();
        }
    }

    V8TestingScope m_scope;
    OwnPtr<Settings> m_settings;
    // The Resource and PendingScript where we stream from. These don't really
    // fetch any data outside the test; the test controls the data by calling
    // ScriptResource::appendData.
    ResourceRequest m_resourceRequest;
    ScriptResource* m_resource;
    PendingScript m_pendingScript;
};

class TestScriptResourceClient : public ScriptResourceClient {
public:
    TestScriptResourceClient()
        : m_finished(false) { }

    virtual void notifyFinished(Resource*) OVERRIDE { m_finished = true; }

    bool finished() const { return m_finished; }

private:
    bool m_finished;
};

TEST_F(ScriptStreamingTest, CompilingStreamedScript)
{
    // Test that we can successfully compile a streamed script.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);

    appendData("function foo() {");
    appendPadding();
    appendData("return 5; }");
    appendPadding();
    appendData("foo();");
    EXPECT_FALSE(client.finished());
    finish();

    // Process tasks on the main thread until the streaming background thread
    // has completed its tasks.
    processTasksUntilStreamingComplete();
    EXPECT_TRUE(client.finished());
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    EXPECT_TRUE(sourceCode.streamer());
    v8::TryCatch tryCatch;
    v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, isolate());
    EXPECT_FALSE(script.IsEmpty());
    EXPECT_FALSE(tryCatch.HasCaught());
}

TEST_F(ScriptStreamingTest, CompilingStreamedScriptWithParseError)
{
    // Test that scripts with parse errors are handled properly. In those cases,
    // the V8 side typically finished before loading finishes: make sure we
    // handle it gracefully.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");
    appendData("this is the part which will be a parse error");
    // V8 won't realize the parse error until it actually starts parsing the
    // script, and this happens only when its buffer is filled.
    appendPadding();

    EXPECT_FALSE(client.finished());

    // Force the V8 side to finish before the loading.
    processTasksUntilStreamingComplete();
    EXPECT_FALSE(client.finished());

    finish();
    EXPECT_TRUE(client.finished());

    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    EXPECT_TRUE(sourceCode.streamer());
    v8::TryCatch tryCatch;
    v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(sourceCode, isolate());
    EXPECT_TRUE(script.IsEmpty());
    EXPECT_TRUE(tryCatch.HasCaught());
}

TEST_F(ScriptStreamingTest, CancellingStreaming)
{
    // Test that the upper layers (PendingScript and up) can be ramped down
    // while streaming is ongoing, and ScriptStreamer handles it gracefully.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");

    // In general, we cannot control what the background thread is doing
    // (whether it's parsing or waiting for more data). In this test, we have
    // given it so little data that it's surely waiting for more.

    // Simulate cancelling the network load (e.g., because the user navigated
    // away).
    EXPECT_FALSE(client.finished());
    m_pendingScript.stopWatchingForLoad(&client);
    m_pendingScript = PendingScript(); // This will destroy m_resource.
    m_resource = 0;

    // The V8 side will complete too. This should not crash. We don't receive
    // any results from the streaming and the client doesn't get notified.
    processTasksUntilStreamingComplete();
    EXPECT_FALSE(client.finished());
}

TEST_F(ScriptStreamingTest, SuppressingStreaming)
{
    // If we notice during streaming that there is a code cache, streaming
    // is suppressed (V8 doesn't parse while the script is loading), and the
    // upper layer (ScriptResourceClient) should get a notification when the
    // script is loaded.
    bool started = ScriptStreamer::startStreaming(m_pendingScript, m_settings.get(), m_scope.scriptState());
    TestScriptResourceClient client;
    m_pendingScript.watchForLoad(&client);
    EXPECT_TRUE(started);
    appendData("function foo() {");
    appendPadding();

    m_resource->setCachedMetadata(V8ScriptRunner::tagForCodeCache(), "X", 1, Resource::CacheLocally);

    appendPadding();
    finish();
    processTasksUntilStreamingComplete();
    EXPECT_TRUE(client.finished());

    bool errorOccurred = false;
    ScriptSourceCode sourceCode = m_pendingScript.getSource(KURL(), errorOccurred);
    EXPECT_FALSE(errorOccurred);
    // ScriptSourceCode doesn't refer to the streamer, since we have suppressed
    // the streaming and resumed the non-streaming code path for script
    // compilation.
    EXPECT_FALSE(sourceCode.streamer());
}

} // namespace

} // namespace blink
<|endoftext|>