text:
#pragma once
//===----------------------------------------------------------------------===//
#include <dtl/bitmap/bitwise_operations.hpp>
#include <dtl/dtl.hpp>

#include <boost/dynamic_bitset.hpp>

#include <memory>
//===----------------------------------------------------------------------===//
namespace dtl {
//===----------------------------------------------------------------------===//
/// Extends a bitmap by a differential data structure. All updates are written
/// to the differential data structure which is merged on request.
///
/// The differential data structure could be of any bitmap type that implements
/// the set(idx, bool) function and a constructor T(size_t) to create an empty
/// bitmap.
///
/// Note that read accesses become more costly, as the XOR of the bitmap and
/// diff needs to be computed on-the-fly.
template<
    /// The (compressed) bitmap type.
    typename B,
    /// The differential data structure to use.
    typename D>
class diff {
  /// The (compressed) bitmap.
  std::unique_ptr<B> bitmap_;
  /// Contains the pending updates.
  std::unique_ptr<D> diff_;
  /// Used to avoid unnecessary merge operations.
  $u1 has_pending_updates_;

public:
  using bitmap_type = B;
  using diff_type = D;

  /// C'tor (similar to all other implementations)
  diff(const boost::dynamic_bitset<$u32>& bitmap)
      : bitmap_(std::make_unique<B>(bitmap)),
        diff_(std::make_unique<D>(bitmap.size())),
        has_pending_updates_(false) {}

  /// Return the name of the implementation.
  static std::string
  name() noexcept {
    return std::string("diff<")
        + B::name() + std::string(",") + D::name()
        + std::string(">");
  }

  /// Returns the length of the original bitmap.
  std::size_t __forceinline__
  size() const noexcept {
    return bitmap_->size();
  }

  /// Return the size in bytes.
  std::size_t __forceinline__
  size_in_bytes() const noexcept {
    return bitmap_->size_in_bytes() + diff_->size_in_bytes()
        + 16; // two pointers
  }

  /// Return the size of the differential data structure in bytes.
  std::size_t __forceinline__
  diff_size_in_bytes() const noexcept {
    return diff_->size_in_bytes();
  }

  /// Returns the name of the instance including the most important parameters
  /// in JSON.
  std::string
  info() const noexcept {
    return "{\"name\":\"" + name() + "\""
        + ",\"bitmap\":" + bitmap_->info()
        + ",\"diff\":" + diff_->info()
        + "}";
  }

  /// For debugging purposes.
  void
  print(std::ostream& os) const noexcept {
    os << *bitmap_ << ", diff = " << *diff_;
  }

  //===--------------------------------------------------------------------===//
  // Update related functions. - Updates are forwarded to the differential data
  // structure, and merged only on request.
  //===--------------------------------------------------------------------===//
  /// Set the i-th bit to the given value.
  void __forceinline__
  set(std::size_t i, u1 val) noexcept {
    has_pending_updates_ = true;
    u1 bitmap_val = bitmap_->test(i);
    u1 diff_val = diff_->test(i);
    u1 current_val = bitmap_val ^ diff_val;
    if (current_val != val) {
      diff_->set(i, bitmap_val ^ val);
      // NOTE: If we do not shrink here, the memory consumption can explode,
      // as WAH and Roaring (when used as differential data structure) may
      // internally use an uncompressed bitmap.
      // On the other hand point updates become more expensive.
      diff_->shrink();
    }
  }

  /// Apply the pending updates and clear the diff.
  template<typename M>
  void
  merge() {
    if (!has_pending_updates_) return;

    // Apply the updates.
    M merge_strategy;
    merge_strategy.merge(bitmap_, diff_);

    // Clear the diff.
    std::unique_ptr<D> empty_diff = std::make_unique<D>(bitmap_->size());
    std::swap(diff_, empty_diff);
  }

  /// Try to reduce the memory consumption. This function is supposed to be
  /// called after the bitmap has been modified.
  void __forceinline__
  shrink() {
    diff_->shrink();
  }

  //===--------------------------------------------------------------------===//
  // Read related functions.
  //===--------------------------------------------------------------------===//
  /// Returns the value of the bit at the given position.
  u1 __forceinline__
  test(const std::size_t pos) const noexcept {
    return bitmap_->test(pos) ^ diff_->test(pos);
  }

  using skip_iter_type =
      decltype(dtl::bitwise_xor_it(bitmap_->it(), diff_->it()));
  // We always use the skip iterator for the diff, as the diffs are supposed
  // to be small.
  using scan_iter_type =
      decltype(dtl::bitwise_xor_it(bitmap_->scan_it(), diff_->it()));

  /// Returns a 1-run iterator, with efficient skip support.
  skip_iter_type __forceinline__
  it() const noexcept {
    return dtl::bitwise_xor_it(bitmap_->it(), diff_->it());
  }

  /// Returns a 1-run iterator, with WITHOUT efficient skip support.
  scan_iter_type __forceinline__
  scan_it() const noexcept {
    return dtl::bitwise_xor_it(bitmap_->scan_it(), diff_->it());
  }

  /// Returns a pointer to the compressed bitmap.
  B*
  get_bitmap() const noexcept {
    return bitmap_.get();
  }

  /// Returns a pointer to the diff.
  D*
  get_diff() const noexcept {
    return diff_.get();
  }
};
//===----------------------------------------------------------------------===//
} // namespace dtl

ext: hpp

max_stars_repo_name: harald-lang/tree-encoded-bitmaps

max_issues_repo_name: harald-lang/tree-encoded-bitmaps

max_forks_repo_name: harald-lang/tree-encoded-bitmaps


text:
#include <Eigen/Dense>
#include <unsupported/Eigen/MatrixFunctions>
#include <iostream>
#include <vector>
#include <iomanip>

using namespace Eigen;
using namespace std;

// This C++ function phim gives the function phi used for the construction of the exponential Euler single step method for an autonomous ODE.
MatrixXd  phim(MatrixXd Z) {
    int n = Z.cols();
    assert( n == Z.rows() && "Matrix must be square.");
    MatrixXd C(2*n,2*n);
    C << Z, MatrixXd::Identity(n,n), MatrixXd::Zero(n,2*n);
    return C.exp().block(0,n,n,n);
}

// This function calculates a single step of the exponential Euler method, where y0 is the initial state, f and df are object with evaluation operators representing f and df, and h is the stepsize.
template <class Function, class Function2>
VectorXd ExpEulStep(VectorXd y0, Function f, Function2 df, double h) {
   // TODO
}

// Test the exponential Euler method with the logistic ODE and determine the approximated order of algebraic convergence.
int main() {
    // TODO
}

ext: cpp

max_stars_repo_path: Nummerical Methods for CSE/PS13/templates_ps13/ExpEul_template.cpp

max_stars_repo_name: valentinjacot/backupETHZ

max_issues_repo_name: valentinjacot/backupETHZ

max_forks_repo_name: valentinjacot/backupETHZ


text:
#include "delay_supplier.h"

#include <boost/static_assert.hpp>

#ifdef __unix__
#include <unistd.h>
#elif _WIN32
#include <windows.h>
#endif

namespace k52
{
namespace parallel
{
namespace mpi
{

DelaySupplier::DelaySupplier()
{
    initial_delay_ = 1;
    maximum_delay_ = 1000;
    current_delay_ = initial_delay_;
}

void DelaySupplier::SleepWithCurrentDelay()
{
    DelaySupplier::SleepMillisec(current_delay_);
}

void DelaySupplier::IncreaseDelay()
{
    current_delay_ *= 10;

    if(current_delay_ > maximum_delay_)
    {
        current_delay_ = maximum_delay_;
    }
}

void DelaySupplier::ResetDelay()
{
    current_delay_ = initial_delay_;
}

void DelaySupplier::SleepMillisec(int milliseconds)
{
#ifdef __unix__
    usleep(milliseconds * 1000);   // usleep takes sleep time in us
#elif _WIN32
    Sleep(milliseconds);
#else
    BOOST_STATIC_ASSERT_MSG(false, "Current system is not supported in k52::parallel::mpi::DelaySupplier::SleepMillisec");
#endif
}

} /* namespace mpi */
} /* namespace parallel */
} /* namespace k52 */


text:
/*
 * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 <algorithm>

#include <boost/algorithm/string.hpp>

#include "mns_sdk.h"

using namespace std;
using namespace mns_sdk;

namespace mns_sdk {

extern mns_sdk::MnsConfig g_config;

struct ServiceInfo {
  meituan_mns::ProtocolRequest protoreq_;
  vector<SvrListCallback> cb_list_;
  vector<UpdateSvrListCallback> update_cb_list_;
  vector<meituan_mns::SGService> sgservice_;

  boost::unordered_map<string, meituan_mns::SGService>
      map_ipport_sgservice_;

  ServiceInfo() {
  }

  void SetProtocolReq(const string &str_cli_appkey,
                      const string &str_svr_appkey,
                      const string &str_proto_type,
                      const string &str_service_name) {
    protoreq_.__set_localAppkey(str_cli_appkey);
    protoreq_.__set_remoteAppkey(str_svr_appkey);
    protoreq_.__set_protocol(str_proto_type);
    protoreq_.__set_serviceName(str_service_name);
  }

  void AddSvrListCallback(const SvrListCallback &cb) {
    cb_list_.push_back(cb);
  }

  void AddUpdateSvrListCallback(const UpdateSvrListCallback &cb) {
    update_cb_list_.push_back(cb);
  }
};

string g_local_ip_port;

int ref_count_ = 0;

muduo::MutexLock init_mutex;
muduo::net::EventLoop *mns_eventloop_p_ = NULL;

boost::shared_ptr<muduo::net::EventLoopThread> mns_worker_thread_sp_;

typedef muduo::ThreadLocalSingleton <boost::shared_ptr<MnsWorker> >
    ThreadLocalSingletonSGAgentClientSharedPtr;

typedef muduo::ThreadLocalSingleton <boost::unordered_map<string, ServiceInfo> >
    ThreadLocalSingletonMap;

void UptSvrList(const string &, ServiceInfo &);
bool FilterService(const meituan_mns::SGService &sg,
                   const string &service_name);
void GetSvrList(void);
void GetSvrList(const string &str_svr_appkey,
                const string &str_cli_appkey,
                const string &str_proto_type,
                const string &str_service_name,
                vector<meituan_mns::SGService> *res_svr_list,
                muduo::CountDownLatch *p_countdown);
void DoAddUpdateSvrListCallback(const string &str_svr_appkey,
                                const UpdateSvrListCallback &cb,
                                string *p_err_info,
                                muduo::CountDownLatch *countdown_set_callback);
void DoAddSvrListCallback(const string &str_svr_appkey,
                          const SvrListCallback &cb,
                          string *p_err_info,
                          muduo::CountDownLatch *countdown_set_callback);
void InitCthrift(void);
void InitMap(void);
void InitWorkerWithSvrListCB(const string &str_svr_appkey,
                             const string &str_cli_appkey,
                             const string &str_proto_type,
                             const string &str_service_name,
                             const SvrListCallback &cb);
void InitWorkerWithUptSvrListCB(const string &str_svr_appkey,
                                const string &str_cli_appkey,
                                const string &str_proto_type,
                                const string &str_service_name,
                                const UpdateSvrListCallback &cb);
int8_t StartSvr(const meituan_mns::SGService &sgService);

string InitLocalAddr(void);
} // namespace mns_sdk

string mns_sdk::InitLocalAddr(void) {
  string str_sgagent_default_port;
  try {
    str_sgagent_default_port =
        boost::lexical_cast<std::string>(g_config.local_chrion_port_);
  } catch (boost::bad_lexical_cast &e) {
    MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what()
                                              << " port : "
                                              << g_config.local_chrion_port_);
  }

  return g_config.str_local_ip_ + ":" + str_sgagent_default_port;
}

void mns_sdk::UptSvrList(const string &appkey, ServiceInfo &service_info) {
  vector<meituan_mns::SGService>::const_iterator it_vec;
  boost::unordered_map<string, meituan_mns::SGService>::iterator
      it_map_sgservice;

  string str_port;

  vector<meituan_mns::SGService> vec_sgservice_add;
  vector<meituan_mns::SGService> vec_sgservice_del;
  vector<meituan_mns::SGService> vec_sgservice_chg;

  const vector<meituan_mns::SGService> &vec_sgservice = service_info.sgservice_;
  boost::unordered_map<string, meituan_mns::SGService>
      &g_map_ipport_sgservice_ =
      service_info.map_ipport_sgservice_;
  if (MNS_UNLIKELY(
      0 == g_map_ipport_sgservice_.size() && 0 == vec_sgservice.size())) {
    MNS_LOG_WARN("Init svr list but empty srvlist");
  } else if (MNS_UNLIKELY(0 == g_map_ipport_sgservice_.size())) {
    it_vec = vec_sgservice.begin();
    MNS_LOG_INFO("Init svr list for appkey: " << it_vec->appkey);

    while (it_vec != vec_sgservice.end()) {
      if (MNS_UNLIKELY(2 != it_vec->status)) {
        MNS_LOG_DEBUG("svr info: " << MnsSdkCommon::SGService2String(*it_vec)
                                   << " IGNORED");
        ++it_vec;
        continue;
      }

      try {
        str_port = boost::lexical_cast<std::string>(it_vec->port);
      } catch (boost::bad_lexical_cast &e) {
        MNS_LOG_ERROR("boost::bad_lexical_cast :"
                          << e.what() << "svr info : "
                          << MnsSdkCommon::SGService2String(
                                                      *it_vec));
        ++it_vec;
        continue;
      }

      g_map_ipport_sgservice_.insert(make_pair(it_vec->ip + ":" + str_port,
                                               *it_vec));

      vec_sgservice_add.push_back(*(it_vec++));
    }
  } else if (MNS_UNLIKELY(0 == vec_sgservice.size())) {
    MNS_LOG_WARN("vec_sgservice empty");

    it_map_sgservice = g_map_ipport_sgservice_.begin();
    while (it_map_sgservice != g_map_ipport_sgservice_.end()
        && (g_local_ip_port)
            != it_map_sgservice->first) {    //exclude local sgagent since sentinel list NOT include it
      vec_sgservice_del.push_back(it_map_sgservice->second);
      g_map_ipport_sgservice_.erase(it_map_sgservice++);
    }
  } else {
    boost::unordered_map<string, meituan_mns::SGService>
        map_tmp_locate_del(g_map_ipport_sgservice_);

    map_tmp_locate_del.erase(g_local_ip_port); //exclude local sgagent

    it_vec = vec_sgservice.begin();
    while (it_vec != vec_sgservice.end()) {
      if (MNS_UNLIKELY(2 != it_vec->status)) {
        MNS_LOG_DEBUG("svr info: " << MnsSdkCommon::SGService2String(*it_vec)
                                   << " IGNORED");
        ++it_vec;
        continue;
      }

      try {
        str_port = boost::lexical_cast<std::string>(it_vec->port);
      } catch (boost::bad_lexical_cast &e) {

        MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what()
                                                  << "svr info : "
                                                  << MnsSdkCommon::SGService2String(
                                                      *it_vec));

        ++it_vec;
        continue;
      }

      string str_key(it_vec->ip + ":" + str_port);
      it_map_sgservice = g_map_ipport_sgservice_.find(str_key);
      if (g_map_ipport_sgservice_.end() == it_map_sgservice) {
        MNS_LOG_DEBUG("ADD svr list info: "
                          << MnsSdkCommon::SGService2String(*it_vec));

        vec_sgservice_add.push_back(*it_vec);
        g_map_ipport_sgservice_.insert(make_pair(str_key, *it_vec));
      } else {
        map_tmp_locate_del.erase(str_key);

        if (it_map_sgservice->second != *it_vec) {
          MNS_LOG_DEBUG(
              "UPDATE svr list. old info: "
                  << MnsSdkCommon::SGService2String(it_map_sgservice->second)
                  << " new info: "
                  << MnsSdkCommon::SGService2String(*it_vec));

          it_map_sgservice->second = *it_vec;

          vec_sgservice_chg.push_back(*it_vec);

          map_tmp_locate_del.erase(str_key);
        }
      }

      ++it_vec;
    }

    if (map_tmp_locate_del.size()) {
      MNS_LOG_DEBUG("DEL svr list");

      it_map_sgservice = map_tmp_locate_del.begin();
      while (it_map_sgservice != map_tmp_locate_del.end()) {
        MNS_LOG_DEBUG(
            "del svr info: "
                << MnsSdkCommon::SGService2String(it_map_sgservice->second));

        vec_sgservice_del.push_back(it_map_sgservice->second);
        g_map_ipport_sgservice_.erase((it_map_sgservice++)->first);
      }
    }
  }

  if (MNS_UNLIKELY(vec_sgservice_add.size() || vec_sgservice_del.size()
                       || vec_sgservice_chg.size())) {
    for (vector<UpdateSvrListCallback>::const_iterator
             itr = service_info.update_cb_list_.begin();
         service_info.update_cb_list_.end() != itr; ++itr) {
      (*itr)(vec_sgservice_add,
             vec_sgservice_del,
             vec_sgservice_chg,
             appkey);
    }

    for (vector<SvrListCallback>::const_iterator
             itr = service_info.cb_list_.begin();
         service_info.cb_list_.end() != itr; ++itr) {
      (*itr)(vec_sgservice,
             appkey);
    }
  }
}

void mns_sdk::GetSvrList(void) {
  typedef boost::unordered_map<string, ServiceInfo>::iterator MAP_IT;
  meituan_mns::ProtocolResponse rsp;
  rsp.__set_errcode(-1);
  for (MAP_IT iter = (ThreadLocalSingletonMap::instance()).begin();
       iter != (ThreadLocalSingletonMap::instance()).end(); ++iter) {
    MNS_LOG_INFO("appkey: " << iter->first << " Do getsvrlist");
    try {
      (ThreadLocalSingletonSGAgentClientSharedPtr::instance())
          ->GetServiceList(rsp, iter->second.protoreq_);
    } catch (apache::thrift::TException &tx) {
      MNS_LOG_ERROR("appkey: " << iter->first << " service getsvrlist error "
                               << tx.what());
      return;
    }

    if (0 != rsp.errcode) {
      MNS_LOG_ERROR(
          "appkey: " << iter->first << " meituan_mns::ProtocolResponse errcode "
                     << rsp.errcode);
      return;
    }

    //filter service name
    const string &tmp_service = iter->second.protoreq_.serviceName;
    if (!tmp_service.empty()) {
      MNS_LOG_INFO(
          "Get service list with serviceName filter: " << tmp_service);
      rsp.servicelist.erase(remove_if(rsp.servicelist.begin(),
                                      rsp.servicelist.end(),
                                      boost::bind(mns_sdk::FilterService,
                                                  _1,
                                                  tmp_service)),
                            rsp.servicelist.end());
    }
    (iter->second.sgservice_).assign(rsp.servicelist.begin(),
                                     rsp.servicelist.end());

    MNS_LOG_DEBUG("appkey: " << iter->first << " recv vec_sgservice.size "
                             << (iter->second.sgservice_).size());
    for (int i = 0; i < static_cast<int>((iter->second.sgservice_).size());
         i++) {
      MNS_LOG_DEBUG(
          "[" << i << "]" << ": "
              << MnsSdkCommon::SGService2String((iter->second.sgservice_)[i]));
    }

    UptSvrList(iter->first, iter->second);
  }
}

void mns_sdk::GetSvrList(const string &str_svr_appkey,
                         const string &str_cli_appkey,
                         const string &str_proto_type,
                         const string &str_service_name,
                         vector<meituan_mns::SGService> *p_res_svr_list,
                         muduo::CountDownLatch *p_countdown_get_svr_list) {
  meituan_mns::ProtocolRequest protoreq;
  protoreq.__set_localAppkey(str_cli_appkey);
  protoreq.__set_remoteAppkey(str_svr_appkey);
  protoreq.__set_protocol(str_proto_type);
  protoreq.__set_serviceName(str_service_name);

  meituan_mns::ProtocolResponse rsp;
  rsp.__set_errcode(-1);
  try {
    (ThreadLocalSingletonSGAgentClientSharedPtr::instance())
        ->GetServiceList(rsp, protoreq);
  } catch (apache::thrift::TException &tx) {
    MNS_LOG_ERROR("appkey: " << str_svr_appkey << " service getsvrlist error "
                             << tx.what());
    p_countdown_get_svr_list->countDown();
    return;
  }

  if (0 != rsp.errcode) {
    MNS_LOG_ERROR("appkey: " << str_svr_appkey
                             << " meituan_mns::ProtocolResponse errcode "
                             << rsp.errcode);
    p_countdown_get_svr_list->countDown();
    return;
  }

  //filter service name
  if (!str_service_name.empty()) {
    MNS_LOG_INFO(
        "Get service list with serviceName filter: " << str_service_name);
    rsp.servicelist.erase(remove_if(rsp.servicelist.begin(),
                                    rsp.servicelist.end(),
                                    boost::bind(mns_sdk::FilterService,
                                                _1,
                                                str_service_name)),
                          rsp.servicelist.end());
  }
  p_res_svr_list->assign(rsp.servicelist.begin(), rsp.servicelist.end());
  MNS_LOG_DEBUG("appkey: " << str_svr_appkey << " recv vec_sgservice.size "
                           << p_res_svr_list->size());
  p_countdown_get_svr_list->countDown();
  //no need to update status.
}

void mns_sdk::InitMap() {
  MNS_LOG_DEBUG("begin to init global map.");
  ThreadLocalSingletonMap::instance() =
      boost::unordered_map<string, ServiceInfo>();
}

int mns_sdk::InitMNS(const std::string &mns_path, const double &sec, const
double &timeout) {

  if (g_config.LoadConfig(mns_path) != 0) {
    MNS_LOG_DEBUG("load config file failed." << mns_path);
    return -1;
  }

  muduo::MutexLockGuard lock(init_mutex);

  if (NULL == mns_eventloop_p_) {
    mns_worker_thread_sp_ = boost::make_shared<muduo::net::EventLoopThread>(
        muduo::net::EventLoopThread::ThreadInitCallback(),
        "mns_sdk");

    mns_eventloop_p_ = mns_worker_thread_sp_->startLoop();

    mns_eventloop_p_->runInLoop(mns_sdk::InitCthrift);

    mns_eventloop_p_->runInLoop(mns_sdk::InitMap);

    mns_eventloop_p_->runEvery(sec,
                               boost::bind(&GetSvrList));

  }
  ref_count_++;

  return 0;
}

void mns_sdk::InitCthrift(void) {
  MNS_LOG_DEBUG("Init Cthrift & sg_agent client");

  if (!ThreadLocalSingletonSGAgentClientSharedPtr::instance()) {
    ThreadLocalSingletonSGAgentClientSharedPtr::instance() =
        boost::make_shared<MnsWorker>();

    ThreadLocalSingletonSGAgentClientSharedPtr::instance()->Init();
    g_local_ip_port = InitLocalAddr();
  }
}

void mns_sdk::InitWorkerWithSvrListCB(const string &str_svr_appkey,
                                      const string &str_cli_appkey,
                                      const string &str_proto_type,
                                      const string &str_service_name,
                                      const SvrListCallback &cb) {
  ServiceInfo &service_info =
      (ThreadLocalSingletonMap::instance())[str_svr_appkey];
  service_info.SetProtocolReq(str_cli_appkey, str_svr_appkey,
                              str_proto_type, str_service_name);
  service_info.AddSvrListCallback(cb);

  GetSvrList();
}

void mns_sdk::InitWorkerWithUptSvrListCB(const string &str_svr_appkey,
                                         const string &str_cli_appkey,
                                         const string &str_proto_type,
                                         const string &str_service_name,
                                         const UpdateSvrListCallback &cb) {
  ServiceInfo &service_info =
      (ThreadLocalSingletonMap::instance())[str_svr_appkey];
  service_info.SetProtocolReq(str_cli_appkey, str_svr_appkey,
                              str_proto_type, str_service_name);
  service_info.AddUpdateSvrListCallback(cb);

  GetSvrList();
}

int8_t mns_sdk::getSvrList(const string &str_svr_appkey,
                           const string &str_cli_appkey,
                           const string &str_proto_type,
                           const string &str_service_name,
                           vector<meituan_mns::SGService> *p_svr_list) {
  if (str_svr_appkey.empty() || NULL == p_svr_list) {
    MNS_LOG_ERROR(
        "Input server appkey can not empty, and result point of "
            "meituan_mns::SGService list should not NULL");
    return -1;
  }

  if (MNS_LIKELY(mns_eventloop_p_)) {

    muduo::CountDownLatch countdown_get_svr_list(1);
    mns_eventloop_p_->runInLoop(boost::bind(&GetSvrList,
                                            str_svr_appkey,
                                            str_cli_appkey,
                                            str_proto_type,
                                            str_service_name,
                                            p_svr_list,
                                            &countdown_get_svr_list));

    countdown_get_svr_list.wait();
  } else {
    MNS_LOG_ERROR("Please init mns_sdk first");
    return -1;
  }
  return 0;
}

void mns_sdk::DoAddSvrListCallback(const string &str_svr_appkey,
                                   const SvrListCallback &cb,
                                   string *p_err_info,
                                   muduo::CountDownLatch *countdown_set_callback) {
  boost::unordered_map<string, ServiceInfo>
      &map_serviceInfo = ThreadLocalSingletonMap::instance();
  if (map_serviceInfo.end() == map_serviceInfo.find(str_svr_appkey)) {
    p_err_info->assign("Has not set protocol type for " + str_svr_appkey
                           + ". Please use StartClient set first.");
    MNS_LOG_DEBUG(*p_err_info);
    countdown_set_callback->countDown();
    return;
  }
  map_serviceInfo[str_svr_appkey].AddSvrListCallback(cb);
  countdown_set_callback->countDown();
}

int8_t mns_sdk::AddSvrListCallback(const string &str_svr_appkey,
                                   const SvrListCallback &cb,
                                   string *p_err_info) {
  bool appkey_empty = str_svr_appkey.empty();
  bool cb_empty = cb.empty();
  bool p_err_info_null = (NULL == p_err_info);
  if (MNS_UNLIKELY(appkey_empty || cb_empty || p_err_info_null)) {
    string str_err_info("input appkey empty " + (appkey_empty ? string("true;")
                                                              : string("false;"))
                            +
                                " input callback func empty "
                            + (cb_empty ? string("true;") : string("false;")) +
        " input err info pointer null "
                            + (p_err_info_null ? string("true.") : string(
                                "false.")));
    MNS_LOG_ERROR(str_err_info);
    if (p_err_info) {
      p_err_info->assign(str_err_info);
    }
    return -1;
  }
  if (MNS_LIKELY(mns_eventloop_p_)) {
    muduo::CountDownLatch countdown_set_callback(1);
    mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::DoAddSvrListCallback,
                                            str_svr_appkey,
                                            cb,
                                            p_err_info,
                                            &countdown_set_callback));
    countdown_set_callback.wait();
  } else {
    MNS_LOG_ERROR("Please init mns_sdk first");
    return -1;
  }
  return p_err_info->empty() ? 0 : -1;
}

void mns_sdk::DoAddUpdateSvrListCallback(const string &str_svr_appkey,
                                         const UpdateSvrListCallback &cb,
                                         string *p_err_info,
                                         muduo::CountDownLatch *countdown_set_callback) {
  boost::unordered_map<string, ServiceInfo>
      &map_serviceInfo = ThreadLocalSingletonMap::instance();
  if (map_serviceInfo.end() == map_serviceInfo.find(str_svr_appkey)) {
    p_err_info->assign("Has not set protocol type for " + str_svr_appkey
                           + ". Please use StartClient set first.");
    MNS_LOG_DEBUG(*p_err_info);
    countdown_set_callback->countDown();
    return;
  }
  map_serviceInfo[str_svr_appkey].AddUpdateSvrListCallback(cb);
  countdown_set_callback->countDown();
}

int8_t mns_sdk::AddUpdateSvrListCallback(const string &str_svr_appkey,
                                         const UpdateSvrListCallback &cb,
                                         string *p_err_info) {
  bool appkey_empty = str_svr_appkey.empty();
  bool cb_empty = cb.empty();
  bool p_err_info_null = (NULL == p_err_info);
  if (MNS_UNLIKELY(appkey_empty || cb_empty || p_err_info_null)) {
    string str_err_info("input appkey empty " + (appkey_empty ? string("true;")
                                                              : string("false;"))
                            +
                                " input callback func empty "
                            + (cb_empty ? string("true;") : string("false;")) +
        " input err info pointer null "
                            + (p_err_info_null ? string("true.") : string(
                                "false.")));
    MNS_LOG_ERROR(str_err_info);
    if (p_err_info) {
      p_err_info->assign(str_err_info);
    }
    return -1;
  }
  if (MNS_LIKELY(mns_eventloop_p_)) {
    muduo::CountDownLatch countdown_set_callback(1);
    mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::DoAddUpdateSvrListCallback,
                                            str_svr_appkey,
                                            cb,
                                            p_err_info,
                                            &countdown_set_callback));
    countdown_set_callback.wait();
  } else {
    MNS_LOG_ERROR("Please init mns_sdk first");
  }
  return p_err_info->empty() ? 0 : -1;
}

int8_t mns_sdk::StartClient(const string &str_svr_appkey,
                            const string &str_cli_appkey,
                            const string &str_proto_type,
                            const string &str_service_name,
                            const SvrListCallback &cb) {
  if (str_svr_appkey.empty() || str_cli_appkey.empty()) {
    MNS_LOG_ERROR("Input appkeys should not empty");
    return -1;
  }
  MNS_LOG_DEBUG("str_svr_appkey " << str_svr_appkey << " str_client_appkey "
                                  << str_cli_appkey << " str_proto_type "
                                  << str_proto_type << " "
                                      "str_service_name " << str_service_name);

  if (MNS_LIKELY(mns_eventloop_p_)) {

    mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::InitWorkerWithSvrListCB,
                                            str_svr_appkey,
                                            str_cli_appkey,
                                            str_proto_type,
                                            str_service_name,
                                            cb));
  } else {
    MNS_LOG_ERROR("Please init mns_sdk first");
    return -1;
  }

  return 0;
}

int8_t mns_sdk::StartClient(const string &str_svr_appkey,
                            const string &str_cli_appkey,
                            const string &str_proto_type,
                            const string &str_service_name,
                            const UpdateSvrListCallback &cb) {
  if (str_svr_appkey.empty() || str_cli_appkey.empty()) {
    MNS_LOG_ERROR("Input appkeys should not empty");
    return -1;
  }
  MNS_LOG_DEBUG("str_svr_appkey " << str_svr_appkey << " str_client_appkey "
                                  << str_cli_appkey << " str_proto_type "
                                  << str_proto_type << " "
                                      "str_service_name " << str_service_name);

  if (MNS_LIKELY(mns_eventloop_p_)) {
    mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::InitWorkerWithUptSvrListCB,
                                            str_svr_appkey,
                                            str_cli_appkey,
                                            str_proto_type,
                                            str_service_name,
                                            cb));
  } else {
    MNS_LOG_ERROR("Please  mns_sdk first");
  }

  return 0;
}

int8_t mns_sdk::StartSvr(const string &str_appkey,
                         const vector<string> &service_list,
                         const int16_t &i16_port,
                         const int32_t &i32_svr_type,
                         const string &str_proto_type,
                         const bool &b_is_uniform) {
  meituan_mns::SGService sgService;
  sgService.appkey.assign(str_appkey);
  sgService.version.assign("mns_sdk-1.3.0");
  sgService.ip.assign(g_config.str_local_ip_);
  sgService.port = i16_port;
  sgService.weight = 10;
  //状态从2-->0，对齐scanner状态图
  sgService.status = 2;
  sgService.lastUpdateTime = static_cast<int32_t>(time(0));
  sgService.fweight = 10.0;
  sgService.serverType = i32_svr_type;
  if (!service_list.empty()) {
    meituan_mns::ServiceDetail detail;
    detail.__set_unifiedProto(b_is_uniform);
    map<string, meituan_mns::ServiceDetail> serviceInfo;

    for (vector<string>::const_iterator iter = service_list.begin();
         iter != service_list.end(); ++iter) {
      serviceInfo.insert(make_pair(*iter, detail));
    }
    sgService.__set_serviceInfo(serviceInfo);
  }

  string tmp;

  switch (i32_svr_type) {
    case 0:sgService.protocol.assign("thrift");
      break;
    case 1:sgService.protocol.assign("http");
      break;
    case 2:tmp.assign(str_proto_type);
      transform(tmp.begin(),
                tmp.end(),
                tmp.begin(),
                ::tolower);
      if ("thrift" == tmp || "http" == tmp) {
        MNS_LOG_ERROR("sgService.serverType 2 but"
                          " str_proto_type " << str_proto_type);
        return -1;
      }

      sgService.protocol.assign(str_proto_type);
      break;
    default: MNS_LOG_ERROR(
        "unkown sgService.serverType " << sgService.serverType);
      return -1;
  }

  MNS_LOG_DEBUG(
      "create sgservice " << MnsSdkCommon::SGService2String(sgService));

  return StartSvr(sgService);
}

int8_t mns_sdk::StartSvr(const string &str_appkey,
                         const int16_t &i16_port,
                         const int32_t &i32_svr_type,
                         const string &str_proto_type) {
  vector<string> service_list;
  return StartSvr(str_appkey,
                  service_list,
                  i16_port,
                  i32_svr_type,
                  str_proto_type);
}

int8_t mns_sdk::StartSvr(const meituan_mns::SGService &sgService) {
  InitCthrift();

  try {
    int32_t i32_ret =
        (ThreadLocalSingletonSGAgentClientSharedPtr::instance())->RegistService(
            sgService);
    if (MNS_UNLIKELY(i32_ret)) {
      MNS_LOG_ERROR("registService failed: " << i32_ret);
      return -1;
    } else {
      MNS_LOG_INFO("reg svr done");
    }
  } catch (apache::thrift::TException &tx) {
    MNS_LOG_ERROR("registService failed: " << tx.what());
    return -1;
  }

  return 0;
}

void mns_sdk::DestroyMNS(void) {
  //仿造智能指针，使用引用计数管理资源释放。
  muduo::MutexLockGuard lock(init_mutex);
  if (0 == (--ref_count_) && mns_eventloop_p_) {
    mns_eventloop_p_->quit();
    usleep(500 * 1000);
    mns_eventloop_p_ = NULL;
  }
}

bool mns_sdk::FilterService(const meituan_mns::SGService &sg,
                            const string &service_name) {
  return sg.serviceInfo.find(service_name) == sg.serviceInfo.end();
}

ext: cc

max_stars_repo_name: wuxianxingkong/octo-ns

max_issues_repo_name: wuxianxingkong/octo-ns

max_forks_repo_name: wuxianxingkong/octo-ns


text:
#include <ctanker.h>

#include <Tanker/AsyncCore.hpp>
#include <Tanker/Crypto/Crypto.hpp>
#include <Tanker/Errors/AssertionError.hpp>
#include <Tanker/Errors/Errc.hpp>
#include <Tanker/Errors/Exception.hpp>

#include <Tanker/Init.hpp>
#include <Tanker/Trustchain/TrustchainId.hpp>
#include <Tanker/Verification/Methods.hpp>

#include <boost/algorithm/hex.hpp>
#include <mgs/base64.hpp>
#include <tconcurrent/async.hpp>
#include <tconcurrent/thread_pool.hpp>

#include <ctanker/async/private/CFuture.hpp>
#include <ctanker/private/Utils.hpp>

#include "CNetwork.hpp"

#include <string>
#include <utility>

using namespace Tanker;
using namespace Tanker::Errors;

namespace
{
template <typename T>
std::optional<T> nullableToOpt(char const* str)
{
  if (str && *str)
    return T(str);
  else
    return std::nullopt;
}

Verification::Verification cverificationToVerification(
    tanker_verification_t const* cverification)
{
  if (!cverification)
  {
    throw formatEx(
        Errc::InvalidArgument,
        "no verification method specified in the tanker_verification_t struct");
  }
  if (cverification->version != 4)
  {
    throw formatEx(Errc::InvalidArgument,
                   "unsupported tanker_verification_t struct version: {}",
                   cverification->version);
  }

  Verification::Verification verification;
  switch (cverification->verification_method_type)
  {
  case TANKER_VERIFICATION_METHOD_EMAIL: {
    if (!cverification->email_verification.email ||
        !cverification->email_verification.verification_code)
      throw formatEx(Errc::InvalidArgument, "null field in email verification");
    verification = Verification::ByEmail{
        Email{cverification->email_verification.email},
        VerificationCode{cverification->email_verification.verification_code}};
    break;
  }
  case TANKER_VERIFICATION_METHOD_PASSPHRASE: {
    if (!cverification->passphrase)
      throw formatEx(Errc::InvalidArgument, "passphrase field is null");
    verification = Passphrase{cverification->passphrase};
    break;
  }
  case TANKER_VERIFICATION_METHOD_VERIFICATION_KEY: {
    if (!cverification->verification_key)
      throw formatEx(Errc::InvalidArgument, "verification key is null");
    verification = VerificationKey{cverification->verification_key};
    break;
  }
  case TANKER_VERIFICATION_METHOD_OIDC_ID_TOKEN: {
    if (!cverification->oidc_id_token)
      throw formatEx(Errc::InvalidArgument, "oidc id token field is null");
    verification = OidcIdToken{cverification->oidc_id_token};
    break;
  }
  case TANKER_VERIFICATION_METHOD_PHONE_NUMBER: {
    if (!cverification->phone_number_verification.phone_number ||
        !cverification->phone_number_verification.verification_code)
      throw formatEx(Errc::InvalidArgument,
                     "null field in phone number verification");
    verification = Verification::ByPhoneNumber{
        PhoneNumber{cverification->phone_number_verification.phone_number},
        VerificationCode{
            cverification->phone_number_verification.verification_code}};
    break;
  }
  default:
    throw formatEx(Errc::InvalidArgument, "unknown verification type");
  }
  return verification;
}

void cVerificationMethodFromVerificationMethod(
    tanker_verification_method_t& c_verif_method,
    Verification::VerificationMethod const& method)
{
  c_verif_method.version = 1;
  c_verif_method.value = nullptr;
  if (method.holds_alternative<Passphrase>())
    c_verif_method.verification_method_type =
        static_cast<uint8_t>(TANKER_VERIFICATION_METHOD_PASSPHRASE);
  else if (method.holds_alternative<OidcIdToken>())
    c_verif_method.verification_method_type =
        static_cast<uint8_t>(TANKER_VERIFICATION_METHOD_OIDC_ID_TOKEN);
  else if (method.holds_alternative<VerificationKey>())
    c_verif_method.verification_method_type =
        static_cast<uint8_t>(TANKER_VERIFICATION_METHOD_VERIFICATION_KEY);
  else if (auto const email = method.get_if<Email>())
  {
    c_verif_method.verification_method_type =
        static_cast<uint8_t>(TANKER_VERIFICATION_METHOD_EMAIL);
    c_verif_method.value = duplicateString(email->c_str());
  }
  else if (auto const phoneNumber = method.get_if<PhoneNumber>())
  {
    c_verif_method.verification_method_type =
        static_cast<uint8_t>(TANKER_VERIFICATION_METHOD_PHONE_NUMBER);
    c_verif_method.value = duplicateString(phoneNumber->c_str());
  }
  else
    throw AssertionError("unknown verification type");
}

Tanker::Core::VerifyWithToken withTokenFromVerifOptions(
    tanker_verification_options_t const* cverif_opts)
{
  using VerifyWithToken = Tanker::Core::VerifyWithToken;

  if (!cverif_opts)
    return VerifyWithToken::No;
  if (cverif_opts->version != 1)
    throw Exception(
        make_error_code(Errc::InvalidArgument),
        fmt::format("options version should be {:d} instead of {:d}",
                    1,
                    cverif_opts->version));

  bool withToken = cverif_opts->with_session_token;
  return withToken ? VerifyWithToken::Yes : VerifyWithToken::No;
}

#define STATIC_ENUM_CHECK(cval, cppval)           \
  static_assert(cval == static_cast<int>(cppval), \
                "enum values not in sync: " #cval " and " #cppval)

// Unlock

STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_EMAIL,
                  Verification::Method::Email);
STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_PASSPHRASE,
                  Verification::Method::Passphrase);
STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_VERIFICATION_KEY,
                  Verification::Method::VerificationKey);
STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_OIDC_ID_TOKEN,
                  Verification::Method::OidcIdToken);
STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_PHONE_NUMBER,
                  Verification::Method::PhoneNumber);
STATIC_ENUM_CHECK(TANKER_VERIFICATION_METHOD_LAST, Verification::Method::Last);

static_assert(TANKER_VERIFICATION_METHOD_LAST == 6,
              "Please update the assertions above if you added a new "
              "unlock method");

// Status

STATIC_ENUM_CHECK(TANKER_STATUS_STOPPED, Status::Stopped);
STATIC_ENUM_CHECK(TANKER_STATUS_READY, Status::Ready);
STATIC_ENUM_CHECK(TANKER_STATUS_IDENTITY_REGISTRATION_NEEDED,
                  Status::IdentityRegistrationNeeded);
STATIC_ENUM_CHECK(TANKER_STATUS_IDENTITY_VERIFICATION_NEEDED,
                  Status::IdentityVerificationNeeded);

STATIC_ENUM_CHECK(TANKER_STATUS_LAST, Status::Last);

static_assert(
    TANKER_STATUS_LAST == 4,
    "Please update the status assertions above if you added a new status");

#undef STATIC_ENUM_CHECK
}

char const* tanker_version_string(void)
{
  return AsyncCore::version().c_str();
}

void tanker_init()
{
  Tanker::init();
}

tanker_future_t* tanker_create(const tanker_options_t* options)
{
  return makeFuture(tc::sync([&] {
    if (options == nullptr)
    {
      throw Exception(make_error_code(Errc::InvalidArgument),
                      "options is null");
    }
    if (options->version != 2 && options->version != 3)
    {
      throw Exception(
          make_error_code(Errc::InvalidArgument),
          fmt::format("options version should be {:d} instead of {:d}",
                      3,
                      options->version));
    }
    if (options->app_id == nullptr)
    {
      throw Exception(make_error_code(Errc::InvalidArgument), "app_id is null");
    }
    if (options->sdk_type == nullptr)
    {
      throw Exception(make_error_code(Errc::InvalidArgument),
                      "sdk_type is null");
    }
    if (options->sdk_version == nullptr)
    {
      throw Exception(make_error_code(Errc::InvalidArgument),
                      "sdk_version is null");
    }

    char const* url = options->url;
    if (url == nullptr)
      url = "https://api.tanker.io";

    if (options->writable_path == nullptr)
    {
      throw Exception(make_error_code(Errc::InvalidArgument),
                      "writable_path is null");
    }

    std::unique_ptr<Tanker::Network::Backend> backend;
    if (options->version == 3 && options->http_send_request &&
        options->http_cancel_request)
    {
      backend = std::make_unique<CTankerBackend>(options->http_send_request,
                                                 options->http_cancel_request,
                                                 options->http_data);
    }

    try
    {
      auto const trustchainId = mgs::base64::decode<Trustchain::TrustchainId>(
          std::string(options->app_id));

      return static_cast<void*>(
          new AsyncCore(url,
                        {options->sdk_type, trustchainId, options->sdk_version},
                        options->writable_path,
                        std::move(backend)));
    }
    catch (mgs::exceptions::exception const&)
    {
      throw Exception(make_error_code(Errc::InvalidArgument),
                      "app_id is invalid");
    }
  }));
}

tanker_future_t* tanker_destroy(tanker_t* ctanker)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->destroy());
}

void tanker_set_log_handler(tanker_log_handler_t handler)
{
  AsyncCore::setLogHandler([handler](Tanker::Log::Record const& record) {
    tanker_log_record_t crecord = {
        record.category,
        static_cast<std::uint32_t>(record.level),
        record.file,
        record.line,
        record.message,
    };
    handler(&crecord);
  });
}

tanker_expected_t* tanker_event_connect(tanker_t* ctanker,
                                        enum tanker_event event,
                                        tanker_event_callback_t cb,
                                        void* data)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tc::sync([&] {
    switch (event)
    {
    case TANKER_EVENT_SESSION_CLOSED:
      return tanker->connectSessionClosed(
          [=, cb = std::move(cb)] { cb(nullptr, data); });
    case TANKER_EVENT_DEVICE_REVOKED:
      return tanker->connectDeviceRevoked(
          [=, cb = std::move(cb)] { cb(nullptr, data); });
    default:
      throw formatEx(Errc::InvalidArgument,
                     FMT_STRING("unknown event: {:d}"),
                     static_cast<int>(event));
    }
  }));
}

tanker_expected_t* tanker_event_disconnect(tanker_t* ctanker,
                                           enum tanker_event event)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tc::sync([&] {
    switch (event)
    {
    case TANKER_EVENT_SESSION_CLOSED:
      tanker->disconnectSessionClosed();
      break;
    case TANKER_EVENT_DEVICE_REVOKED:
      tanker->disconnectDeviceRevoked();
      break;
    default:
      throw formatEx(Errc::InvalidArgument,
                     FMT_STRING("unknown event: {:d}"),
                     static_cast<int>(event));
    }
  }));
}

tanker_future_t* tanker_start(tanker_t* ctanker, char const* identity)
{
  if (identity == nullptr)
    return makeFuture(tc::make_exceptional_future<void>(
        Exception(make_error_code(Errc::InvalidArgument), "identity is null")));

  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(
      tanker->start(std::string(identity))
          .and_then(tc::get_synchronous_executor(), [](auto status) {
            return reinterpret_cast<void*>(status);
          }));
}

tanker_future_t* tanker_register_identity(
    tanker_t* ctanker,
    tanker_verification_t const* cverification,
    tanker_verification_options_t const* cverif_opts)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  auto withToken = withTokenFromVerifOptions(cverif_opts);
  auto const verification = cverificationToVerification(cverification);
  return makeFuture(
      tanker->registerIdentity(verification, withToken)
          .and_then(tc::get_synchronous_executor(), [](auto const& token) {
            if (!token.has_value())
              return static_cast<void*>(nullptr);
            return static_cast<void*>(duplicateString(*token));
          }));
}

tanker_future_t* tanker_verify_identity(
    tanker_t* ctanker,
    tanker_verification_t const* cverification,
    tanker_verification_options_t const* cverif_opts)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  auto withToken = withTokenFromVerifOptions(cverif_opts);
  auto const verification = cverificationToVerification(cverification);
  return makeFuture(
      tanker->verifyIdentity(verification, withToken)
          .and_then(tc::get_synchronous_executor(), [](auto const& token) {
            if (!token.has_value())
              return static_cast<void*>(nullptr);
            return static_cast<void*>(duplicateString(*token));
          }));
}

tanker_future_t* tanker_stop(tanker_t* ctanker)
{
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->stop());
}

enum tanker_status tanker_status(tanker_t* ctanker)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return static_cast<enum tanker_status>(tanker->status());
}

tanker_future_t* tanker_device_id(tanker_t* ctanker)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->deviceId().and_then(
      tc::get_synchronous_executor(), [](auto const& deviceId) {
        return static_cast<void*>(duplicateString(deviceId.string()));
      }));
}

tanker_future_t* tanker_get_device_list(tanker_t* ctanker)
{
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->getDeviceList().and_then(
      tc::get_synchronous_executor(),
      [](std::vector<Users::Device> const& deviceList) {
        auto* cDeviceList = new tanker_device_list_t;
        cDeviceList->count = deviceList.size();
        cDeviceList->devices = new tanker_device_list_elem_t[deviceList.size()];
        tanker_device_list_elem_t* cDevice = cDeviceList->devices;
        for (auto const& device : deviceList)
        {
          cDevice->device_id =
              duplicateString(mgs::base64::encode(device.id()));
          cDevice->is_revoked = device.isRevoked();
          cDevice++;
        }
        return reinterpret_cast<void*>(cDeviceList);
      }));
}

tanker_future_t* tanker_generate_verification_key(tanker_t* ctanker)
{
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->generateVerificationKey().and_then(
      tc::get_synchronous_executor(), [](auto uk) {
        return static_cast<void*>(duplicateString(uk.string()));
      }));
}

tanker_future_t* tanker_set_verification_method(
    tanker_t* ctanker,
    tanker_verification_t const* cverification,
    tanker_verification_options_t const* cverif_opts)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  auto withToken = withTokenFromVerifOptions(cverif_opts);
  auto const verification = cverificationToVerification(cverification);
  return makeFuture(
      tanker->setVerificationMethod(verification, withToken)
          .and_then(tc::get_synchronous_executor(), [](auto const& token) {
            if (!token.has_value())
              return static_cast<void*>(nullptr);
            return static_cast<void*>(duplicateString(*token));
          }));
}

tanker_future_t* tanker_get_verification_methods(tanker_t* ctanker)
{
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->getVerificationMethods().and_then(
      tc::get_synchronous_executor(),
      [](std::vector<Verification::VerificationMethod> methods) {
        auto verifMethods = new tanker_verification_method_t[methods.size()];
        for (size_t i = 0; i < methods.size(); ++i)
        {
          cVerificationMethodFromVerificationMethod(verifMethods[i],
                                                    methods[i]);
        }
        auto verifMethodList = new tanker_verification_method_list;
        verifMethodList->count = methods.size();
        verifMethodList->methods = verifMethods;
        return reinterpret_cast<void*>(verifMethodList);
      }));
}

uint64_t tanker_encrypted_size(uint64_t clear_size)
{
  return AsyncCore::encryptedSize(clear_size);
}

tanker_expected_t* tanker_decrypted_size(uint8_t const* encrypted_data,
                                         uint64_t encrypted_size)
{
  return makeFuture(
      AsyncCore::decryptedSize(gsl::make_span(encrypted_data, encrypted_size))
          .and_then(tc::get_synchronous_executor(),
                    [](auto size) { return reinterpret_cast<void*>(size); }));
}

tanker_expected_t* tanker_get_resource_id(uint8_t const* encrypted_data,
                                          uint64_t encrypted_size)
{
  return makeFuture(
      AsyncCore::getResourceId(
          gsl::make_span(static_cast<uint8_t const*>(encrypted_data),
                         encrypted_size))
          .and_then(tc::get_synchronous_executor(), [](auto resId) {
            return static_cast<void*>(duplicateString(resId.string()));
          }));
}

tanker_future_t* tanker_encrypt(tanker_t* ctanker,
                                uint8_t* encrypted_data,
                                uint8_t const* data,
                                uint64_t data_size,
                                tanker_encrypt_options_t const* options)
{
  std::vector<SPublicIdentity> spublicIdentities{};
  std::vector<SGroupId> sgroupIds{};
  bool shareWithSelf = true;
  if (options)
  {
    if (options->version != 3)
    {
      return makeFuture(tc::make_exceptional_future<void>(
          formatEx(Errc::InvalidArgument,
                   "unsupported tanker_encrypt_options struct version")));
    }
    spublicIdentities = to_vector<SPublicIdentity>(options->share_with_users,
                                                   options->nb_users);
    sgroupIds =
        to_vector<SGroupId>(options->share_with_groups, options->nb_groups);
    shareWithSelf = options->share_with_self;
  }
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->encrypt(encrypted_data,
                                    gsl::make_span(data, data_size),
                                    spublicIdentities,
                                    sgroupIds,
                                    Core::ShareWithSelf{shareWithSelf}));
}

tanker_future_t* tanker_decrypt(tanker_t* ctanker,
                                uint8_t* decrypted_data,
                                uint8_t const* data,
                                uint64_t data_size)
{
  auto tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(
      tanker->decrypt(decrypted_data, gsl::make_span(data, data_size)));
}

tanker_future_t* tanker_share(tanker_t* ctanker,
                              char const* const* resource_ids,
                              uint64_t nb_resource_ids,
                              tanker_sharing_options_t const* options)
{
  if (!options)
  {
    return makeFuture(tc::make_exceptional_future<void>(formatEx(
        Errc::InvalidArgument, "tanker_sharing_options must not be NULL")));
  }

  if (options->version != 1)
  {
    return makeFuture(tc::make_exceptional_future<void>(
        formatEx(Errc::InvalidArgument,
                 "unsupported tanker_sharing_options struct version")));
  }

  auto const spublicIdentities =
      to_vector<SPublicIdentity>(options->share_with_users, options->nb_users);
  auto const sgroupIds =
      to_vector<SGroupId>(options->share_with_groups, options->nb_groups);
  auto const resources = to_vector<SResourceId>(resource_ids, nb_resource_ids);
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);

  return makeFuture(tanker->share(resources, spublicIdentities, sgroupIds));
}

tanker_future_t* tanker_attach_provisional_identity(
    tanker_t* ctanker, char const* provisional_identity)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(
      tanker
          ->attachProvisionalIdentity(
              SSecretProvisionalIdentity{provisional_identity})
          .and_then(tc::get_synchronous_executor(),
                    [](AttachResult const& attachResult) {
                      auto cAttachResult = new tanker_attach_result_t;
                      cAttachResult->version = 1;
                      cAttachResult->method = nullptr;
                      cAttachResult->status =
                          static_cast<uint8_t>(attachResult.status);
                      if (attachResult.verificationMethod.has_value())
                      {
                        tanker_verification_method cMethod;
                        cVerificationMethodFromVerificationMethod(
                            cMethod, *attachResult.verificationMethod);
                        cAttachResult->method =
                            new tanker_verification_method(cMethod);
                      }
                      return reinterpret_cast<void*>(cAttachResult);
                    }));
}

tanker_future_t* tanker_verify_provisional_identity(
    tanker_t* ctanker, tanker_verification_t const* cverification)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tc::sync([&] {
                      auto const verification =
                          cverificationToVerification(cverification);
                      return tanker->verifyProvisionalIdentity(verification);
                    }).unwrap());
}

tanker_future_t* tanker_revoke_device(tanker_t* ctanker, char const* device_id)
{
  auto const tanker = reinterpret_cast<AsyncCore*>(ctanker);
  return makeFuture(tanker->revokeDevice(SDeviceId(device_id)));
}

void tanker_free_buffer(void const* buffer)
{
  free(const_cast<void*>(buffer));
}

void tanker_free_device_list(tanker_device_list_t* list)
{
  for (size_t i = 0; i < list->count; ++i)
    free(const_cast<char*>(list->devices[i].device_id));
  delete[] list->devices;
  delete list;
}

void tanker_free_verification_method_list(
    tanker_verification_method_list_t* methodList)
{
  for (size_t i = 0; i < methodList->count; ++i)
  {
    if (methodList->methods[i].verification_method_type ==
            TANKER_VERIFICATION_METHOD_EMAIL ||
        methodList->methods[i].verification_method_type ==
            TANKER_VERIFICATION_METHOD_PHONE_NUMBER)
      free(const_cast<char*>(methodList->methods[i].value));
  }
  delete[] methodList->methods;
  delete methodList;
}

void tanker_free_attach_result(tanker_attach_result_t* result)
{
  if (result->method)
  {
    if (result->method->verification_method_type ==
            TANKER_VERIFICATION_METHOD_EMAIL ||
        result->method->verification_method_type ==
            TANKER_VERIFICATION_METHOD_PHONE_NUMBER)
      free(const_cast<char*>(result->method->value));
    delete result->method;
  }
  delete result;
}

tanker_expected_t* tanker_prehash_password(char const* password)
{
  return makeFuture(tc::sync([&] {
    if (!password)
      throw formatEx(Errc::InvalidArgument, "password is null");
    return static_cast<void*>(duplicateString(
        mgs::base64::encode(Crypto::prehashPassword(password))));
  }));
}

max_stars_repo_name: TankerHQ/sdk-native

max_issues_repo_name: TankerHQ/sdk-native

max_forks_repo_name: TankerHQ/sdk-native


text:
//
// Licensed to Green Energy Corp (www.greenenergycorp.com) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Green Enery Corp licenses this file
// to you 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 <boost/test/unit_test.hpp>
#include <opendnp3/APL/test/util/TestHelpers.h>

#include <opendnp3/APL/TimerSourceASIO.h>
#include <opendnp3/APL/Threadable.h>
#include <opendnp3/APL/Thread.h>
#include <opendnp3/APL/Exception.h>

#include <map>
#include <boost/bind.hpp>
#include <boost/asio.hpp>

using namespace std;
using namespace apl;

class MockTimerHandler
{
public:
	MockTimerHandler() : mCount(0)
	{}

	void OnExpiration() {
		++mCount;
	}
	size_t GetCount() {
		return mCount;
	}

private:
	size_t mCount;
};

class MonotonicReceiver : private Threadable
{
public:
	MonotonicReceiver(boost::asio::io_service* apSrv, TimerSourceASIO* apTimerSrc) :
		mLast(-1),
		mNum(0),
		mMonotonic(true),
		mpSrv(apSrv),
		mpTimerSrc(apTimerSrc),
		mpInfinite(apTimerSrc->StartInfinite()),
		mThread(this) {
		mThread.Start();
	}

	~MonotonicReceiver() {
		mpInfinite->Cancel();
	}

	void Receive(int aVal) {
		if(aVal <= mLast) mMonotonic = false;
		++mNum;
		mLast = aVal;
	}

	bool IsMonotonic() {
		return mMonotonic;
	}

	int Num() {
		return mNum;
	}

private:

	int mLast;
	int mNum;
	bool mMonotonic;

	boost::asio::io_service* mpSrv;
	TimerSourceASIO* mpTimerSrc;
	ITimer* mpInfinite;

	void Run() {
		mpSrv->run();
	}

	Thread mThread;
};

BOOST_AUTO_TEST_SUITE(Timers)

void ThrowInvalidStateException()
{
	throw InvalidStateException(LOCATION, "some bad state");
}

BOOST_AUTO_TEST_CASE(SyncRethrowsExceptions)
{
	boost::asio::io_service srv;
	TimerSourceASIO ts(&srv);
	MonotonicReceiver rcv(&srv, &ts);

	BOOST_REQUIRE_THROW(ts.PostSync(boost::bind(&ThrowInvalidStateException)), Exception);

}

BOOST_AUTO_TEST_CASE(TestOrderedDispatch)
{
	const int NUM = 10000;

	boost::asio::io_service srv;
	TimerSourceASIO ts(&srv);
	MonotonicReceiver rcv(&srv, &ts);

	for(int i = 0; i < NUM; ++i) {
		ts.Post(boost::bind(&MonotonicReceiver::Receive, &rcv, i));
	}

	ts.Sync();

	BOOST_REQUIRE_EQUAL(NUM, rcv.Num());
	BOOST_REQUIRE(rcv.IsMonotonic());
}

BOOST_AUTO_TEST_CASE(ExpirationAndReuse)
{
	MockTimerHandler mth;
	boost::asio::io_service srv;
	TimerSourceASIO ts(&srv);
	ITimer* pT1 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth));
	BOOST_REQUIRE_EQUAL(srv.run_one(), 1);
	BOOST_REQUIRE_EQUAL(1, mth.GetCount());
	ITimer* pT2 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth));
	BOOST_REQUIRE_EQUAL(pT1, pT2); //The ASIO implementation should reuse timers
}

BOOST_AUTO_TEST_CASE(Cancelation)
{
	MockTimerHandler mth;
	boost::asio::io_service srv;
	TimerSourceASIO ts(&srv);
	ITimer* pT1 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth));
	pT1->Cancel();
	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(0, mth.GetCount());
	ITimer* pT2 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth));
	BOOST_REQUIRE_EQUAL(pT1, pT2);
}

BOOST_AUTO_TEST_CASE(MultipleOutstanding)
{
	MockTimerHandler mth1;
	MockTimerHandler mth2;
	boost::asio::io_service srv;
	TimerSourceASIO ts(&srv);
	ITimer* pT1 = ts.Start(0, boost::bind(&MockTimerHandler::OnExpiration, &mth1));
	ITimer* pT2 = ts.Start(100, boost::bind(&MockTimerHandler::OnExpiration, &mth2));

	BOOST_REQUIRE_NOT_EQUAL(pT1, pT2);

	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(1, mth1.GetCount());
	BOOST_REQUIRE_EQUAL(0, mth2.GetCount());

	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(1, mth1.GetCount());
	BOOST_REQUIRE_EQUAL(1, mth2.GetCount());
}

BOOST_AUTO_TEST_SUITE_END()


text:
//==============================================================================
//         Copyright 2009 - 2014 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//         Copyright 2012 - 2014 NumScale SAS
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_SDK_BENCH_PROTOCOL_HPP_INCLUDED
#define NT2_SDK_BENCH_PROTOCOL_HPP_INCLUDED

#include <nt2/sdk/bench/details/display_metric.hpp>
#include <nt2/sdk/bench/details/measure.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/vector.hpp>

namespace nt2 { namespace details
{
  template<class Experiment, class Enable = void>
  struct experiment_copy
  {
    typedef Experiment type;
  };

  template<class Experiment>
  struct experiment_copy<Experiment, typename Experiment::experiment_is_immutable>
  {
    typedef Experiment& type;
  };
} }

namespace nt2 { namespace bench
{
  /*!

  **/
  template<typename... Metrics>
  struct protocol
  {
    typedef boost::fusion::vector<Metrics...> metrics_type;

    protocol() {}
    protocol(Metrics const&... m) : metrics_(m...) {}

    template<typename Experiment>
    inline time_quantum_t run ( Experiment& e
                              , details::times_set&  t
                              , details::cycles_set& c
                              ) const
    {
      // We copy reference experiment depending on whether they have
      // experiment_is_immutable or not
      typename details::experiment_copy<Experiment>::type local(e);

      time_quantum_t const time_start  ( time_quantum() );
      cycles_t       const cycles_start( read_cycles() );

      local();

      cycles_t       const cycles_end( read_cycles() );
      time_quantum_t const time_end  ( time_quantum() );

      cycles_t       const burned_cycles( cycles_end - cycles_start );
      time_quantum_t const elapsed_time ( time_end   - time_start   );

      t(to_microseconds(elapsed_time));
      c(burned_cycles);

      return elapsed_time;
    }

    template<typename Experiment>
    inline void display ( Experiment& e
                        , details::times_set&  t, details::cycles_set& c
                        ) const
    {
      boost::fusion::for_each ( metrics_
                              , details::display_metric<Experiment>(e,t,c)
                              );
    }

    protected:
    metrics_type  metrics_;
  };
} }

#endif


text:
/* CirKit: A circuit toolkit
 * Copyright (C) 2009-2015  University of Bremen
 * Copyright (C) 2015-2017  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "sequential_simulation.hpp"

#include <fstream>
#include <map>
#include <string>
#include <vector>

#include <boost/assign/std/vector.hpp>
#include <boost/format.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/irange.hpp>

#include <core/utils/timer.hpp>

#include <reversible/simulation/partial_simulation.hpp>

using namespace boost::assign;

namespace cirkit
{

  // If needed somewhere else, put to utilities of simulation
  class wave_file
  {
  public:
    wave_file( const std::string& filename, const std::string& name )
      : wire_count( 0u ),
        time_step( 0u )
    {
      os.open( filename.c_str() );

      os << "$timescale 1 ps $end" << std::endl << std::endl;

      os << "$scope module " << name << " $end" << std::endl;
      os << "$var wire 1 clk clock $end" << std::endl;
    }

    bool add_wire( const std::string& name, unsigned num_bits = 1u )
    {
      if ( wire_mapping.find( name ) != wire_mapping.end() )
      {
        std::cout << "Wire with name " << name << " has been defined already" << std::endl;
        return false;
      }

      wire_mapping.insert( std::make_pair( name, wire_count ) );

      os << "$var wire " << num_bits << " w" << wire_count << " " << name << " $end" << std::endl;

      ++wire_count;

      return true;
    }

    bool add_signal( const std::string& name, bool value )
    {
      std::map<std::string, unsigned>::const_iterator it = wire_mapping.find( name );

      if ( it == wire_mapping.end() )
      {
        return false;
      }

      os << value << "w" << it->second << std::endl;

      return true;
    }

    bool add_signal( const std::string& name, const boost::dynamic_bitset<>& value )
    {
      std::map<std::string, unsigned>::const_iterator it = wire_mapping.find( name );

      if ( it == wire_mapping.end() )
      {
        return false;
      }

      os << "b" << value << " w" << it->second << std::endl;

      return true;
    }

    void next()
    {
      if ( time_step == 0u )
      {
        os << "$upscope $end" << std::endl;
        os << "$enddefinitions $end" << std::endl << std::endl;
      }

      os << boost::format( "#%d" ) % ( time_step * 1000u ) << std::endl;
      os << boost::format( "%dclk" ) % ( time_step % 2u ) << std::endl;

      ++time_step;
    }

    void close()
    {
      os << boost::format( "#%d" ) % ( time_step * 1000u ) << std::endl;
    }

  private:
    std::ofstream os;
    unsigned wire_count;
    std::map<std::string, unsigned> wire_mapping;
    unsigned time_step;
  };

  template<typename Integer>
  boost::iterator_range<boost::range_detail::integer_iterator<Integer> >
  irange( Integer last )
  {
    return boost::irange( 0u, last );
  }

  // Maybe needed somewhere else as well
  // Input at i is no constant and no state variable and in no bus
  inline bool is_single_input( const circuit& circ, unsigned index )
  {
    return !circ.constants().at( index ) &&
      !circ.statesignals().has_bus( index ) &&
      !circ.inputbuses().has_bus( index );
  }

  // Maybe needed somewhere else as well
  // Output at i is no garbage and no state variable and in no bus
  inline bool is_single_output( const circuit& circ, unsigned index )
  {
    return !circ.garbage().at( index ) &&
      !circ.statesignals().has_bus( index ) &&
      !circ.outputbuses().has_bus( index );
  }

  inline bool is_input( const circuit& circ, unsigned index )
  {
    return !circ.constants().at( index );
  }

  inline bool is_output( const circuit& circ, unsigned index )
  {
    return !circ.garbage().at( index );
  }

  inline bool is_primary_input( const circuit& circ, unsigned index )
  {
    return is_input( circ, index ) && !circ.statesignals().has_bus( index );
  }

  inline bool is_primary_output( const circuit& circ, unsigned index )
  {
    return is_output( circ, index ) && !circ.statesignals().has_bus( index );
  }

  bool sequential_simulation( std::vector<boost::dynamic_bitset<> >& outputs,
                              const circuit& circ,
                              const std::vector<boost::dynamic_bitset<> >& inputs,
                              properties::ptr settings, properties::ptr statistics )
  {

    typedef std::map<std::string, boost::dynamic_bitset<> > bitset_map;

    // Settings parsing
    bitset_map initial_state = get<bitset_map>( settings, "initial_state", bitset_map() );
    std::string vcd_filename = get<std::string>( settings, "vcd_filename", std::string() );
    sequential_step_result_func step_result = get<sequential_step_result_func>( settings, "step_result", sequential_step_result_func() );

    // Run-time measuring
    properties_timer t( statistics );

    // Wavefile Generation
    bool write_wavefile = !vcd_filename.empty();
    std::shared_ptr<wave_file> vcd_file;

    bitset_map ibitsets;
    bitset_map sbitsets;
    bitset_map obitsets;

    for ( const auto& bus : circ.inputbuses().buses() )
    {
      ibitsets.insert( std::make_pair( bus.first, boost::dynamic_bitset<>( bus.second.size() ) ) );
    }

    for ( const auto& bus : circ.statesignals().buses() )
    {
      sbitsets.insert( std::make_pair( bus.first, boost::dynamic_bitset<>( bus.second.size() ) ) );

      bitset_map::const_iterator itInitialState = initial_state.find( bus.first );
      if ( itInitialState != initial_state.end() )
      {
        // found a key defined in the initial states
        // now the respective bitvectors have to match in size
        if ( itInitialState->second.size() == bus.second.size() )
        {
          // ok, sizes match
          sbitsets[bus.first] = itInitialState->second;
        }
        else
        {
          // failed
          set_error_message( statistics, boost::str( boost::format( "Bit-vector of initial state %s has wrong bit-width %d. Expected bitwidth is %d." ) % bus.first % itInitialState->second % bus.second.size() ) );
          return false;
        }
      }
    }

    for ( const auto& bus : circ.outputbuses().buses() )
    {
      obitsets.insert( std::make_pair( bus.first, boost::dynamic_bitset<>( bus.second.size() ) ) );
    }

    // wave file
    if ( write_wavefile )
    {
      vcd_file.reset( new wave_file( vcd_filename, "RevKit" ) );

      // inputs
      for ( const auto& bus : circ.inputbuses().buses() )
      {
        vcd_file->add_wire( bus.first, bus.second.size() );
      }

      for ( unsigned index : irange( circ.lines() ) )
      {
        if ( is_single_input( circ, index ) )
        {
          vcd_file->add_wire( circ.inputs().at( index ) );
        }
      }

      // states
      for ( const auto& bus : circ.statesignals().buses() )
      {
        vcd_file->add_wire( bus.first, bus.second.size() );
        vcd_file->add_wire( bus.first + "'", bus.second.size() );
      }

      // outputs
      for ( const auto& bus : circ.outputbuses().buses() )
      {
        vcd_file->add_wire( bus.first + "'", bus.second.size() );
      }

      for ( unsigned index : irange( circ.lines() ) )
      {
        if ( is_single_output( circ, index ) )
        {
          vcd_file->add_wire( circ.outputs().at( index ) + "'" );
        }
      }
    }

    // number of inputs (no constants)
    unsigned num_inputs = boost::count_if( irange( circ.lines() ), [&circ]( unsigned l ) { return is_input( circ, l ); } );
    // number of primary outputs (no garbage)
    unsigned num_pos = boost::count_if( irange( circ.lines() ), [&circ]( unsigned l ) { return is_primary_output( circ, l ); } );

    // simulate
    unsigned current_input = 0u;
    boost::dynamic_bitset<> next_input( 0u ); // can be given by the step_result_func, however, current_input has priority
    while ( current_input < inputs.size() || !next_input.empty() )
    {
      using boost::adaptors::filtered;

      boost::dynamic_bitset<> input_assignment = ( current_input < inputs.size() ? inputs.at( current_input ) : next_input );

      // wave file
      if ( write_wavefile )
      {
        vcd_file->next();
      }

      boost::dynamic_bitset<> input( num_inputs );
      unsigned pos = 0u;
      unsigned pos_in_input = 0u;

      for ( unsigned index : irange( circ.lines() ) | filtered( [&circ]( unsigned l ) { return is_input( circ, l ); } ) )
      {
        // PI or PPI?
        if ( is_primary_input( circ, index ) ) // PI
        {
          input.set( pos, input_assignment.test( pos_in_input++ ) );

          // wave file
          if ( write_wavefile )
          {
            std::string bus_name = circ.inputbuses().find_bus( index );
            if ( !bus_name.empty() )
            {
              const std::vector<unsigned>& line_indices = circ.inputbuses().get( bus_name );
              ibitsets[bus_name].set( std::find( line_indices.begin(), line_indices.end(), index ) - line_indices.begin(), input.test( pos ) );
            }
            else
            {
              vcd_file->add_signal( circ.inputs().at( index ), input.test( pos ) );
            }

          }
        }
        else // PPI
        {
          input.set( pos, sbitsets[circ.statesignals().find_bus( index )].test( circ.statesignals().signal_index( index ) ) );
        }

        ++pos;
      }

      // wave file
      if ( write_wavefile )
      {
        for ( bitset_map::const_iterator itBitset = ibitsets.begin(); itBitset != ibitsets.end(); ++itBitset )
        {
          vcd_file->add_signal( itBitset->first, itBitset->second );
        }

        for ( bitset_map::const_iterator itBitset = sbitsets.begin(); itBitset != sbitsets.end(); ++itBitset )
        {
          vcd_file->add_signal( itBitset->first, itBitset->second );
        }
      }

      boost::dynamic_bitset<> output;
      partial_simulation( output, circ, input );

      boost::dynamic_bitset<> outputAssignment( num_pos );

      // reset obitsets
      for ( bitset_map::iterator itBitset = obitsets.begin(); itBitset != obitsets.end(); ++itBitset )
      {
        itBitset->second.reset();
      }

      pos = 0u;
      unsigned pos_in_output = 0u;
      for ( unsigned index : irange( circ.lines() ) | filtered( [&circ]( unsigned l ) { return is_output( circ, l ); } ) )
      {
        // PO or PPO?
        if ( is_primary_output( circ, index ) ) // PO
        {
          outputAssignment.set( pos_in_output++, output.test( pos ) );

          // wave file
          if ( write_wavefile )
          {
            std::string bus_name = circ.outputbuses().find_bus( index );
            if ( !bus_name.empty() )
            {
              const std::vector<unsigned>& line_indices = circ.outputbuses().get( bus_name );
              obitsets[bus_name].set( std::find( line_indices.begin(), line_indices.end(), index ) - line_indices.begin(), output.test( pos ) );
            }
            else
            {
              vcd_file->add_signal( circ.outputs().at( index ) + "'", output.test( pos ) );
            }
          }
        }
        else
        {
          sbitsets[circ.statesignals().find_bus( index )].set( circ.statesignals().signal_index( index ), output.test( pos ) );
        }
        ++pos;
      }

      // wave file
      if ( write_wavefile )
      {
        for ( bitset_map::const_iterator itBitset = obitsets.begin(); itBitset != obitsets.end(); ++itBitset )
        {
          vcd_file->add_signal( itBitset->first + "'", itBitset->second );
        }

        for ( bitset_map::const_iterator itBitset = sbitsets.begin(); itBitset != sbitsets.end(); ++itBitset )
        {
          vcd_file->add_signal( itBitset->first + "'", itBitset->second );
        }
      }

      outputs += outputAssignment;

      if ( step_result )
      {
        next_input = step_result( sbitsets, outputAssignment );
      }

      ++current_input;
    }

    if ( write_wavefile )
    {
      vcd_file->close();
    }

    return true;
  }

  multi_step_simulation_func sequential_simulation_func( properties::ptr settings, properties::ptr statistics )
  {
    multi_step_simulation_func f = [&settings, &statistics]( std::vector<boost::dynamic_bitset<> >& outputs,
                                                             const circuit& circ,
                                                             const std::vector<boost::dynamic_bitset<> >& inputs ) {
      return sequential_simulation( outputs, circ, inputs, settings, statistics );
    };
    f.init( settings, statistics );
    return f;
  }

}

// Local Variables:
// c-basic-offset: 2
// eval: (c-set-offset 'substatement-open 0)
// eval: (c-set-offset 'innamespace 0)
// End:

max_stars_repo_name: eletesta/cirkit

max_issues_repo_name: eletesta/cirkit

max_forks_repo_name: eletesta/cirkit


text:
#pragma once
#include <chrono>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <rai/common/numbers.hpp>
#include <rai/common/blocks.hpp>

namespace rai
{
class GapInfo
{
public:
    GapInfo(const rai::BlockHash&, const std::shared_ptr<rai::Block>&);
    rai::BlockHash hash_;
    rai::Account account_;
    std::chrono::steady_clock::time_point arrival_;
    std::shared_ptr<rai::Block> block_;
};

class GapInfoByAccount
{
};

class GapInfoByArrival
{
};

class GapCache
{
public:
    bool Insert(const rai::GapInfo&);
    void Remove(const rai::BlockHash&);
    boost::optional<rai::GapInfo> Query(const rai::BlockHash&) const;
    std::vector<rai::GapInfo> Age(uint64_t);

private:
    static size_t constexpr MAX_CACHES_PER_ACCOUNT = 16;
    static size_t constexpr MAX_CACHES = 128 * 1024;

    mutable std::mutex mutex_;
    boost::multi_index_container<
        rai::GapInfo,
        boost::multi_index::indexed_by<
            boost::multi_index::hashed_unique<boost::multi_index::member<
                rai::GapInfo, rai::BlockHash, &rai::GapInfo::hash_>>,
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<rai::GapInfoByAccount>,
                boost::multi_index::member<rai::GapInfo, rai::Account,
                                           &rai::GapInfo::account_>>,
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<rai::GapInfoByArrival>,
                boost::multi_index::member<
                    rai::GapInfo, std::chrono::steady_clock::time_point,
                    &rai::GapInfo::arrival_>>>>
        caches_;
};
}  // namespace rai

max_stars_repo_name: gokoo/Raicoin


text:
#pragma once

#include <grpc++/grpc++.h>

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <cstdio>
#include <iostream>
#include <mutex>
#include <string>

#include "etcd/Client.hpp"
#include "etcd/Response.hpp"
#include "proto/rpc.grpc.pb.h"

namespace etcdv3 {
class AsyncKeepAliveAction;
}

using etcdserverpb::KV;
using grpc::Channel;

namespace etcd {
/**
 * Wrapper for a boost::asio timer that provides simple start/stop/repeat
 * functions
 */
class KeepAliveTimer {
 public:
  typedef boost::function<void(boost::system::error_code, KeepAliveTimer*)> handler_function;

  KeepAliveTimer(boost::asio::io_context& io, boost::asio::chrono::milliseconds interval)
      : interval_(interval), timer_(boost::asio::steady_timer(io, interval)) {}
  ~KeepAliveTimer() { timer_.cancel(); }

  void setCallback(handler_function handler) { handler_ = handler; }

  void start() {
    timer_.expires_from_now(boost::asio::chrono::milliseconds(50) /* expire immediately; set to interval_ otherwise*/);
    timer_.async_wait(boost::bind(handler_, boost::asio::placeholders::error,
                                  this));  // boost::ref(*this)));
  }

  void repeat() {
    timer_.expires_at(timer_.expiry() + interval_);
    timer_.async_wait(boost::bind(handler_, boost::asio::placeholders::error,
                                  this));  // boost::ref(*this)));
  }

  void stop() { timer_.cancel(); }

 private:
  boost::asio::chrono::milliseconds interval_;
  boost::asio::steady_timer timer_;
  handler_function handler_;
};

/**
 * The main KeepAlive service class. You only need one per process since it can
 * service many leases with different refresh intervals
 */
class KeepAlive {
  enum class Type { READ = 1, WRITE = 2, CONNECT = 3, WRITES_DONE = 4, FINISH = 5 };

 public:
  /**
   * Create an instance of the KeepAlive service
   * Call add(leaseid, refresh_interval) to add a leaseid to be kept alive by
   * this service
   * @param client the client etcd connection to use
   */
  KeepAlive(Client& client);

  /**
   * Add a lease to be kept alive by this service
   * @param leaseid the id of the lease
   * @param refresh_interval the interval to refresh the lease
   */
  void add(int64_t leaseid, boost::asio::chrono::milliseconds refresh_interval);

  /**
   * Remove a lease from being kept alive, and optionally revoke it immediately
   * @param leaseid the id of the lease
   * @param revoke true to immediatley revoke the lease (defaults to false)
   */
  void remove(int64_t leaseid, bool revoke = false);

  /**
   * Remove all leases that the service is currently refreshing.
   * @param revoke true to immediately revoke the leases (defaulst to false)
   */
  void removeAll(bool revoke = false);

  ~KeepAlive();

 private:
  KeepAlive(KeepAlive const& rhs);             // prevent copying
  KeepAlive& operator=(KeepAlive const& rhs);  // prevent assignment

  /**
   * Moves the registered leases to a processing queue, and then resets the
   * timer and triggers the first lease renewal request
   */
  void queueKeepAlivesCallback(const boost::system::error_code& error, KeepAliveTimer* timer);

  /**
   * Sends a keep alive for the next lease in the queue
   */
  void sendNextKeepAlive(std::unique_ptr<grpc::ClientAsyncReaderWriter<etcdserverpb::LeaseKeepAliveRequest,
                                                                       etcdserverpb::LeaseKeepAliveResponse>>& stream);

  /**
   * Read the response off the stream
   */
  void readNextMessage(std::unique_ptr<grpc::ClientAsyncReaderWriter<etcdserverpb::LeaseKeepAliveRequest,
                                                                     etcdserverpb::LeaseKeepAliveResponse>>& stream);

  // Boost io_context, which is responsible for doing the timer work
  boost::asio::io_context io_;
  // Thread for the io_context to use
  std::unique_ptr<boost::thread> t_;

  // A mutex to use to protect all of our lease maps/queues when manipulating
  // them
  std::mutex mutex_;
  // The map of leases that have been registered with this service to be kept
  // alive
  std::map<int64_t, std::shared_ptr<KeepAliveTimer>> leases_;
  // All of the timers that are currently running
  std::map<boost::asio::chrono::milliseconds, std::shared_ptr<KeepAliveTimer>> timers_;
  // The current queue of keepalives that need to be sent
  std::queue<int64_t> keepalive_queue_;

  // The long running task for this service
  pplx::task<void> current_task_;

  // The client that we are attached to.
  Client& client_;

  // Context for the client. It could be used to convey extra information to
  // the server and/or tweak certain RPC behaviors.
  grpc::ClientContext context_;

  // The producer-consumer queue we use to communicate asynchronously with the
  // gRPC runtime.
  grpc::CompletionQueue cq_;

  // Out of the passed in Channel comes the stub, stored here, our view of the
  // server's exposed services.
  std::unique_ptr<etcdserverpb::Lease::Stub> stub_;

  bool connected_ = false;

  // The bidirectional, asynchronous stream for sending/receiving messages.
  std::unique_ptr<
      grpc::ClientAsyncReaderWriter<etcdserverpb::LeaseKeepAliveRequest, etcdserverpb::LeaseKeepAliveResponse>>
      stream_;

  // Allocated protobuf that holds the response. In real clients and servers,
  // the memory management would a bit more complex as the thread that fills
  // in the response should take care of concurrency as well as memory
  // management.
  etcdserverpb::LeaseKeepAliveResponse response_;

  // Finish status when the client is done with the stream.
  grpc::Status finish_status_ = grpc::Status::OK;
};
}  // namespace etcd


text:
#include "map.h"
#include "node.h"
#include "path_finding.h"
#include <iostream>
#include <boost/assert.hpp>
#include <boost/assign/list_inserter.hpp>

pf::Map generateMap()
{
	std::vector<int> q0, q1, q2, q3, q4, q5, q6, q7, q8, q9;

	boost::assign::push_back(q0) (1)(1)(1)(1)(1)(9)(1)(1)(1)(1);
	boost::assign::push_back(q1) (1)(1)(1)(1)(1)(9)(1)(1)(1)(1);
	boost::assign::push_back(q2) (1)(1)(9)(9)(9)(9)(9)(9)(9)(1);
	boost::assign::push_back(q3) (1)(1)(1)(1)(1)(1)(1)(1)(9)(1);
	boost::assign::push_back(q4) (9)(9)(9)(9)(9)(9)(9)(1)(9)(1);
	boost::assign::push_back(q5) (1)(1)(1)(1)(1)(1)(9)(1)(9)(1);
	boost::assign::push_back(q6) (1)(1)(1)(1)(9)(9)(9)(1)(9)(1);
	boost::assign::push_back(q7) (1)(1)(1)(1)(1)(1)(1)(1)(9)(1);
	boost::assign::push_back(q8) (1)(1)(1)(1)(9)(9)(9)(9)(9)(1);
	boost::assign::push_back(q9) (1)(1)(1)(1)(1)(1)(1)(1)(1)(1);

	std::vector< std::vector<int> > fieldMap;
	boost::assign::push_back(fieldMap)
		(q0)(q1)(q2)(q3)(q4)(q5)(q6)(q7)(q8)(q9)
	;

	pf::Map map(fieldMap);
	return map;
}

void main()
{
	pf::Map map = generateMap();

	pf::LPNode nodeStart(new pf::Node(map.getField(0, 3)));
	pf::LPNode nodeStop (new pf::Node(map.getField(9, 3)));

	std::cout << "before" << std::endl;
	pf::PathFinding::print(map, nodeStart, nodeStop, pf::NodeList());

	pf::NodeList path = pf::PathFinding::search(map, nodeStart, nodeStop);

	std::cout << std::endl << "after" << std::endl;
	pf::PathFinding::print(map, nodeStart, nodeStop, path);
	std::cout << std::endl;
}


text:
#ifndef BOOST_CONTRACT_DETAIL_COND_POST_HPP_
#define BOOST_CONTRACT_DETAIL_COND_POST_HPP_

// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html

#include <boost/contract/core/config.hpp>
#include <boost/contract/core/exception.hpp>
#include <boost/contract/detail/condition/cond_base.hpp>
#include <boost/contract/detail/none.hpp>
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
#include <boost/contract/detail/type_traits/optional.hpp>
#include <boost/function.hpp>
#include <boost/mpl/if.hpp>
#include <boost/optional.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/type_traits/remove_reference.hpp>
#endif

/* PRIVATE */

#define BOOST_CONTRACT_DETAIL_COND_POST_DEF_(result_type, result_param,        \
                                             ftor_type, ftor_var, ftor_call)   \
public:                                                                        \
  template <typename F> void set_post(F const &f) { ftor_var = f; }            \
                                                                               \
protected:                                                                     \
  void check_post(result_type const &result_param) {                           \
    if (failed())                                                              \
      return;                                                                  \
    try {                                                                      \
      if (ftor_var) {                                                          \
        ftor_call;                                                             \
      }                                                                        \
    } catch (...) {                                                            \
      fail(&boost::contract::postcondition_failure);                           \
    }                                                                          \
  }                                                                            \
                                                                               \
private:                                                                       \
  boost::function<ftor_type> ftor_var; /* Boost.Func for lambdas, etc. */

/* CODE */

namespace boost {
namespace contract {
namespace detail {

template <typename VR>
class cond_post : public cond_base { // Non-copyable base.
public:
  explicit cond_post(boost::contract::from from) : cond_base(from) {}

#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
private:
  typedef typename boost::mpl::if_<
      is_optional<VR>,
      boost::optional<typename boost::remove_reference<
          typename optional_value_type<VR>::type>::type const &> const &,
      VR const &>::type r_type;

  BOOST_CONTRACT_DETAIL_COND_POST_DEF_(
      r_type, r, void(r_type),
      // Won't raise this error if NO_POST (for optimization).
      BOOST_CONTRACT_ERROR_postcondition_result_parameter_required,
      BOOST_CONTRACT_ERROR_postcondition_result_parameter_required(r))
#endif
};

template <> class cond_post<none> : public cond_base { // Non-copyable base.
public:
  explicit cond_post(boost::contract::from from) : cond_base(from) {}

#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  BOOST_CONTRACT_DETAIL_COND_POST_DEF_(
      none,
      /* r */ BOOST_PP_EMPTY(), void(),
      // Won't raise this error if NO_POST (for optimization).
      BOOST_CONTRACT_ERROR_postcondition_result_parameter_not_allowed,
      BOOST_CONTRACT_ERROR_postcondition_result_parameter_not_allowed())
#endif
};

} // namespace detail
} // namespace contract
} // namespace boost

#endif // #include guard

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/CPPAlliance/url
//

#ifndef BOOST_URL_BNF_PARSE_HPP
#define BOOST_URL_BNF_PARSE_HPP

#include <boost/url/detail/config.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/optional.hpp>

namespace boost {
namespace urls {
namespace bnf {

/** Parse a literal character
*/
inline
bool
parse(
    char const*& it,
    char const* end,
    error_code& ec,
    char ch) noexcept;

/** Parse an optional element

    @par BNF
    @code
    optional    = [ <T> ]
    @endcode
*/
template<class T>
bool
parse(
    char const*& it,
    char const* end,
    error_code& ec,
    optional<T>& t);

/** Parse a sequence of elements
*/
template<
    class T0,
    class T1,
    class... Tn>
bool
parse(
    char const*& it,
    char const* end,
    error_code& ec,
    T0&& t0,
    T1&& t1,
    Tn&&... tn);

/** Parse a complete string
*/
template<
    class T0,
    class... Tn>
bool
parse_string(
    string_view s,
    error_code& ec,
    T0&& t0,
    Tn&&... tn);

/** Parse a complete string

    @throw system_error Thrown on failure
*/
template<
    class T0,
    class... Tn>
void
parse_string(
    string_view s,
    T0&& t0,
    Tn&&... tn);

/** Return true if a string matches the grammar
*/
template<class T>
bool
is_valid(
    string_view s);

/** Throw an exception the string does not match the grammar
*/
template<class T>
void
validate(
    string_view s);

} // bnf
} // urls
} // boost

#include <boost/url/bnf/impl/parse.hpp>

#endif

max_stars_repo_name: TankerHQ/url

max_issues_repo_name: TankerHQ/url

max_forks_repo_name: TankerHQ/url