<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html

IGNORE:
struct DUMMY { // dummy class for auto indentation

interface_scope:Object:
  BSE_USE_RESULT
  ::Aida::IfaceEventConnection on  (const ::std::string &type, ::Aida::EventHandlerF handler)   { return this->ImplicitBase::__attach__ (type, handler); }
  BSE_USE_RESULT
  ::Aida::IfaceEventConnection on  (const ::std::string &type, ::std::function<void()> vfunc)   { return this->ImplicitBase::__attach__ (type, [vfunc] (const ::Aida::Event&) { vfunc(); }); }
  void     off (::Aida::IfaceEventConnection &hcon)                                             { hcon.disconnect(); }
  void     off (::Aida::IfaceEventConnection *hcon)                                             { hcon->disconnect(); *hcon = ::Aida::IfaceEventConnection();  }
  // as<BseObjectPtr>()
  template<class BseObjectPtr, typename ::std::enable_if<std::is_pointer<BseObjectPtr>::value, bool>::type = true>
  BseObjectPtr           as ()
  {
    static_assert (std::is_pointer<BseObjectPtr>::value, "'BseObject*' required");
    typedef typename std::remove_pointer<BseObjectPtr>::type BseObjectT;
    static_assert (std::is_base_of<GObject, BseObjectT>::value, "'BseObject*' required");
    return (BseObjectPtr) this->as_bse_object();
  }
  // DERIVES_shared_ptr (uses void_t to prevent errors for T without shared_ptr's typedefs)
  template<class T, typename = void> struct DERIVES_shared_ptr : std::false_type {};
  template<class T> struct DERIVES_shared_ptr<T, Bse::void_t< typename T::element_type > > :
  std::is_base_of< std::shared_ptr<typename T::element_type>, T > {};
  // as<shared_ptr<T>>()
  template<class ObjectImplP, typename ::std::enable_if<DERIVES_shared_ptr<ObjectImplP>::value, bool>::type = true>
  ObjectImplP            as ()
  {
    typedef typename ObjectImplP::element_type ObjectImplT;
    static_assert (std::is_base_of<Aida::ImplicitBase, ObjectImplT>::value, "");
    ObjectImplT *impl = dynamic_cast<ObjectImplT*> (this);
    return impl ? Bse::shared_ptr_cast<ObjectImplT> (impl) : NULL;
  }
protected:
  virtual BseObject* as_bse_object() = 0;

IGNORE: // close last _scope
}; // DUMMY
<commit_msg>BSE: bseapi-inserts.hh: on(): use ObjectImpl->__attach__() for connecting<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html

IGNORE:
struct DUMMY { // dummy class for auto indentation

interface_scope:Object:
  BSE_USE_RESULT
  ::Aida::IfaceEventConnection on  (const ::std::string &type, ::Aida::EventHandlerF handler)   { return this->__attach__ (type, handler); }
  BSE_USE_RESULT
  ::Aida::IfaceEventConnection on  (const ::std::string &type, ::std::function<void()> vfunc)   { return this->__attach__ (type, [vfunc] (const ::Aida::Event&) { vfunc(); }); }
  void     off (::Aida::IfaceEventConnection &hcon)                                             { hcon.disconnect(); }
  void     off (::Aida::IfaceEventConnection *hcon)                                             { hcon->disconnect(); *hcon = ::Aida::IfaceEventConnection();  }
  // as<BseObjectPtr>()
  template<class BseObjectPtr, typename ::std::enable_if<std::is_pointer<BseObjectPtr>::value, bool>::type = true>
  BseObjectPtr           as ()
  {
    static_assert (std::is_pointer<BseObjectPtr>::value, "'BseObject*' required");
    typedef typename std::remove_pointer<BseObjectPtr>::type BseObjectT;
    static_assert (std::is_base_of<GObject, BseObjectT>::value, "'BseObject*' required");
    return (BseObjectPtr) this->as_bse_object();
  }
  // DERIVES_shared_ptr (uses void_t to prevent errors for T without shared_ptr's typedefs)
  template<class T, typename = void> struct DERIVES_shared_ptr : std::false_type {};
  template<class T> struct DERIVES_shared_ptr<T, Bse::void_t< typename T::element_type > > :
  std::is_base_of< std::shared_ptr<typename T::element_type>, T > {};
  // as<shared_ptr<T>>()
  template<class ObjectImplP, typename ::std::enable_if<DERIVES_shared_ptr<ObjectImplP>::value, bool>::type = true>
  ObjectImplP            as ()
  {
    typedef typename ObjectImplP::element_type ObjectImplT;
    static_assert (std::is_base_of<Aida::ImplicitBase, ObjectImplT>::value, "");
    ObjectImplT *impl = dynamic_cast<ObjectImplT*> (this);
    return impl ? Bse::shared_ptr_cast<ObjectImplT> (impl) : NULL;
  }
protected:
  virtual BseObject* as_bse_object() = 0;

IGNORE: // close last _scope
}; // DUMMY
<|endoftext|>


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

#include "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <utility>
#include <cmath>
#include <limits>
#include <memory>

#include "modules/common/adapters/proto/adapter_config.pb.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/obstacles/obstacles_container.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using ::apollo::common::adapter::AdapterConfig;
using ::apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() {
  Predictor::Clear();
  adc_lane_id_.clear();
  adc_lane_s_ = 0.0;
}

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const LaneGraph& lane_graph,
    const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(
      num_lane_sequence, LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  // Get ADC status
  GetADC();

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] == LaneChangeType::INVALID) {
        continue;
    }

    double probability = sequence.probability();

    if (LaneSequenceWithMaxProb(
        lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(
        lane_change_type[i], probability, change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    // The obstacle has interference with ADC within a small distance
    if (GetLaneChangeDistanceWithADC(sequence) < FLAGS_lane_change_dist) {
      (*enable_lane_sequence)[i] = false;
      continue;
    }

    double probability = sequence.probability();
    if (probability < FLAGS_lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

void SequencePredictor::GetADC() {
  ObstaclesContainer* container = dynamic_cast<ObstaclesContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PERCEPTION_OBSTACLES));
  if (container == nullptr) {
    AERROR << "Unavailable obstacle container";
    return;
  }

  Obstacle* adc = container->GetObstacle(PoseContainer::ID);
  if (adc != nullptr) {
    const Feature& feature = adc->latest_feature();
    if (feature.has_lane() && feature.lane().has_lane_feature()) {
      adc_lane_id_ = feature.lane().lane_feature().lane_id();
      adc_lane_s_ = feature.lane().lane_feature().lane_s();
    }
    if (feature.has_position()) {
      adc_position_[0] = feature.position().x();
      adc_position_[1] = feature.position().y();
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  PredictionMap* map = PredictionMap::instance();

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    if (map->IsLeftNeighborLane(map->LaneById(lane_change_id),
                                map->LaneById(lane_id))) {
      return LaneChangeType::LEFT;
    } else if (map->IsRightNeighborLane(map->LaneById(lane_change_id),
                                        map->LaneById(lane_id))) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  if (adc_lane_id_.empty() || lane_sequence.lane_segment_size() <= 0) {
    return std::numeric_limits<double>::max();
  }

  PredictionMap* map = PredictionMap::instance();
  std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
  double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();

  if (SameLaneSequence(obstacle_lane_id, obstacle_lane_s)) {
    return std::numeric_limits<double>::max();
  }

  double lane_s = 0.0;
  double lane_l = 0.0;
  if (map->GetProjection(adc_position_, map->LaneById(obstacle_lane_id),
                         &lane_s, &lane_l)) {
    return std::fabs(lane_s - obstacle_lane_s);
  }
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::SameLaneSequence(const std::string& lane_id,
                                         double lane_s) {
  PredictionMap* map = PredictionMap::instance();

  std::shared_ptr<const LaneInfo> obstacle_lane = map->LaneById(lane_id);
  std::shared_ptr<const LaneInfo> adc_lane = map->LaneById(adc_lane_id_);

  if (obstacle_lane != nullptr && adc_lane != nullptr) {
    RoadGraph obstacle_road_graph(lane_s, FLAGS_lane_change_dist,
                                  obstacle_lane);
    LaneGraph obstacle_lane_graph;
    obstacle_road_graph.BuildLaneGraph(&obstacle_lane_graph);

    RoadGraph adc_road_graph(adc_lane_s_, FLAGS_lane_change_dist, adc_lane);
    LaneGraph adc_lane_graph;
    adc_road_graph.BuildLaneGraph(&adc_lane_graph);

    return obstacle_road_graph.IsOnLaneGraph(adc_lane, obstacle_lane_graph) ||
           adc_road_graph.IsOnLaneGraph(obstacle_lane, adc_lane_graph);
  }

  return false;
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double& probability,
                                                const double& max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::abs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double& probability,
                                              const double& max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction: fix the problem of nearby obstacles no prediction trajectories (#826)<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <utility>
#include <cmath>
#include <limits>
#include <memory>

#include "modules/common/adapters/proto/adapter_config.pb.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/obstacles/obstacles_container.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using ::apollo::common::adapter::AdapterConfig;
using ::apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() {
  Predictor::Clear();
  adc_lane_id_.clear();
  adc_lane_s_ = 0.0;
}

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const LaneGraph& lane_graph,
    const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(
      num_lane_sequence, LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  // Get ADC status
  GetADC();

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] == LaneChangeType::INVALID) {
      continue;
    }

    double probability = sequence.probability();

    if (LaneSequenceWithMaxProb(
        lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(
        lane_change_type[i], probability, change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    // The obstacle has interference with ADC within a small distance
    if (GetLaneChangeDistanceWithADC(sequence) < FLAGS_lane_change_dist &&
        (lane_change_type[i] == LaneChangeType::LEFT ||
         lane_change_type[i] == LaneChangeType::RIGHT)) {
      (*enable_lane_sequence)[i] = false;
      continue;
    }

    double probability = sequence.probability();
    if (probability < FLAGS_lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

void SequencePredictor::GetADC() {
  ObstaclesContainer* container = dynamic_cast<ObstaclesContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PERCEPTION_OBSTACLES));
  if (container == nullptr) {
    AERROR << "Unavailable obstacle container";
    return;
  }

  Obstacle* adc = container->GetObstacle(PoseContainer::ID);
  if (adc != nullptr) {
    const Feature& feature = adc->latest_feature();
    if (feature.has_lane() && feature.lane().has_lane_feature()) {
      adc_lane_id_ = feature.lane().lane_feature().lane_id();
      adc_lane_s_ = feature.lane().lane_feature().lane_s();
    }
    if (feature.has_position()) {
      adc_position_[0] = feature.position().x();
      adc_position_[1] = feature.position().y();
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  PredictionMap* map = PredictionMap::instance();

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    if (map->IsLeftNeighborLane(map->LaneById(lane_change_id),
                                map->LaneById(lane_id))) {
      return LaneChangeType::LEFT;
    } else if (map->IsRightNeighborLane(map->LaneById(lane_change_id),
                                        map->LaneById(lane_id))) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  if (adc_lane_id_.empty() || lane_sequence.lane_segment_size() <= 0) {
    return std::numeric_limits<double>::max();
  }

  PredictionMap* map = PredictionMap::instance();
  std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
  double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();

  if (SameLaneSequence(obstacle_lane_id, obstacle_lane_s)) {
    return std::numeric_limits<double>::max();
  }

  double lane_s = 0.0;
  double lane_l = 0.0;
  if (map->GetProjection(adc_position_, map->LaneById(obstacle_lane_id),
                         &lane_s, &lane_l)) {
    return std::fabs(lane_s - obstacle_lane_s);
  }
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::SameLaneSequence(const std::string& lane_id,
                                         double lane_s) {
  PredictionMap* map = PredictionMap::instance();

  std::shared_ptr<const LaneInfo> obstacle_lane = map->LaneById(lane_id);
  std::shared_ptr<const LaneInfo> adc_lane = map->LaneById(adc_lane_id_);

  if (obstacle_lane != nullptr && adc_lane != nullptr) {
    RoadGraph obstacle_road_graph(lane_s, FLAGS_lane_change_dist,
                                  obstacle_lane);
    LaneGraph obstacle_lane_graph;
    obstacle_road_graph.BuildLaneGraph(&obstacle_lane_graph);

    RoadGraph adc_road_graph(adc_lane_s_, FLAGS_lane_change_dist, adc_lane);
    LaneGraph adc_lane_graph;
    adc_road_graph.BuildLaneGraph(&adc_lane_graph);

    return obstacle_road_graph.IsOnLaneGraph(adc_lane, obstacle_lane_graph) ||
           adc_road_graph.IsOnLaneGraph(obstacle_lane, adc_lane_graph);
  }

  return false;
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double& probability,
                                                const double& max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::abs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double& probability,
                                              const double& max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// interface header
#include "TimeKeeper.h"

// system implementation headers
#include <time.h>
#include <string>
#include <string.h>
#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif
#ifdef __BEOS__
#  include <OS.h>
#endif
#if !defined(_WIN32)
#  include <sys/time.h>
#  include <sys/types.h>
static int64_t lastTime = 0;
#  ifdef HAVE_SCHED_H
#    include <sched.h>
#  endif
#else // !defined(_WIN32)
#  include <mmsystem.h>
static unsigned long int lastTime = 0;
static LARGE_INTEGER     qpcLastTime;
static LONGLONG          qpcFrequency = 0;
static LONGLONG          qpcLastCalibration;
static DWORD             timeLastCalibration;
#endif // !defined(_WIN32)

// common implementation headers
#include "TextUtils.h"
#include "bzfio.h"

static TimeKeeper currentTime;
static TimeKeeper tickTime;
static TimeKeeper sunExplodeTime;
static TimeKeeper sunGenesisTime;
static TimeKeeper nullTime;
static TimeKeeper startTime = TimeKeeper::getCurrent();

#if !defined(_WIN32)
static inline int64_t getEpochMicroseconds()
{
  struct timeval nowTime;
  gettimeofday(&nowTime, NULL);
  return (int64_t(nowTime.tv_sec) * int64_t(1000000))
        + int64_t(nowTime.tv_usec);
}
#endif

const TimeKeeper& TimeKeeper::getCurrent(void)
{
  // if not first call then update current time, else use default initial time
#if !defined(_WIN32)
  if (lastTime == 0) {
    // time starts at 0 seconds from the first call to getCurrent()
    lastTime = getEpochMicroseconds();
  }
  else {
    const int64_t nowTime = getEpochMicroseconds();

    int64_t diff = (nowTime - lastTime);
    if (diff < 0) {
      logDebugMessage(1, "WARNING: went back in time %li microseconds\n",
                      (long int)diff);
      diff = 0; // eh, how'd we go back in time?
    }

    currentTime += double(diff) * 1.0e-6;;

    lastTime = nowTime;
  }
#else /* !defined(_WIN32) */
  if (qpcFrequency != 0) {

    // main timer is qpc
    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);

    LONGLONG diff     = now.QuadPart - qpcLastTime.QuadPart;
    LONGLONG clkSpent = now.QuadPart - qpcLastCalibration;
    qpcLastTime = now;

    if (clkSpent > qpcFrequency) {
      // Recalibrate Frequency
      DWORD tgt	   = timeGetTime();
      DWORD deltaTgt      = tgt - timeLastCalibration;
      timeLastCalibration = tgt;
      qpcLastCalibration  = now.QuadPart;
      if (deltaTgt > 0) {
	LONGLONG oldqpcfreq = qpcFrequency;
	qpcFrequency	= (clkSpent * 1000) / deltaTgt;
	if (qpcFrequency != oldqpcfreq)
	  logDebugMessage(4, "Recalibrated QPC frequency.  Old: %f ; New: %f\n",
			  (double)oldqpcfreq, (double)qpcFrequency);
      }
    }

    currentTime += (double) diff / (double) qpcFrequency;
  } else if (lastTime != 0) {
    unsigned long int now = (unsigned long int)timeGetTime();
    unsigned long int diff;
    if (now < lastTime) {
      // eh, how'd we go back in time?
      diff = 0;
    } else {
      diff = now - lastTime;
    }
    currentTime += 1.0e-3 * (double)diff;
    lastTime = now;
  } else {
    static bool sane = true;

    // should only get into here once on app start
    if (!sane) {
      logDebugMessage(1,"Sanity check failure in TimeKeeper::getCurrent()\n");
    }
    sane = false;

    // make sure we're at our best timer resolution possible
    timeBeginPeriod(1);

    LARGE_INTEGER freq;
    if (QueryPerformanceFrequency(&freq)) {
      QueryPerformanceCounter(&qpcLastTime);
      qpcFrequency	= freq.QuadPart;
      logDebugMessage(4,"Actual reported QPC Frequency: %f\n", (double)qpcFrequency);
      qpcLastCalibration  = qpcLastTime.QuadPart;
      timeLastCalibration = timeGetTime();
    } else {
      logDebugMessage(1,"QueryPerformanceFrequency failed with error %d\n", GetLastError());

      lastTime = (unsigned long int)timeGetTime();
    }
  }
#endif /* !defined(_WIN32) */
  return currentTime;
}

const TimeKeeper& TimeKeeper::getStartTime(void) // const
{
  return startTime;
}

const TimeKeeper& TimeKeeper::getTick(void) // const
{
  return tickTime;
}

void TimeKeeper::setTick(void)
{
  tickTime = getCurrent();
}

const TimeKeeper& TimeKeeper::getSunExplodeTime(void)
{
  sunExplodeTime.seconds = 10000.0 * 365 * 24 * 60 * 60;
  return sunExplodeTime;
}

const TimeKeeper& TimeKeeper::getSunGenesisTime(void)
{
  sunGenesisTime.seconds = -10000.0 * 365 * 24 * 60 * 60;
  return sunGenesisTime;
}

const TimeKeeper& TimeKeeper::getNullTime(void)
{
  nullTime.seconds = 0;
  return nullTime;
}

const char *TimeKeeper::timestamp(void) // const
{
  static char buffer[256]; // static, so that it doesn't vanish
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  strncpy (buffer, TextUtils::format("%04d-%02d-%02d %02d:%02d:%02d",
				     now->tm_year, now->tm_mon, now->tm_mday,
				     now->tm_hour, now->tm_min, now->tm_sec).c_str(), 256);
  buffer[255] = '\0'; // safety

  return buffer;
}

/** returns a short string of the local time */
//static
std::string TimeKeeper::shortTimeStamp(void) {
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);

  std::string result( TextUtils::format("%02d:%02d", now->tm_hour, now->tm_min) );
  return result;
}

void TimeKeeper::localTime(int *year, int *month, int* day,
                           int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::localTimeDOW(int *year, int *month, int* day, int* wday,
                              int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::UTCTime(int *year, int *month, int* day, int* wday,
                         int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = gmtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

// function for converting a float time (e.g. difference of two TimeKeepers)
// into an array of ints
void TimeKeeper::convertTime(double raw, long int convertedTimes[]) // const
{
  long int day, hour, min, sec, remainder;
  static const int secondsInDay = 86400;

  sec = (long int)raw;
  day = sec / secondsInDay;
  remainder = sec - (day * secondsInDay);
  hour = remainder / 3600;
  remainder = sec - ((hour * 3600) + (day * secondsInDay));
  min = remainder / 60;
  remainder = sec - ((hour * 3600) + (day * secondsInDay) + (min * 60));
  sec = remainder;

  convertedTimes[0] = day;
  convertedTimes[1] = hour;
  convertedTimes[2] = min;
  convertedTimes[3] = sec;

  return;
}

// function for printing an array of ints representing a time
// as a human-readable string
const std::string TimeKeeper::printTime(long int timeValue[])
{
  std::string valueNames;
  char temp[20];

  if (timeValue[0] > 0) {
    snprintf(temp, 20, "%ld day%s", timeValue[0], timeValue[0] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[1] > 0) {
    if (timeValue[0] > 0) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld hour%s", timeValue[1], timeValue[1] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[2] > 0) {
    if ((timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld min%s", timeValue[2], timeValue[2] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[3] > 0) {
    if ((timeValue[2] > 0) || (timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld sec%s", timeValue[3], timeValue[3] == 1 ? "" : "s");
    valueNames.append(temp);
  }

  return valueNames;
}

// function for printing a float time difference as a human-readable string
const std::string TimeKeeper::printTime(double diff)
{
  long int temp[4];
  convertTime(diff, temp);
  return printTime(temp);
}

void TimeKeeper::sleep(double seconds)
{
  if (seconds <= 0.0) {
    return;
  }

#ifdef HAVE_USLEEP
  usleep((unsigned int)(1.0e6 * seconds));
  return;
#endif
#if defined(HAVE_SLEEP) && !defined(__APPLE__)
  // equivalent to _sleep() on win32 (not sleep(3))
  Sleep((DWORD)(seconds * 1000.0));
  return;
#endif
#ifdef HAVE_SNOOZE
  snooze((bigtime_t)(1.0e6 * seconds));
  return;
#endif
#ifdef HAVE_SELECT
  struct timeval tv;
  tv.tv_sec = (long)seconds;
  tv.tv_usec = (long)(1.0e6 * (seconds - tv.tv_sec));
  select(0, NULL, NULL, NULL, &tv);
  return;
#endif
#ifdef HAVE_WAITFORSINGLEOBJECT
  HANDLE dummyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  WaitForSingleObject(dummyEvent, (DWORD)(1000.0 * seconds));
  CloseHandle(dummyEvent);
  return;
#endif

  // fall-back case is fugly manual timekeeping
  TimeKeeper now = TimeKeeper::getCurrent();
  while ((TimeKeeper::getCurrent() - now) < seconds) {
    continue;
  }
  return;
}

void TimeKeeper::setProcessorAffinity(int processor)
{
#ifdef HAVE_SCHED_SETAFFINITY
  /* linuxy fix for time travel */
  cpu_set_t mask;
  CPU_ZERO(&mask);
  CPU_SET(processor, &mask);
  sched_setaffinity(0, sizeof(mask), &mask);
#elif defined(WIN32)
  /* windowsy fix for time travel */
  HANDLE hThread = GetCurrentThread();
  DWORD_PTR dwMask = 1 << processor;
  DWORD_PTR dwProcs = 0;
  GetProcessAffinityMask(NULL, NULL, &dwProcs);
  if (dwMask < dwProcs) {
    logDebugMessage(1, "Unable to set process affinity mask (specified processor does not exist).\n");
    return;
  }
  SetThreadAffinityMask(hThread, dwMask);
#else
  logDebugMessage(1, "Unable to set processor affinity to %d - function not implemented on this platform.\n", processor);
#endif
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>* changed a debug message level<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// interface header
#include "TimeKeeper.h"

// system implementation headers
#include <time.h>
#include <string>
#include <string.h>
#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif
#ifdef __BEOS__
#  include <OS.h>
#endif
#if !defined(_WIN32)
#  include <sys/time.h>
#  include <sys/types.h>
static int64_t lastTime = 0;
#  ifdef HAVE_SCHED_H
#    include <sched.h>
#  endif
#else // !defined(_WIN32)
#  include <mmsystem.h>
static unsigned long int lastTime = 0;
static LARGE_INTEGER     qpcLastTime;
static LONGLONG          qpcFrequency = 0;
static LONGLONG          qpcLastCalibration;
static DWORD             timeLastCalibration;
#endif // !defined(_WIN32)

// common implementation headers
#include "TextUtils.h"
#include "bzfio.h"

static TimeKeeper currentTime;
static TimeKeeper tickTime;
static TimeKeeper sunExplodeTime;
static TimeKeeper sunGenesisTime;
static TimeKeeper nullTime;
static TimeKeeper startTime = TimeKeeper::getCurrent();

#if !defined(_WIN32)
static inline int64_t getEpochMicroseconds()
{
  struct timeval nowTime;
  gettimeofday(&nowTime, NULL);
  return (int64_t(nowTime.tv_sec) * int64_t(1000000))
        + int64_t(nowTime.tv_usec);
}
#endif

const TimeKeeper& TimeKeeper::getCurrent(void)
{
  // if not first call then update current time, else use default initial time
#if !defined(_WIN32)
  if (lastTime == 0) {
    // time starts at 0 seconds from the first call to getCurrent()
    lastTime = getEpochMicroseconds();
  }
  else {
    const int64_t nowTime = getEpochMicroseconds();

    int64_t diff = (nowTime - lastTime);
    if (diff < 0) {
      logDebugMessage(5, "WARNING: went back in time %li microseconds\n",
                      (long int)diff);
      diff = 0; // eh, how'd we go back in time?
    }

    currentTime += double(diff) * 1.0e-6;;

    lastTime = nowTime;
  }
#else /* !defined(_WIN32) */
  if (qpcFrequency != 0) {

    // main timer is qpc
    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);

    LONGLONG diff     = now.QuadPart - qpcLastTime.QuadPart;
    LONGLONG clkSpent = now.QuadPart - qpcLastCalibration;
    qpcLastTime = now;

    if (clkSpent > qpcFrequency) {
      // Recalibrate Frequency
      DWORD tgt	   = timeGetTime();
      DWORD deltaTgt      = tgt - timeLastCalibration;
      timeLastCalibration = tgt;
      qpcLastCalibration  = now.QuadPart;
      if (deltaTgt > 0) {
	LONGLONG oldqpcfreq = qpcFrequency;
	qpcFrequency	= (clkSpent * 1000) / deltaTgt;
	if (qpcFrequency != oldqpcfreq)
	  logDebugMessage(4, "Recalibrated QPC frequency.  Old: %f ; New: %f\n",
			  (double)oldqpcfreq, (double)qpcFrequency);
      }
    }

    currentTime += (double) diff / (double) qpcFrequency;
  } else if (lastTime != 0) {
    unsigned long int now = (unsigned long int)timeGetTime();
    unsigned long int diff;
    if (now < lastTime) {
      // eh, how'd we go back in time?
      diff = 0;
    } else {
      diff = now - lastTime;
    }
    currentTime += 1.0e-3 * (double)diff;
    lastTime = now;
  } else {
    static bool sane = true;

    // should only get into here once on app start
    if (!sane) {
      logDebugMessage(1,"Sanity check failure in TimeKeeper::getCurrent()\n");
    }
    sane = false;

    // make sure we're at our best timer resolution possible
    timeBeginPeriod(1);

    LARGE_INTEGER freq;
    if (QueryPerformanceFrequency(&freq)) {
      QueryPerformanceCounter(&qpcLastTime);
      qpcFrequency	= freq.QuadPart;
      logDebugMessage(4,"Actual reported QPC Frequency: %f\n", (double)qpcFrequency);
      qpcLastCalibration  = qpcLastTime.QuadPart;
      timeLastCalibration = timeGetTime();
    } else {
      logDebugMessage(1,"QueryPerformanceFrequency failed with error %d\n", GetLastError());

      lastTime = (unsigned long int)timeGetTime();
    }
  }
#endif /* !defined(_WIN32) */
  return currentTime;
}

const TimeKeeper& TimeKeeper::getStartTime(void) // const
{
  return startTime;
}

const TimeKeeper& TimeKeeper::getTick(void) // const
{
  return tickTime;
}

void TimeKeeper::setTick(void)
{
  tickTime = getCurrent();
}

const TimeKeeper& TimeKeeper::getSunExplodeTime(void)
{
  sunExplodeTime.seconds = 10000.0 * 365 * 24 * 60 * 60;
  return sunExplodeTime;
}

const TimeKeeper& TimeKeeper::getSunGenesisTime(void)
{
  sunGenesisTime.seconds = -10000.0 * 365 * 24 * 60 * 60;
  return sunGenesisTime;
}

const TimeKeeper& TimeKeeper::getNullTime(void)
{
  nullTime.seconds = 0;
  return nullTime;
}

const char *TimeKeeper::timestamp(void) // const
{
  static char buffer[256]; // static, so that it doesn't vanish
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  strncpy (buffer, TextUtils::format("%04d-%02d-%02d %02d:%02d:%02d",
				     now->tm_year, now->tm_mon, now->tm_mday,
				     now->tm_hour, now->tm_min, now->tm_sec).c_str(), 256);
  buffer[255] = '\0'; // safety

  return buffer;
}

/** returns a short string of the local time */
//static
std::string TimeKeeper::shortTimeStamp(void) {
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);

  std::string result( TextUtils::format("%02d:%02d", now->tm_hour, now->tm_min) );
  return result;
}

void TimeKeeper::localTime(int *year, int *month, int* day,
                           int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::localTimeDOW(int *year, int *month, int* day, int* wday,
                              int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = localtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

void TimeKeeper::UTCTime(int *year, int *month, int* day, int* wday,
                         int* hour, int* min, int* sec, bool* dst) // const
{
  time_t tnow = time(0);
  struct tm *now = gmtime(&tnow);
  now->tm_year += 1900;
  ++now->tm_mon;

  if (year)  { *year  = now->tm_year; }
  if (month) { *month = now->tm_mon;  }
  if (day)   { *day   = now->tm_mday; }
  if (wday)  { *wday  = now->tm_wday; }
  if (hour)  { *hour  = now->tm_hour; }
  if (min)   { *min   = now->tm_min;  }
  if (sec)   { *sec   = now->tm_sec;  }
  if (dst)   { *dst   = (now->tm_isdst != 0); }
}

// function for converting a float time (e.g. difference of two TimeKeepers)
// into an array of ints
void TimeKeeper::convertTime(double raw, long int convertedTimes[]) // const
{
  long int day, hour, min, sec, remainder;
  static const int secondsInDay = 86400;

  sec = (long int)raw;
  day = sec / secondsInDay;
  remainder = sec - (day * secondsInDay);
  hour = remainder / 3600;
  remainder = sec - ((hour * 3600) + (day * secondsInDay));
  min = remainder / 60;
  remainder = sec - ((hour * 3600) + (day * secondsInDay) + (min * 60));
  sec = remainder;

  convertedTimes[0] = day;
  convertedTimes[1] = hour;
  convertedTimes[2] = min;
  convertedTimes[3] = sec;

  return;
}

// function for printing an array of ints representing a time
// as a human-readable string
const std::string TimeKeeper::printTime(long int timeValue[])
{
  std::string valueNames;
  char temp[20];

  if (timeValue[0] > 0) {
    snprintf(temp, 20, "%ld day%s", timeValue[0], timeValue[0] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[1] > 0) {
    if (timeValue[0] > 0) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld hour%s", timeValue[1], timeValue[1] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[2] > 0) {
    if ((timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld min%s", timeValue[2], timeValue[2] == 1 ? "" : "s");
    valueNames.append(temp);
  }
  if (timeValue[3] > 0) {
    if ((timeValue[2] > 0) || (timeValue[1] > 0) || (timeValue[0] > 0)) {
      valueNames.append(", ");
    }
    snprintf(temp, 20, "%ld sec%s", timeValue[3], timeValue[3] == 1 ? "" : "s");
    valueNames.append(temp);
  }

  return valueNames;
}

// function for printing a float time difference as a human-readable string
const std::string TimeKeeper::printTime(double diff)
{
  long int temp[4];
  convertTime(diff, temp);
  return printTime(temp);
}

void TimeKeeper::sleep(double seconds)
{
  if (seconds <= 0.0) {
    return;
  }

#ifdef HAVE_USLEEP
  usleep((unsigned int)(1.0e6 * seconds));
  return;
#endif
#if defined(HAVE_SLEEP) && !defined(__APPLE__)
  // equivalent to _sleep() on win32 (not sleep(3))
  Sleep((DWORD)(seconds * 1000.0));
  return;
#endif
#ifdef HAVE_SNOOZE
  snooze((bigtime_t)(1.0e6 * seconds));
  return;
#endif
#ifdef HAVE_SELECT
  struct timeval tv;
  tv.tv_sec = (long)seconds;
  tv.tv_usec = (long)(1.0e6 * (seconds - tv.tv_sec));
  select(0, NULL, NULL, NULL, &tv);
  return;
#endif
#ifdef HAVE_WAITFORSINGLEOBJECT
  HANDLE dummyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  WaitForSingleObject(dummyEvent, (DWORD)(1000.0 * seconds));
  CloseHandle(dummyEvent);
  return;
#endif

  // fall-back case is fugly manual timekeeping
  TimeKeeper now = TimeKeeper::getCurrent();
  while ((TimeKeeper::getCurrent() - now) < seconds) {
    continue;
  }
  return;
}

void TimeKeeper::setProcessorAffinity(int processor)
{
#ifdef HAVE_SCHED_SETAFFINITY
  /* linuxy fix for time travel */
  cpu_set_t mask;
  CPU_ZERO(&mask);
  CPU_SET(processor, &mask);
  sched_setaffinity(0, sizeof(mask), &mask);
#elif defined(WIN32)
  /* windowsy fix for time travel */
  HANDLE hThread = GetCurrentThread();
  DWORD_PTR dwMask = 1 << processor;
  DWORD_PTR dwProcs = 0;
  GetProcessAffinityMask(NULL, NULL, &dwProcs);
  if (dwMask < dwProcs) {
    logDebugMessage(1, "Unable to set process affinity mask (specified processor does not exist).\n");
    return;
  }
  SetThreadAffinityMask(hThread, dwMask);
#else
  logDebugMessage(1, "Unable to set processor affinity to %d - function not implemented on this platform.\n", processor);
#endif
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// bzflag common header
#include "common.h"

// class interface header
#include "URLManager.h"

// system headers
#ifdef _WIN32
#include <winsock.h>
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

bool URLManager::getURL(const std::string URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#ifdef HAVE_CURL
  CURLcode curlResult;

#if LIBCURL_VERSION_NUM >= 0x070a00
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);
#endif

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
#endif
}

URLManager::~URLManager()
{
  clearInternal();

#ifdef HAVE_CURL
  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);

#if LIBCURL_VERSION_NUM >= 0x070a00
  curl_global_cleanup();
#endif

#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

#ifdef HAVE_CURL
bool URLManager::beginGet(const std::string URL)
#else
bool URLManager::beginGet(const std::string)
#endif
{
#ifdef HAVE_CURL
  CURLcode result = CURLE_OK;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
#else
  return false;
#endif // HAVE_CURL
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}
#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>better not declare if your not going to use it<commit_after>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// bzflag common header
#include "common.h"

// class interface header
#include "URLManager.h"

// system headers
#ifdef _WIN32
#include <winsock.h>
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

bool URLManager::getURL(const std::string URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#ifdef HAVE_CURL

#if LIBCURL_VERSION_NUM >= 0x070a00
  CURLcode curlResult;
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);
#endif

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
#endif
}

URLManager::~URLManager()
{
  clearInternal();

#ifdef HAVE_CURL
  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);

#if LIBCURL_VERSION_NUM >= 0x070a00
  curl_global_cleanup();
#endif

#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

#ifdef HAVE_CURL
bool URLManager::beginGet(const std::string URL)
#else
bool URLManager::beginGet(const std::string)
#endif
{
#ifdef HAVE_CURL
  CURLcode result = CURLE_OK;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
#else
  return false;
#endif // HAVE_CURL
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}
#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2004 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

// bzflag common header

#include "common.h"

#include "URLManager.h"
#include <iostream>

#include "bzfio.h"

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

#ifdef HAVE_CURL
bool URLManager::getURL ( const std::string URL, std::string &data )
#else
bool URLManager::getURL ( const std::string, std::string&)
#endif // HAVE_CURL
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode result;
	if (!easyHandle) {
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, 5);
	if (result)
	  DEBUG1("Something wrong with CURL; Error: %d",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
	if (result) {
		DEBUG1("Something wrong with CURL; Error:  %d",result);
		return false;
	}

	result = curl_easy_perform((CURL*)easyHandle);
	if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
		DEBUG1("Error: server reported: %d",result);
		return false;
	}else if (result) {
		DEBUG1("Something wrong with CURL; Error: %d",result);
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
	if (result) {
		DEBUG1("Something wrong with CURL; Error: %d",result);
		return false;
	}

	if (!theData)
		return false;

	char	* newData = (char*)malloc(theLen + 1);
	memcpy(newData,theData,theLen);

	newData[theLen] = 0;

	data = newData;
	free(newData);

	return true;
#endif
	return false;
}

#ifdef HAVE_CURL
bool URLManager::getURL ( const std::string URL, void **data, unsigned int& size )
#else
bool URLManager::getURL (const std::string, void **, unsigned int&)
#endif // HAVE_CURL
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode result;
	if (!easyHandle) {
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, 60);
	if (result)
	  DEBUG1("Something wrong with CURL; Error: %d",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
	if (result) {
		DEBUG1("Something wrong with CURL; Error:  %d",result);
	}

	result = curl_easy_perform((CURL*)easyHandle);
	if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
		DEBUG1("Error: server reported: %d",result);
		return false;
	}else if (result) {
		DEBUG1("Something wrong with CURL; Error: %d",result);
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
	if (result) {
		DEBUG1("Something wrong with CURL; Error: %d",result);
		return false;
	}

	if (!theData)
		return false;

	*data = malloc(theLen);
	memcpy(*data,theData,theLen);
	size = theLen;
	return true;
#endif
	return false;
}

void URLManager::freeURLData ( void *data )
{
	free(data);
}

URLManager::URLManager()
{
	easyHandle = NULL;
	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode curlResult;
	if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
		DEBUG1("Unexpected error from libcurl; Error: %d",curlResult);

	easyHandle = curl_easy_init();
	if (!easyHandle) {
		DEBUG1("Something wrong with CURL");
		return;
	}

	CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
	if (result)
			DEBUG1("Something wrong with CURL; Error: %d",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
	if (result)
		DEBUG1("Something wrong with CURL; Error: %d",result);
#endif
}

URLManager::~URLManager()
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	if (easyHandle)
		curl_easy_cleanup((CURL*)easyHandle);
	curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
	unsigned char	*newData = (unsigned char*)malloc(theLen + len);
	if (theData)
		memcpy(newData,theData,theLen);

	memcpy(&(newData[theLen]),ptr,len);
	theLen+= len;

	free(theData);
	theData = newData;
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb,void *stream)
{
	int len = size * nmemb;
	((URLManager *)stream)->collectData((char *)ptr, len);
	return len;
}
#endif // HAVE_CURL

<commit_msg>Newlines on DEBUG messages<commit_after>/* bzflag
* Copyright (c) 1993 - 2004 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

// bzflag common header

#include "common.h"

#include "URLManager.h"
#include <iostream>

#include "bzfio.h"

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

#ifdef HAVE_CURL
bool URLManager::getURL ( const std::string URL, std::string &data )
#else
bool URLManager::getURL ( const std::string, std::string&)
#endif // HAVE_CURL
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode result;
	if (!easyHandle) {
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, 5);
	if (result)
	  DEBUG1("Something wrong with CURL; Error: %d\n",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
	if (result) {
		DEBUG1("Something wrong with CURL; Error:  %d\n",result);
		return false;
	}

	result = curl_easy_perform((CURL*)easyHandle);
	if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
		DEBUG1("Error: server reported: %d\n",result);
		return false;
	} else if (result) {
		DEBUG1("Something wrong with CURL; Error: %d\n",result);
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
	if (result) {
		DEBUG1("Something wrong with CURL; Error: %d\n",result);
		return false;
	}

	if (!theData)
		return false;

	char	* newData = (char*)malloc(theLen + 1);
	memcpy(newData,theData,theLen);

	newData[theLen] = 0;

	data = newData;
	free(newData);

	return true;
#endif
	return false;
}

#ifdef HAVE_CURL
bool URLManager::getURL ( const std::string URL, void **data, unsigned int& size )
#else
bool URLManager::getURL (const std::string, void **, unsigned int&)
#endif // HAVE_CURL
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode result;
	if (!easyHandle) {
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, 60);
	if (result)
	  DEBUG1("Something wrong with CURL; Error: %d\n",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
	if (result) {
		DEBUG1("Something wrong with CURL; Error:  %d\n",result);
	}

	result = curl_easy_perform((CURL*)easyHandle);
	if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
		DEBUG1("Error: server reported: %d\n",result);
		return false;
	} else if (result) {
		DEBUG1("Something wrong with CURL; Error: %d\n",result);
		return false;
	}

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
	if (result) {
		DEBUG1("Something wrong with CURL; Error: %d\n",result);
		return false;
	}

	if (!theData)
		return false;

	*data = malloc(theLen);
	memcpy(*data,theData,theLen);
	size = theLen;
	return true;
#endif
	return false;
}

void URLManager::freeURLData ( void *data )
{
	free(data);
}

URLManager::URLManager()
{
	easyHandle = NULL;
	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	CURLcode curlResult;
	if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
		DEBUG1("Unexpected error from libcurl; Error: %d\n",curlResult);

	easyHandle = curl_easy_init();
	if (!easyHandle) {
		DEBUG1("Something wrong with CURL\n");
		return;
	}

	CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
	if (result)
			DEBUG1("Something wrong with CURL; Error: %d\n",result);

	result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
	if (result)
		DEBUG1("Something wrong with CURL; Error: %d\n",result);
#endif
}

URLManager::~URLManager()
{
	if (theData)
		free (theData);

	theData = NULL;
	theLen = 0;

#ifdef HAVE_CURL
	if (easyHandle)
		curl_easy_cleanup((CURL*)easyHandle);
	curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
	unsigned char	*newData = (unsigned char*)malloc(theLen + len);
	if (theData)
		memcpy(newData,theData,theLen);

	memcpy(&(newData[theLen]),ptr,len);
	theLen+= len;

	free(theData);
	theData = newData;
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb,void *stream)
{
	int len = size * nmemb;
	((URLManager *)stream)->collectData((char *)ptr, len);
	return len;
}
#endif // HAVE_CURL

<|endoftext|>


<commit_before>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "AutoNetServerImpl.hpp"
#include "at_exit.h"
#include "autowiring.h"
#include "demangle.h"
#include "ObjectTraits.h"
#include "EventRegistry.h"
#include "TypeRegistry.h"
#include <iostream>
#include FUTURE_HEADER

using std::placeholders::_1;
using std::placeholders::_2;
using json11::Json;

AutoNetServerImpl::AutoNetServerImpl(void) :
  m_Port(8000)
{
  // Configure websocketpp
  m_Server.init_asio();
  m_Server.set_access_channels(websocketpp::log::alevel::none);
  m_Server.set_error_channels(websocketpp::log::elevel::none);

  // Register handlers
  m_Server.set_open_handler(std::bind(&AutoNetServerImpl::OnOpen, this, ::_1));
  m_Server.set_close_handler(std::bind(&AutoNetServerImpl::OnClose, this, ::_1));
  m_Server.set_message_handler(std::bind(&AutoNetServerImpl::OnMessage, this, ::_1, ::_2));

  // Generate list of all types from type registry
  for(auto type = g_pFirstTypeEntry; type; type = type->pFlink)
    if(type->CanInject())
      m_AllTypes[autowiring::demangle(type->ti)] = [type]{ type->Inject(); };

  // Generate list of all events from event registry
  for(auto event = g_pFirstEventEntry; event; event = event->pFlink)
    m_EventTypes.insert(event->NewTypeIdentifier());
}

AutoNetServerImpl::~AutoNetServerImpl()
{
}

AutoNetServer* NewAutoNetServerImpl(void) {
  return new AutoNetServerImpl;
}

// CoreThread overrides
void AutoNetServerImpl::Run(void){
  std::cout << "Starting Autonet server..." << std::endl;

  m_Server.listen(m_Port);
  m_Server.start_accept();

  // blocks until the server finishes
  auto websocket = std::async(std::launch::async, [this]{
    m_Server.run();
  });

  PollThreadUtilization(std::chrono::milliseconds(1000));
  CoreThread::Run();
}

void AutoNetServerImpl::OnStop(void) {
  if (m_Server.is_listening())
    m_Server.stop_listening();

  for (auto& conn : m_Subscribers) {
    m_Server.close(conn, websocketpp::close::status::normal, "closed");
  }
}

// Server Handler functions
void AutoNetServerImpl::OnOpen(websocketpp::connection_hdl hdl) {
  *this += [this, hdl] {
    SendMessage(hdl, "opened");
  };
}
void AutoNetServerImpl::OnClose(websocketpp::connection_hdl hdl) {
  *this += [this, hdl] {
    this->m_Subscribers.erase(hdl);
  };
}

void AutoNetServerImpl::OnMessage(websocketpp::connection_hdl hdl, message_ptr p_message) {
  // Parse string from client
  std::string err;
  Json msg = Json::parse(p_message->get_payload(), err);

  if(!err.empty()) {
    std::cout << "Parse error: " << err << std::endl;
    SendMessage(hdl, "invalidMessage", "Couldn't parse message");
    return;
  }

  std::string msgType = msg["type"].string_value();
  Json::array msgArgs = msg["args"].array_items();

  *this += [this, hdl, msgType, msgArgs] {
    if(msgType == "subscribe") HandleSubscribe(hdl);
    else if(msgType == "unsubscribe") HandleUnsubscribe(hdl);
    else if(msgType == "terminateContext") HandleTerminateContext(msgArgs[0].int_value());
    else if(msgType == "injectContextMember") HandleInjectContextMember(msgArgs[0].int_value(), msgArgs[1].string_value());
    else if(msgType == "resumeFromBreakpoint") HandleResumeFromBreakpoint(msgArgs[0].string_value());
    else
      SendMessage(hdl, "invalidMessage", "Message type not recognized");
  };
}

void AutoNetServerImpl::Breakpoint(std::string name){
  std::unique_lock<std::mutex> lk(m_mutex);

  m_breakpoints.insert(name);

  *this += [this, name]{
    BroadcastMessage("breakpoint", name);
  };

  m_breakpoint_cv.wait(lk, [this, name]{
    return !m_breakpoints.count(name);
  });
}

// Update Functions
void AutoNetServerImpl::NewContext(CoreContext& newCtxt){
  auto ctxt = newCtxt.shared_from_this();

  *this += [this, ctxt] {
    Json::object context{
        {"name", autowiring::demangle(ctxt->GetSigilType())}
    };

    if(ctxt->GetParentContext()){
      context["parent"] = ResolveContextID(ctxt->GetParentContext().get());
    }

    BroadcastMessage("newContext", ResolveContextID(ctxt.get()), context);
  };
}

void AutoNetServerImpl::ExpiredContext(CoreContext& oldCtxt){
  int id = ResolveContextID(&oldCtxt);
  *this += [this, id] {
    BroadcastMessage("expiredContext", id);
  };
}

void AutoNetServerImpl::NewObject(CoreContext& ctxt, const ObjectTraits& object){
  int contextID = ResolveContextID(&ctxt);

  *this += [this, object, contextID]{
    Json::object objData;
    Json::object types;

    // Add object data
    objData["name"] = autowiring::demangle(typeid(*object.pObject));
    {
      Json::array slots;
      for(auto slot = object.stump.pHead; slot; slot = slot->pFlink) {
        slots.push_back(Json::object{
            {"name", autowiring::demangle(slot->type)},
            {"autoRequired", slot->autoRequired},
            {"offset", int(slot->slotOffset)}
        });
      }
      objData["slots"] = slots;
    }

    // Add type information
    auto member = object.pContextMember;
    if(member) {
      types["contextMember"] = true;
    }

    auto runnable = object.pCoreRunnable;
    if(runnable) {
      types["coreRunnable"] = true;
    }

    auto thread = object.pBasicThread;
    if(thread) {
      // Create slot in map
      m_Threads[thread->GetSelf<BasicThread>()];

      types["thread"] = Json::object{
          {"kernal", 0.0},
          {"user", 0.0}
      };
    }

    // Check if type implements an AutoFilter
    if (!object.subscriber.empty()) {
      Json::object args;
      for (auto pArg = object.subscriber.GetAutoFilterInput(); *pArg; ++pArg) {
        args[autowiring::demangle(pArg->ti)] = Json::object{
          {"isInput", pArg->is_input || bool(pArg->tshift)},
          {"isOutput", pArg->is_output}
        };
      }
      types["autoFilter"] = args;
    }

    // Check if type receives any events
    {
      Json::array listenerTypes;
      for(const auto& event : m_EventTypes) {
        if(event->IsSameAs(object.pObject.get()))
          listenerTypes.push_back(autowiring::demangle(event->Type()));
      }

      if(!listenerTypes.empty())
        types["eventReceiver"] = listenerTypes;
    }

    auto filter = object.pFilter;
    if(filter) {
      types["exceptionFilter"] = true;
    }

    auto bolt = object.pBoltBase;
    if(bolt) {
      Json::array sigils;
      for(auto cur = bolt->GetContextSigils(); *cur; cur++){
        sigils.push_back(autowiring::demangle(**cur));
      }
      types["bolt"] = sigils;
    }

    BroadcastMessage("newObject", contextID, types, objData);
  };
}

void AutoNetServerImpl::EventFired(CoreContext& context, const std::type_info& info){
  int contextID = ResolveContextID(&context);
  std::string name = autowiring::demangle(info);

  *this += [this, contextID, name] {
    BroadcastMessage("eventFired", contextID, Json::object{{"name", name}});
  };
}

void AutoNetServerImpl::HandleSubscribe(websocketpp::connection_hdl hdl) {
  m_Subscribers.insert(hdl);

  Json::array types;
  for(const auto& type : m_AllTypes) {
    types.push_back(type.first);
  }

  SendMessage(hdl, "subscribed", types);
  GetContext()->BuildCurrentState();

  // Send breakpoint message
  for(const auto& breakpoint : m_breakpoints) {
    SendMessage(hdl, "breakpoint", breakpoint);
  }
}

void AutoNetServerImpl::HandleUnsubscribe(websocketpp::connection_hdl hdl) {
  this->m_Subscribers.erase(hdl);
  SendMessage(hdl, "unsubscribed");
}

void AutoNetServerImpl::HandleTerminateContext(int contextID) {
  ResolveContextID(contextID)->SignalShutdown();
}

void AutoNetServerImpl::HandleInjectContextMember(int contextID, std::string typeName) {
  std::shared_ptr<CoreContext> ctxt = ResolveContextID(contextID)->shared_from_this();

  if(m_AllTypes.find(typeName) != m_AllTypes.end()) {
    CurrentContextPusher pshr(ctxt);
    m_AllTypes[typeName]();
  }
  else {
    // Type doesn't exist
    assert(false);
  }
}

void AutoNetServerImpl::HandleResumeFromBreakpoint(std::string name){
  std::unique_lock<std::mutex> lk(m_mutex);

  m_breakpoints.erase(name);
  m_breakpoint_cv.notify_all();
}

//helper functions
int AutoNetServerImpl::ResolveContextID(CoreContext* ctxt) {
  static int counter = 0;

  if(m_ContextIDs.find(ctxt) == m_ContextIDs.end()){
    m_ContextIDs[ctxt] = counter;
    m_ContextPtrs[counter] = ctxt;
    return counter++;
  }
  else {
    return m_ContextIDs[ctxt];
  }
}

CoreContext* AutoNetServerImpl::ResolveContextID(int id) {
  return m_ContextPtrs.at(id);
}

void AutoNetServerImpl::PollThreadUtilization(std::chrono::milliseconds period){

  *this += period, [this, period] {

    for(auto q = m_Threads.begin(); q != m_Threads.end();) {
      std::shared_ptr<BasicThread> thread = q->first.lock();
      if(!thread) {
        m_Threads.erase(q++);
        continue;
      }

      std::chrono::milliseconds runtimeKM, runtimeUM;
      thread->GetThreadTimes(runtimeKM, runtimeUM);

      // Determine the amount of time this thread has run since the last time we
      // asked it for its runtime.
      std::chrono::duration<double> deltaRuntimeKM = runtimeKM - q->second.m_lastRuntimeKM;
      std::chrono::duration<double> deltaRuntimeUM = runtimeUM - q->second.m_lastRuntimeUM;

      // Update timing values:
      q->second.m_lastRuntimeKM = runtimeKM;
      q->second.m_lastRuntimeUM = runtimeUM;

      // Broadcast current thread utilization
      int contextID = ResolveContextID(thread->GetContext().get());
      std::string name = autowiring::demangle(typeid(*thread.get()));

      std::chrono::duration<double> periodDbl = period;
      double kmPercent = 100.0 * (deltaRuntimeKM.count() / periodDbl.count());
      double umPercent = 100.0 * (deltaRuntimeUM.count() / periodDbl.count());

      // Make sure user + kernel percent < 100.0
      umPercent = std::min(umPercent, 99.9 - kmPercent);

      if(kmPercent >= 0.0 && umPercent >= 0.0) {
        BroadcastMessage("threadUtilization", contextID, name, kmPercent, umPercent);
      }

      // Next!
      q++;
    }

    // Poll again after "period" milliseconds
    PollThreadUtilization(period);
  };
}
<commit_msg>Fixing warning in MSVC<commit_after>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "AutoNetServerImpl.hpp"
#include "at_exit.h"
#include "autowiring.h"
#include "demangle.h"
#include "ObjectTraits.h"
#include "EventRegistry.h"
#include "TypeRegistry.h"
#include <iostream>
#include FUTURE_HEADER

using std::placeholders::_1;
using std::placeholders::_2;
using json11::Json;

AutoNetServerImpl::AutoNetServerImpl(void) :
  m_Port(8000)
{
  // Configure websocketpp
  m_Server.init_asio();
  m_Server.set_access_channels(websocketpp::log::alevel::none);
  m_Server.set_error_channels(websocketpp::log::elevel::none);

  // Register handlers
  m_Server.set_open_handler(std::bind(&AutoNetServerImpl::OnOpen, this, ::_1));
  m_Server.set_close_handler(std::bind(&AutoNetServerImpl::OnClose, this, ::_1));
  m_Server.set_message_handler(std::bind(&AutoNetServerImpl::OnMessage, this, ::_1, ::_2));

  // Generate list of all types from type registry
  for(auto type = g_pFirstTypeEntry; type; type = type->pFlink)
    if(type->CanInject())
      m_AllTypes[autowiring::demangle(type->ti)] = [type]{ type->Inject(); };

  // Generate list of all events from event registry
  for(auto event = g_pFirstEventEntry; event; event = event->pFlink)
    m_EventTypes.insert(event->NewTypeIdentifier());
}

AutoNetServerImpl::~AutoNetServerImpl()
{
}

AutoNetServer* NewAutoNetServerImpl(void) {
  return new AutoNetServerImpl;
}

// CoreThread overrides
void AutoNetServerImpl::Run(void){
  std::cout << "Starting Autonet server..." << std::endl;

  m_Server.listen(m_Port);
  m_Server.start_accept();

  // blocks until the server finishes
  auto websocket = std::async(std::launch::async, [this]{
    m_Server.run();
  });

  PollThreadUtilization(std::chrono::milliseconds(1000));
  CoreThread::Run();
}

void AutoNetServerImpl::OnStop(void) {
  if (m_Server.is_listening())
    m_Server.stop_listening();

  for (auto& conn : m_Subscribers) {
    m_Server.close(conn, websocketpp::close::status::normal, "closed");
  }
}

// Server Handler functions
void AutoNetServerImpl::OnOpen(websocketpp::connection_hdl hdl) {
  *this += [this, hdl] {
    SendMessage(hdl, "opened");
  };
}
void AutoNetServerImpl::OnClose(websocketpp::connection_hdl hdl) {
  *this += [this, hdl] {
    this->m_Subscribers.erase(hdl);
  };
}

void AutoNetServerImpl::OnMessage(websocketpp::connection_hdl hdl, message_ptr p_message) {
  // Parse string from client
  std::string err;
  Json msg = Json::parse(p_message->get_payload(), err);

  if(!err.empty()) {
    std::cout << "Parse error: " << err << std::endl;
    SendMessage(hdl, "invalidMessage", "Couldn't parse message");
    return;
  }

  std::string msgType = msg["type"].string_value();
  Json::array msgArgs = msg["args"].array_items();

  *this += [this, hdl, msgType, msgArgs] {
    if(msgType == "subscribe") HandleSubscribe(hdl);
    else if(msgType == "unsubscribe") HandleUnsubscribe(hdl);
    else if(msgType == "terminateContext") HandleTerminateContext(msgArgs[0].int_value());
    else if(msgType == "injectContextMember") HandleInjectContextMember(msgArgs[0].int_value(), msgArgs[1].string_value());
    else if(msgType == "resumeFromBreakpoint") HandleResumeFromBreakpoint(msgArgs[0].string_value());
    else
      SendMessage(hdl, "invalidMessage", "Message type not recognized");
  };
}

void AutoNetServerImpl::Breakpoint(std::string name){
  std::unique_lock<std::mutex> lk(m_mutex);

  m_breakpoints.insert(name);

  *this += [this, name]{
    BroadcastMessage("breakpoint", name);
  };

  m_breakpoint_cv.wait(lk, [this, name]{
    return !m_breakpoints.count(name);
  });
}

// Update Functions
void AutoNetServerImpl::NewContext(CoreContext& newCtxt){
  auto ctxt = newCtxt.shared_from_this();

  *this += [this, ctxt] {
    Json::object context{
        {"name", autowiring::demangle(ctxt->GetSigilType())}
    };

    if(ctxt->GetParentContext()){
      context["parent"] = ResolveContextID(ctxt->GetParentContext().get());
    }

    BroadcastMessage("newContext", ResolveContextID(ctxt.get()), context);
  };
}

void AutoNetServerImpl::ExpiredContext(CoreContext& oldCtxt){
  int id = ResolveContextID(&oldCtxt);
  *this += [this, id] {
    BroadcastMessage("expiredContext", id);
  };
}

void AutoNetServerImpl::NewObject(CoreContext& ctxt, const ObjectTraits& object){
  int contextID = ResolveContextID(&ctxt);

  *this += [this, object, contextID]{
    Json::object objData;
    Json::object types;

    // Add object data
    objData["name"] = autowiring::demangle(typeid(*object.pObject));
    {
      Json::array slots;
      for(auto slot = object.stump.pHead; slot; slot = slot->pFlink) {
        slots.push_back(Json::object{
            {"name", autowiring::demangle(slot->type)},
            {"autoRequired", slot->autoRequired},
            {"offset", int(slot->slotOffset)}
        });
      }
      objData["slots"] = slots;
    }

    // Add type information
    auto member = object.pContextMember;
    if(member) {
      types["contextMember"] = true;
    }

    auto runnable = object.pCoreRunnable;
    if(runnable) {
      types["coreRunnable"] = true;
    }

    auto thread = object.pBasicThread;
    if(thread) {
      // Create slot in map
      m_Threads[thread->GetSelf<BasicThread>()];

      types["thread"] = Json::object{
          {"kernal", 0.0},
          {"user", 0.0}
      };
    }

    // Check if type implements an AutoFilter
    if (!object.subscriber.empty()) {
      Json::object args;
      for (auto pArg = object.subscriber.GetAutoFilterInput(); *pArg; ++pArg) {
        args[autowiring::demangle(pArg->ti)] = Json::object{
          {"isInput", pArg->is_input || pArg->tshift},
          {"isOutput", pArg->is_output}
        };
      }
      types["autoFilter"] = args;
    }

    // Check if type receives any events
    {
      Json::array listenerTypes;
      for(const auto& event : m_EventTypes) {
        if(event->IsSameAs(object.pObject.get()))
          listenerTypes.push_back(autowiring::demangle(event->Type()));
      }

      if(!listenerTypes.empty())
        types["eventReceiver"] = listenerTypes;
    }

    auto filter = object.pFilter;
    if(filter) {
      types["exceptionFilter"] = true;
    }

    auto bolt = object.pBoltBase;
    if(bolt) {
      Json::array sigils;
      for(auto cur = bolt->GetContextSigils(); *cur; cur++){
        sigils.push_back(autowiring::demangle(**cur));
      }
      types["bolt"] = sigils;
    }

    BroadcastMessage("newObject", contextID, types, objData);
  };
}

void AutoNetServerImpl::EventFired(CoreContext& context, const std::type_info& info){
  int contextID = ResolveContextID(&context);
  std::string name = autowiring::demangle(info);

  *this += [this, contextID, name] {
    BroadcastMessage("eventFired", contextID, Json::object{{"name", name}});
  };
}

void AutoNetServerImpl::HandleSubscribe(websocketpp::connection_hdl hdl) {
  m_Subscribers.insert(hdl);

  Json::array types;
  for(const auto& type : m_AllTypes) {
    types.push_back(type.first);
  }

  SendMessage(hdl, "subscribed", types);
  GetContext()->BuildCurrentState();

  // Send breakpoint message
  for(const auto& breakpoint : m_breakpoints) {
    SendMessage(hdl, "breakpoint", breakpoint);
  }
}

void AutoNetServerImpl::HandleUnsubscribe(websocketpp::connection_hdl hdl) {
  this->m_Subscribers.erase(hdl);
  SendMessage(hdl, "unsubscribed");
}

void AutoNetServerImpl::HandleTerminateContext(int contextID) {
  ResolveContextID(contextID)->SignalShutdown();
}

void AutoNetServerImpl::HandleInjectContextMember(int contextID, std::string typeName) {
  std::shared_ptr<CoreContext> ctxt = ResolveContextID(contextID)->shared_from_this();

  if(m_AllTypes.find(typeName) != m_AllTypes.end()) {
    CurrentContextPusher pshr(ctxt);
    m_AllTypes[typeName]();
  }
  else {
    // Type doesn't exist
    assert(false);
  }
}

void AutoNetServerImpl::HandleResumeFromBreakpoint(std::string name){
  std::unique_lock<std::mutex> lk(m_mutex);

  m_breakpoints.erase(name);
  m_breakpoint_cv.notify_all();
}

//helper functions
int AutoNetServerImpl::ResolveContextID(CoreContext* ctxt) {
  static int counter = 0;

  if(m_ContextIDs.find(ctxt) == m_ContextIDs.end()){
    m_ContextIDs[ctxt] = counter;
    m_ContextPtrs[counter] = ctxt;
    return counter++;
  }
  else {
    return m_ContextIDs[ctxt];
  }
}

CoreContext* AutoNetServerImpl::ResolveContextID(int id) {
  return m_ContextPtrs.at(id);
}

void AutoNetServerImpl::PollThreadUtilization(std::chrono::milliseconds period){

  *this += period, [this, period] {

    for(auto q = m_Threads.begin(); q != m_Threads.end();) {
      std::shared_ptr<BasicThread> thread = q->first.lock();
      if(!thread) {
        m_Threads.erase(q++);
        continue;
      }

      std::chrono::milliseconds runtimeKM, runtimeUM;
      thread->GetThreadTimes(runtimeKM, runtimeUM);

      // Determine the amount of time this thread has run since the last time we
      // asked it for its runtime.
      std::chrono::duration<double> deltaRuntimeKM = runtimeKM - q->second.m_lastRuntimeKM;
      std::chrono::duration<double> deltaRuntimeUM = runtimeUM - q->second.m_lastRuntimeUM;

      // Update timing values:
      q->second.m_lastRuntimeKM = runtimeKM;
      q->second.m_lastRuntimeUM = runtimeUM;

      // Broadcast current thread utilization
      int contextID = ResolveContextID(thread->GetContext().get());
      std::string name = autowiring::demangle(typeid(*thread.get()));

      std::chrono::duration<double> periodDbl = period;
      double kmPercent = 100.0 * (deltaRuntimeKM.count() / periodDbl.count());
      double umPercent = 100.0 * (deltaRuntimeUM.count() / periodDbl.count());

      // Make sure user + kernel percent < 100.0
      umPercent = std::min(umPercent, 99.9 - kmPercent);

      if(kmPercent >= 0.0 && umPercent >= 0.0) {
        BroadcastMessage("threadUtilization", contextID, name, kmPercent, umPercent);
      }

      // Next!
      q++;
    }

    // Poll again after "period" milliseconds
    PollThreadUtilization(period);
  };
}
<|endoftext|>


<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

    This program 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 General Public License for more details.

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

#include "Board.h"
#include "Variables.h"

volatile uint8_t    digitalInBuffer[NUMBER_OF_BUTTON_COLUMNS];
volatile uint8_t    digitalInBuffer_copy[NUMBER_OF_BUTTON_COLUMNS];
volatile uint8_t    activeInColumn;

bool Board::digitalInputDataAvailable()
{
    return (activeInColumn == NUMBER_OF_BUTTON_COLUMNS);
}

void Board::continueDigitalInReadout()
{
    activeInColumn = 0;
}
<commit_msg>remove unused array<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

    This program 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 General Public License for more details.

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

#include "Board.h"
#include "Variables.h"

volatile uint8_t    digitalInBuffer[NUMBER_OF_BUTTON_COLUMNS];
volatile uint8_t    activeInColumn;

bool Board::digitalInputDataAvailable()
{
    return (activeInColumn == NUMBER_OF_BUTTON_COLUMNS);
}

void Board::continueDigitalInReadout()
{
    activeInColumn = 0;
}
<|endoftext|>