text:
#include "tsuba/RDGTopology.h"

#include <memory>
#include <string>
#include <unordered_map>
#include <utility>

#include <boost/outcome/detail/value_storage.hpp>
#include <unicode/utypes.h>

#include "PartitionTopologyMetadata.h"
#include "RDGPartHeader.h"
#include "katana/EntityTypeManager.h"
#include "katana/ErrorCode.h"
#include "katana/Logging.h"
#include "katana/Result.h"
#include "katana/URI.h"
#include "katana/config.h"
#include "tsuba/Errors.h"
#include "tsuba/FaultTest.h"
#include "tsuba/FileFrame.h"
#include "tsuba/FileView.h"
#include "tsuba/RDG.h"
#include "tsuba/tsuba.h"

namespace tsuba {

std::string
RDGTopology::path() const {
  if (metadata_entry_valid()) {
    return metadata_entry_->path_;
  }

  KATANA_LOG_WARN(
      "trying to get topology path, but not linked to a metadata entry. "
      "Returning empty string");
  return std::string();
}

void
RDGTopology::set_path(const std::string& path) {
  KATANA_LOG_VASSERT(
      metadata_entry_valid(),
      "metadata_entry_->must be set before we can set the topology path");
  metadata_entry_->path_ = path;
}

void
RDGTopology::set_invalid() {
  invalid_ = true;
  if (metadata_entry_valid()) {
    metadata_entry_->set_invalid();
  }
}

void
RDGTopology::set_metadata_entry(PartitionTopologyMetadataEntry* entry) {
  KATANA_LOG_ASSERT(entry != nullptr);
  metadata_entry_ = entry;
  KATANA_LOG_ASSERT(metadata_entry_valid());
}

bool
RDGTopology::metadata_entry_valid() const {
  return (metadata_entry_ != nullptr);
}

katana::Result<void>
RDGTopology::Bind(const katana::Uri& metadata_dir, bool resolve) {
  if (file_store_bound_) {
    KATANA_LOG_WARN("topology already bound, nothing to do");
    return katana::ResultSuccess();
  }
  if (path().empty()) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument, "Cannot bind topology with empty path");
  }

  katana::Uri t_path = metadata_dir.Join(path());
  KATANA_LOG_DEBUG(
      "binding to entire topology file at path {}", t_path.string());
  KATANA_CHECKED(file_storage_.Bind(t_path.string(), resolve));

  file_store_bound_ = true;
  storage_valid_ = true;

  return katana::ResultSuccess();
}

katana::Result<void>
RDGTopology::Bind(
    const katana::Uri& metadata_dir, uint64_t begin, uint64_t end,
    bool resolve) {
  if (path().empty()) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument, "Cannot bind topology with empty path");
  }
  katana::Uri t_path = metadata_dir.Join(path());
  KATANA_LOG_DEBUG(
      "binding from {} to {} with topology file at path {}", begin, end,
      t_path.string());
  KATANA_CHECKED(file_storage_.Bind(t_path.string(), begin, end, resolve));

  file_store_bound_ = true;
  storage_valid_ = true;

  return katana::ResultSuccess();
}

katana::Result<void>
RDGTopology::Map() {
  if (file_store_mapped_) {
    return katana::ResultSuccess();
  }

  if (!file_store_bound_) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument,
        "topology must be bound before it is mapped");
  }

  const auto* data = file_storage_.ptr<uint64_t>();

  size_t min_size = 4;
  if (file_storage_.size() < min_size) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument,
        "file_storage size {} is less than the minimum size {}",
        file_storage_.size(), min_size);
  }

  if (data[0] != 1) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument,
        "first entry in the topology data array must be 1, is {}", data[0]);
  }

  // ensure the data file matches the metadata
  KATANA_LOG_VASSERT(
      num_nodes_ == data[2], "expected {} nodes, found {} nodes", num_nodes_,
      data[2]);
  KATANA_LOG_VASSERT(
      num_edges_ == data[3], "expected {} edges, found {} edges", num_edges_,
      data[3]);

  adj_indices_ = &data[4];

  //TODO(emcginnis): this cursor stuff is gross and easy to mess up.
  // Could introduce a byte iterator, with all usual iterator input stuff.
  // Iterator is initialized with what byte alignment we would like to keep
  // in this case it is sizeof(uint64_t) aligned
  // as well as something like
  // AdvanceBy<T> which advances the cursor in the iterator by sizeof(T)
  // all of the padding math then gets wrapped up in the iterator
  const uint64_t* cursor = adj_indices_;
  const uint64_t magic = (num_nodes_ + num_edges_);

  uint64_t adj_indices_size = num_nodes_;
  // EdgeTypeAwareTopologies have a larger adj_indices array than usual topologies
  if (topology_state_ ==
      tsuba::RDGTopology::TopologyKind::kEdgeTypeAwareTopology) {
    adj_indices_size =
        std::max(num_nodes_, num_nodes_ * edge_condensed_type_id_map_size_);
  }

  cursor += adj_indices_size;

  dests_ = reinterpret_cast<const uint32_t*>(cursor);

  cursor += (num_edges_ / 2 + num_edges_ % 2);

  if (metadata_entry_->edge_index_to_property_index_map_present_) {
    KATANA_LOG_VASSERT(
        *cursor == magic, "expected magic number = {}, found {}", magic,
        *cursor);
    cursor += 1;
    edge_index_to_property_index_map_ = cursor;
    cursor += num_edges_;
  }

  if (metadata_entry_->node_index_to_property_index_map_present_) {
    KATANA_LOG_VASSERT(
        *cursor == magic, "expected magic number = {}, found {}", magic,
        *cursor);
    cursor += 1;
    node_index_to_property_index_map_ = cursor;
    cursor += num_nodes_;
  }

  if (metadata_entry_->edge_condensed_type_id_map_present_) {
    KATANA_LOG_VASSERT(
        *cursor == magic, "expected magic number = {}, found {}", magic,
        *cursor);

    cursor += 1;
    edge_condensed_type_id_map_ =
        reinterpret_cast<const katana::EntityTypeID*>(cursor);
    cursor +=
        ((num_edges_ / sizeof(uint64_t)) +
         FileFrame::calculate_padding_bytes(num_edges_, sizeof(uint64_t)));
  }

  if (metadata_entry_->node_condensed_type_id_map_present_) {
    KATANA_LOG_VASSERT(
        *cursor == magic, "expected magic number = {}, found {}", magic,
        *cursor);

    cursor += 1;
    node_condensed_type_id_map_ =
        reinterpret_cast<const katana::EntityTypeID*>(cursor);
    cursor +=
        ((num_nodes_ / sizeof(uint64_t)) +
         FileFrame::calculate_padding_bytes(num_nodes_, sizeof(uint64_t)));
  }

  size_t expected_size = GetGraphSize();
  if (file_storage_.size() < expected_size) {
    return KATANA_ERROR(
        katana::ErrorCode::InvalidArgument,
        "file_view size: {} expected size: {}., num_nodes = {}, num_edges = "
        "{}, "
        "edge_index_to_property_index_map_present_ = {}, "
        "node_index_to_property_index_map_present_ = {}, "
        "edge_condensed_type_id_map_present = {}, "
        "node_condensed_type_id_map_present = {}",
        file_storage_.size(), expected_size, num_nodes_, num_edges_,
        metadata_entry_->edge_index_to_property_index_map_present_,
        metadata_entry_->node_index_to_property_index_map_present_,
        metadata_entry_->edge_condensed_type_id_map_present_,
        metadata_entry_->node_condensed_type_id_map_present_);
  }

  file_store_mapped_ = true;

  return katana::ResultSuccess();
}

katana::Result<void>
RDGTopology::MapMetadataExtract(
    uint64_t num_nodes, uint64_t num_edges, bool storage_valid) {
  if (file_store_mapped_) {
    KATANA_LOG_WARN(
        "Tried to map metadata of the topology file, but topology file is "
        "already mapped");
    return katana::ResultSuccess();
  }

  if (!file_store_bound_) {
    return KATANA_ERROR(
        ErrorCode::InvalidArgument,
        "topology must be bound before it is mapped");
  }

  const auto* data = file_storage_.ptr<uint64_t>();

  size_t min_size = 4;
  if (file_storage_.size() < min_size) {
    return katana::ErrorCode::InvalidArgument;
  }

  if (data[0] != 1) {
    return katana::ErrorCode::InvalidArgument;
  }

  num_nodes_ = data[2];
  num_edges_ = data[3];

  //TODO(emcginnis): remove the || num_nodes/edges == 0 when the input rdgs are updated
  KATANA_LOG_VASSERT(
      num_nodes_ == num_nodes || num_nodes == 0,
      "Extracted num_nodes = {} does not match the known num_nodes = {}",
      num_nodes_, num_nodes);
  KATANA_LOG_VASSERT(
      num_edges_ == num_edges || num_edges == 0,
      "Extracted num_edges = {} does not match the known num_edges = {}",
      num_edges_, num_edges);

  topology_state_ = TopologyKind::kCSR;
  transpose_state_ = TransposeKind::kNo;
  edge_sort_state_ = EdgeSortKind::kAny;
  node_sort_state_ = NodeSortKind::kAny;

  // update our metadata entry with what we loaded, must do this since the metadata was incomplete before
  metadata_entry_->Update(
      num_edges_, num_nodes_,
      /*edge_index_to_property_index_map_present=*/false,
      /*node_index_to_property_index_map_present=*/false,
      /*edge_condensed_type_id_map_size_=*/0,
      /*edge_condensed_type_id_map_present=*/false,
      /*node_condensed_type_id_map_size_=*/0,
      /*node_condensed_type_id_map_present=*/false, topology_state_,
      transpose_state_, edge_sort_state_, node_sort_state_);

  KATANA_LOG_DEBUG(
      "Extracted Metadata from topology file: num_edges = {}, num_nodes = {}",
      metadata_entry_->num_edges_, metadata_entry_->num_nodes_);

  // since we extracted the metadata, we must write out this topology on Store
  // unless we have RemoteCopied the topology file into place already
  storage_valid_ = storage_valid;

  return katana::ResultSuccess();
}

katana::Result<void>
tsuba::RDGTopology::DoStore(
    RDGHandle handle, const katana::Uri& current_rdg_dir,
    std::unique_ptr<tsuba::WriteGroup>& write_group) {
  KATANA_LOG_VASSERT(!invalid_, "tried to store an invalid RDGTopology");

  if (!storage_valid_) {
    // This RDGTopology is either new, or is an update to a now-invalid RDGTopology

    KATANA_LOG_DEBUG(
        "Storing RDGTopology to file. TopologyKind={}, TransposeKind={}, "
        "EdgeSortKind={}, NodeSortKind={}",
        topology_state_, transpose_state_, edge_sort_state_, node_sort_state_);

    auto ff = std::make_unique<tsuba::FileFrame>();
    KATANA_CHECKED(ff->Init());

    uint64_t data[4] = {1, 0, num_nodes_, num_edges_};
    arrow::Status aro_sts = ff->Write(&data, 4 * sizeof(uint64_t));
    if (!aro_sts.ok()) {
      return tsuba::ArrowToTsuba(aro_sts.code());
    }

    if (num_nodes_) {
      if (edge_condensed_type_id_map_size_ > 0) {
        KATANA_LOG_VASSERT(
            adj_indices_ != nullptr,
            "Cannot store an RDGTopology with edges and null adj_indices");
      }
      const auto* raw = adj_indices_;
      static_assert(std::is_same_v<std::decay_t<decltype(*raw)>, uint64_t>);
      uint64_t adj_indices_size = num_nodes_;

      // EdgeTypeAwareTopologies have a larger adj_indices array than usual topologies
      if (topology_state_ ==
          tsuba::RDGTopology::TopologyKind::kEdgeTypeAwareTopology) {
        adj_indices_size = num_nodes_ * edge_condensed_type_id_map_size_;
      }

      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing adj_indices, size = {}",
          adj_indices_size);

      if (adj_indices_size > 0) {
        auto buf = arrow::Buffer::Wrap(raw, adj_indices_size);
        aro_sts = ff->Write(buf);
        if (!aro_sts.ok()) {
          return tsuba::ArrowToTsuba(aro_sts.code());
        }
      }
    }

    if (num_edges_) {
      KATANA_LOG_VASSERT(
          dests_ != nullptr, "Cannot store an RDGTopology with null dests_");
      const auto* raw = dests_;
      static_assert(std::is_same_v<std::decay_t<decltype(*raw)>, uint32_t>);

      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing dests, size = {}", num_edges_);

      auto buf = arrow::Buffer::Wrap(raw, num_edges_);
      KATANA_CHECKED_CONTEXT(
          ff->PaddedWrite(buf, sizeof(uint64_t)),
          "Failed to write dests to file frame");
    }

    if (edge_index_to_property_index_map_ != nullptr && num_edges_) {
      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing "
          "edge_index_to_property_index_map, size = {}",
          num_edges_);

      // first write the magic number
      uint64_t data[1] = {num_nodes_ + num_edges_};
      arrow::Status aro_sts = ff->Write(&data, 1 * sizeof(uint64_t));
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }

      // edge property index map is uint64_t map[num_edges]
      const auto* raw = edge_index_to_property_index_map_;
      static_assert(std::is_same_v<std::decay_t<decltype(*raw)>, uint64_t>);
      auto buf = arrow::Buffer::Wrap(raw, num_edges_);
      aro_sts = ff->Write(buf);
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }
    }

    if (node_index_to_property_index_map_ != nullptr && num_nodes_) {
      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing "
          "node_index_to_property_index_map, size = {}",
          num_nodes_);

      // first write the magic number
      uint64_t data[1] = {num_nodes_ + num_edges_};
      arrow::Status aro_sts = ff->Write(&data, 1 * sizeof(uint64_t));
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }

      // node property index map is uint64_t map[num_nodes]
      const auto* raw = node_index_to_property_index_map_;
      static_assert(std::is_same_v<std::decay_t<decltype(*raw)>, uint64_t>);
      auto buf = arrow::Buffer::Wrap(raw, num_nodes_);
      aro_sts = ff->Write(buf);
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }
    }

    if (edge_condensed_type_id_map_ != nullptr && num_edges_) {
      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing "
          "edge_condensed_type_id_map, size = {}",
          edge_condensed_type_id_map_size_);

      // first write the magic number
      uint64_t data[1] = {num_nodes_ + num_edges_};
      arrow::Status aro_sts = ff->Write(&data, 1 * sizeof(uint64_t));
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }

      // node property index map is uint64_t map[num_nodes]
      const auto* raw = edge_condensed_type_id_map_;
      static_assert(
          std::is_same_v<std::decay_t<decltype(*raw)>, katana::EntityTypeID>);
      auto buf = arrow::Buffer::Wrap(raw, edge_condensed_type_id_map_size_);
      // pad to nearest uint64_t aka 8 byte boundry
      KATANA_CHECKED_CONTEXT(
          ff->PaddedWrite(buf, sizeof(uint64_t)),
          "Failed to write edge_condensed_type_id_map to file frame");
    }

    if (node_condensed_type_id_map_ != nullptr && num_nodes_) {
      KATANA_LOG_DEBUG(
          "Storing RDGTopology to file. Writing "
          "node_condensed_type_id_map, size = {}",
          node_condensed_type_id_map_size_);

      // first write the magic number
      uint64_t data[1] = {num_nodes_ + num_edges_};
      arrow::Status aro_sts = ff->Write(&data, 1 * sizeof(uint64_t));
      if (!aro_sts.ok()) {
        return tsuba::ArrowToTsuba(aro_sts.code());
      }

      // node property index map is uint64_t map[num_nodes]
      const auto* raw = node_condensed_type_id_map_;
      static_assert(
          std::is_same_v<std::decay_t<decltype(*raw)>, katana::EntityTypeID>);
      auto buf = arrow::Buffer::Wrap(raw, node_condensed_type_id_map_size_);
      // pad to nearest uint64_t aka 8 byte boundry
      KATANA_CHECKED_CONTEXT(
          ff->PaddedWrite(buf, sizeof(uint64_t)),
          "Failed to write node_condensed_type_id_map to file frame");
    }

    //TODO: emcginnis need different naming schemes for the optional topologies?
    // add "epi_npi_eti_nti" to name?
    katana::Uri path_uri = MakeTopologyFileName(handle);
    ff->Bind(path_uri.string());
    TSUBA_PTP(internal::FaultSensitivity::Normal);
    write_group->StartStore(std::move(ff));
    TSUBA_PTP(internal::FaultSensitivity::Normal);

    // update the metadata entry

    KATANA_LOG_ASSERT(topology_state_ != TopologyKind::kInvalid);
    KATANA_LOG_ASSERT(transpose_state_ != TransposeKind::kInvalid);
    KATANA_LOG_ASSERT(edge_sort_state_ != EdgeSortKind::kInvalid);
    KATANA_LOG_ASSERT(node_sort_state_ != NodeSortKind::kInvalid);

    metadata_entry_->Update(
        path_uri.BaseName(), num_edges_, num_nodes_,
        (edge_index_to_property_index_map_ != nullptr),
        (node_index_to_property_index_map_ != nullptr),
        edge_condensed_type_id_map_size_,
        (edge_condensed_type_id_map_ != nullptr),
        node_condensed_type_id_map_size_,
        (node_condensed_type_id_map_ != nullptr), topology_state_,
        transpose_state_, edge_sort_state_, node_sort_state_);
  }

  else if (path().empty()) {
    // we don't have an update, but we are persisting in a new location
    // store our in memory state

    KATANA_LOG_DEBUG(
        "Storing RDGTopology to file in new location. TopologyKind={}, "
        "TransposeKind={}, "
        "EdgeSortKind={}, NodeSortKind={}",
        topology_state_, transpose_state_, edge_sort_state_, node_sort_state_);

    //TODO: emcginnis need different naming schemes for the optional topologies
    katana::Uri path_uri = MakeTopologyFileName(handle);

    // file store must be bound to make a copy of it in a new location
    if (!file_store_bound_) {
      // Can't just use RDGTopology::Bind() here since path() is empty
      // Must bind to old_path since we are persisting in a new location
      std::string old_path = metadata_entry_->old_path_;
      if (old_path.empty()) {
        return KATANA_ERROR(
            ErrorCode::InvalidArgument, "Cannot bind topology with empty path");
      }
      katana::Uri t_path = current_rdg_dir.Join(old_path);

      KATANA_LOG_DEBUG(
          "binding to entire topology file at path {} for relocation",
          t_path.string());
      KATANA_CHECKED_CONTEXT(
          file_storage_.Bind(t_path.string(), true),
          "failed binding topology file for copying at path = {}, "
          "TopologyKind={}, "
          "TransposeKind={}, EdgeSortKind={}, NodeSortKind={}",
          t_path.string(), topology_state_, transpose_state_, edge_sort_state_,
          node_sort_state_);

      file_store_bound_ = true;
    }

    TSUBA_PTP(internal::FaultSensitivity::Normal);
    // depends on `topology file_storage_` outliving writes
    // all topology file stores must remain bound until write_group->Finish() completes
    write_group->StartStore(
        path_uri.string(), file_storage_.ptr<uint8_t>(), file_storage_.size());
    TSUBA_PTP(internal::FaultSensitivity::Normal);

    // since nothing has changed besides the storage location, just have to update path
    metadata_entry_->path_ = path_uri.BaseName();
  }
  // else: no update, not persisting in a new location, so nothing for us to do

  return katana::ResultSuccess();
}

bool
tsuba::RDGTopology::Equals(const RDGTopology& other) const {
  return (
      file_storage_.size() == other.file_storage_.size() &&
      !memcmp(
          file_storage_.ptr<uint8_t>(), other.file_storage_.ptr<uint8_t>(),
          file_storage_.size()) &&
      topology_state_ == other.topology_state_ &&
      transpose_state_ == other.transpose_state_ &&
      edge_sort_state_ == other.edge_sort_state_ &&
      node_sort_state_ == other.node_sort_state_);
}

tsuba::RDGTopology
tsuba::RDGTopology::MakeShadow(
    TopologyKind topology_state, TransposeKind transpose_state,
    EdgeSortKind edge_sort_state, NodeSortKind node_sort_state) {
  RDGTopology topo = RDGTopology();

  topo.topology_state_ = topology_state;
  topo.transpose_state_ = transpose_state;
  topo.edge_sort_state_ = edge_sort_state;
  topo.node_sort_state_ = node_sort_state;
  return RDGTopology(std::move(topo));
}

tsuba::RDGTopology
tsuba::RDGTopology::MakeShadowCSR() {
  // Match on a CSR topology transposed or not transposed, and no sorting
  return MakeShadow(
      TopologyKind::kCSR, TransposeKind::kAny, EdgeSortKind::kAny,
      NodeSortKind::kAny);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::DoMake(
    tsuba::RDGTopology topo, const uint64_t* adj_indices, uint64_t num_nodes,
    const uint32_t* dests, uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    NodeSortKind node_sort_state) {
  topo.num_edges_ = num_edges;
  topo.adj_indices_ = std::move(adj_indices);
  topo.num_nodes_ = num_nodes;
  topo.dests_ = std::move(dests);
  topo.topology_state_ = topology_state;
  topo.transpose_state_ = transpose_state;
  topo.edge_sort_state_ = edge_sort_state;
  topo.node_sort_state_ = node_sort_state;

  return RDGTopology(std::move(topo));
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(
    const uint64_t* adj_indices, uint64_t num_nodes, const uint32_t* dests,
    uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    NodeSortKind node_sort_state) {
  RDGTopology topo = RDGTopology();

  // when we make from in memory objects, mark storage as invalid
  topo.storage_valid_ = false;
  return DoMake(
      std::move(topo), adj_indices, num_nodes, dests, num_edges, topology_state,
      transpose_state, edge_sort_state, node_sort_state);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(
    const uint64_t* adj_indices, uint64_t num_nodes, const uint32_t* dests,
    uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    const uint64_t* edge_index_to_property_index_map) {
  RDGTopology topo = RDGTopology();
  topo.edge_index_to_property_index_map_ =
      std::move(edge_index_to_property_index_map);

  // when we make from in memory objects, mark storage as invalid
  topo.storage_valid_ = false;
  return DoMake(
      std::move(topo), adj_indices, num_nodes, dests, num_edges, topology_state,
      transpose_state, edge_sort_state, NodeSortKind::kAny);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(
    const uint64_t* adj_indices, uint64_t num_nodes, const uint32_t* dests,
    uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    const uint64_t* edge_index_to_property_index_map,
    uint64_t edge_condensed_type_id_map_size,
    const katana::EntityTypeID* edge_condensed_type_id_map) {
  RDGTopology topo = RDGTopology();
  topo.edge_index_to_property_index_map_ =
      std::move(edge_index_to_property_index_map);
  topo.edge_condensed_type_id_map_size_ = edge_condensed_type_id_map_size;
  topo.edge_condensed_type_id_map_ = std::move(edge_condensed_type_id_map);

  // when we make from in memory objects, mark storage as invalid
  topo.storage_valid_ = false;

  return DoMake(
      std::move(topo), adj_indices, num_nodes, dests, num_edges, topology_state,
      transpose_state, edge_sort_state, NodeSortKind::kAny);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(
    const uint64_t* adj_indices, uint64_t num_nodes, const uint32_t* dests,
    uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    NodeSortKind node_sort_state,
    const uint64_t* edge_index_to_property_index_map,
    const uint64_t* node_index_to_property_index_map) {
  RDGTopology topo = RDGTopology();
  topo.edge_index_to_property_index_map_ =
      std::move(edge_index_to_property_index_map);
  topo.node_index_to_property_index_map_ =
      std::move(node_index_to_property_index_map);

  // when we make from in memory objects, mark storage as invalid
  topo.storage_valid_ = false;
  return DoMake(
      std::move(topo), adj_indices, num_nodes, dests, num_edges, topology_state,
      transpose_state, edge_sort_state, node_sort_state);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(
    const uint64_t* adj_indices, uint64_t num_nodes, const uint32_t* dests,
    uint64_t num_edges, TopologyKind topology_state,
    TransposeKind transpose_state, EdgeSortKind edge_sort_state,
    NodeSortKind node_sort_state,
    const uint64_t* edge_index_to_property_index_map,
    const uint64_t* node_index_to_property_index_map,
    uint64_t edge_condensed_type_id_map_size,
    const katana::EntityTypeID* edge_condensed_type_id_map,
    uint64_t node_condensed_type_id_map_size,
    const katana::EntityTypeID* node_condensed_type_id_map) {
  RDGTopology topo = RDGTopology();
  topo.edge_index_to_property_index_map_ =
      std::move(edge_index_to_property_index_map);
  topo.node_index_to_property_index_map_ =
      std::move(node_index_to_property_index_map);
  topo.edge_condensed_type_id_map_size_ = edge_condensed_type_id_map_size;
  topo.edge_condensed_type_id_map_ = std::move(edge_condensed_type_id_map);
  topo.node_condensed_type_id_map_size_ = node_condensed_type_id_map_size;
  topo.node_condensed_type_id_map_ = std::move(node_condensed_type_id_map);

  // when we make from in memory objects, mark storage as invalid
  topo.storage_valid_ = false;
  return DoMake(
      std::move(topo), adj_indices, num_nodes, dests, num_edges, topology_state,
      transpose_state, edge_sort_state, node_sort_state);
}

katana::Result<tsuba::RDGTopology>
tsuba::RDGTopology::Make(PartitionTopologyMetadataEntry* entry) {
  RDGTopology topo = RDGTopology(entry);
  topo.set_metadata_entry(entry);
  topo.num_edges_ = topo.metadata_entry_->num_edges_;
  topo.num_nodes_ = topo.metadata_entry_->num_nodes_;
  topo.topology_state_ = topo.metadata_entry_->topology_state_;
  topo.transpose_state_ = topo.metadata_entry_->transpose_state_;
  topo.edge_sort_state_ = topo.metadata_entry_->edge_sort_state_;
  topo.node_sort_state_ = topo.metadata_entry_->node_sort_state_;
  topo.edge_condensed_type_id_map_size_ =
      topo.metadata_entry_->edge_condensed_type_id_map_size_;
  topo.node_condensed_type_id_map_size_ =
      topo.metadata_entry_->node_condensed_type_id_map_size_;

  // when we make from storage primitives, we can say the storage is up to date
  topo.storage_valid_ = true;

  return katana::Result<tsuba::RDGTopology>(std::move(topo));
}

size_t
tsuba::RDGTopology::GetGraphSize() const {
  /// version, sizeof_edge_data, num_nodes, num_edges
  constexpr int mandatory_fields = 4;
  size_t graphsize = (mandatory_fields + num_nodes_) * sizeof(uint64_t) +
                     (num_edges_ * sizeof(uint32_t));

  KATANA_LOG_DEBUG("Base graph size = {}", graphsize);

  if (metadata_entry_->edge_index_to_property_index_map_present_) {
    // 1 is for the magic number
    graphsize += (1 * sizeof(uint64_t)) + (num_edges_ * sizeof(uint64_t));
    KATANA_LOG_DEBUG(
        "edge_index_to_property_index_map_present graph size = {}", graphsize);
  }

  if (metadata_entry_->node_index_to_property_index_map_present_) {
    // 1 is for the magic number
    graphsize += (1 * sizeof(uint64_t)) + (num_nodes_ * sizeof(uint64_t));
    KATANA_LOG_DEBUG(
        "node_index_to_property_index_map_present graph size = {}", graphsize);
  }

  if (metadata_entry_->edge_condensed_type_id_map_present_) {
    // 1 is for the magic number
    graphsize +=
        (1 * sizeof(uint64_t)) + (num_edges_ * sizeof(katana::EntityTypeID));
    KATANA_LOG_DEBUG(
        "edge_condensed_type_id_map_present graph size = {}", graphsize);
  }

  if (metadata_entry_->node_condensed_type_id_map_present_) {
    // 1 is for the magic number
    graphsize +=
        (1 * sizeof(uint64_t)) + (num_nodes_ * sizeof(katana::EntityTypeID));
    KATANA_LOG_DEBUG(
        "node_condensed_type_id_map_present graph size = {}", graphsize);
  }

  KATANA_LOG_DEBUG("Total graph size = {}", graphsize);
  return graphsize;
}

RDGTopology::RDGTopology(PartitionTopologyMetadataEntry* metadata_entry)
    : metadata_entry_(metadata_entry) {}

RDGTopology::RDGTopology() = default;

}  // namespace tsuba

max_stars_repo_name: bowu/katana

max_issues_repo_name: bowu/katana

max_forks_repo_name: bowu/katana


text:
#include <facter/util/directory.hpp>
#include <internal/util/regex.hpp>
#include <boost/filesystem.hpp>

using namespace std;
using namespace boost::filesystem;

namespace facter { namespace util {

    void directory::each_file(string const& directory, function<bool(string const&)> callback, string const& pattern)
    {
        boost::regex regex(pattern);

        // Attempt to iterate the directory
        boost::system::error_code ec;
        directory_iterator it = directory_iterator(directory, ec);
        if (ec) {
            return;
        }

        // Call the callback for any matching files
        directory_iterator end;
        for (; it != end; ++it) {
            boost::system::error_code ec;
            if (!is_regular_file(it->status(ec))) {
                continue;
            }
            if (re_search(it->path().filename().string(), regex)) {
                if (!callback(it->path().string())) {
                    break;
                }
            }
        }
    }

    void directory::each_subdirectory(string const& directory, function<bool(string const&)> callback, string const& pattern)
    {
        boost::regex regex(pattern);

        // Attempt to iterate the directory
        boost::system::error_code ec;
        directory_iterator it = directory_iterator(directory, ec);
        if (ec) {
            return;
        }

        // Call the callback for any matching subdirectories
        directory_iterator end;
        for (; it != end; ++it) {
            boost::system::error_code ec;
            if (!is_directory(it->status(ec))) {
                continue;
            }
            if (re_search(it->path().filename().string(), regex)) {
                if (!callback(it->path().string())) {
                    break;
                }
            }
        }
    }

}}  // namespace facter::util

ext: cc

max_stars_repo_name: whopper/facter

max_issues_repo_name: ferventcoder/facter

max_forks_repo_name: ferventcoder/facter


text:
// Copyright (C) 2016-2018 T. Zachary Laine
//
// 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)
#ifndef BOOST_YAP_USER_MACROS_HPP_INCLUDED
#define BOOST_YAP_USER_MACROS_HPP_INCLUDED

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum.hpp>

#ifndef BOOST_YAP_DOXYGEN

// unary
#define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int)
#define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int)

// binary
#define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__)
#define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__)

#define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro)

#endif // BOOST_YAP_DOXYGEN

/** Defines operator overloads for unary operator \a op_name that each take an
    expression instantiated from \a expr_template and return an expression
    instantiated from the \a result_expr_template expression template.  One
    overload is defined for each of the qualifiers const &,
    &, and &&.  For the lvalue reference overloads,
    the argument is captured by reference into the resulting expression.  For
    the rvalue reference overload, the argument is moved into the resulting
    expression.

    Example:
    \snippet user_macros_snippets.cpp USER_UNARY_OPERATOR

    \param op_name The operator to be overloaded; this must be one of the \b
    unary enumerators in expr_kind, without the
    expr_kind:: qualification.

    \param expr_template The expression template to which the overloads apply.
    \a expr_template must be an \ref ExpressionTemplate.

    \param result_expr_template The expression template to use to instantiate
    the result expression.  \a result_expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_UNARY_OPERATOR(                                         \
    op_name, expr_template, result_expr_template)                              \
    template<::boost::yap::expr_kind Kind, typename Tuple>                     \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> const & x)                                  \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::operand_type_t<                 \
            result_expr_template,                                              \
            expr_template<Kind, Tuple> const &>;                               \
        using tuple_type = ::boost::hana::tuple<lhs_type>;                     \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{                                                       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}};    \
    }                                                                          \
    template<::boost::yap::expr_kind Kind, typename Tuple>                     \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> & x)                                        \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::operand_type_t<                 \
            result_expr_template,                                              \
            expr_template<Kind, Tuple> &>;                                     \
        using tuple_type = ::boost::hana::tuple<lhs_type>;                     \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{                                                       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}};    \
    }                                                                          \
    template<::boost::yap::expr_kind Kind, typename Tuple>                     \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> && x)                                       \
    {                                                                          \
        using tuple_type = ::boost::hana::tuple<expr_template<Kind, Tuple>>;   \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{tuple_type{std::move(x)}};                             \
    }

/** Defines operator overloads for binary operator \a op_name that each
    produce an expression instantiated from the \a expr_template expression
    template.  One overload is defined for each of the qualifiers const
    &, &, and &&.  For the lvalue reference
    overloads, *this is captured by reference into the resulting
    expression.  For the rvalue reference overload, *this is
    moved into the resulting expression.

    Note that this does not work for yap::expr_kinds assign, subscript, or
    call.  Use BOOST_YAP_USER_ASSIGN_OPERATOR,
    BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for
    those, respectively.

    Example:
    \snippet user_macros_snippets.cpp USER_BINARY_OPERATOR

    \param op_name The operator to be overloaded; this must be one of the \b
    binary enumerators in expr_kind, except assign, subscript, or
    call, without the expr_kind:: qualification.

    \param expr_template The expression template to which the overloads apply.
    \a expr_template must be an \ref ExpressionTemplate.

    \param result_expr_template The expression template to use to instantiate
    the result expression.  \a result_expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_BINARY_OPERATOR(                                        \
    op_name, expr_template, result_expr_template)                              \
    template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> const & lhs, Expr && rhs)                   \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::operand_type_t<                 \
            result_expr_template,                                              \
            expr_template<Kind, Tuple> const &>;                               \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{                                                       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs),    \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> & lhs, Expr && rhs)                         \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::operand_type_t<                 \
            result_expr_template,                                              \
            expr_template<Kind, Tuple> &>;                                     \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{                                                       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs),    \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr>      \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        expr_template<Kind, Tuple> && lhs, Expr && rhs)                        \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::remove_cv_ref_t<                \
            expr_template<Kind, Tuple> &&>;                                    \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<result_expr_template, Expr>;  \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return result_expr_template<                                           \
            ::boost::yap::expr_kind::op_name,                                  \
            tuple_type>{                                                       \
            tuple_type{std::move(lhs),                                         \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        T && lhs, expr_template<Kind, Tuple> && rhs)                           \
        ->::boost::yap::detail::free_binary_op_result_t<                       \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> &&>                                     \
    {                                                                          \
        using result_types = ::boost::yap::detail::free_binary_op_result<      \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> &&>;                                    \
        using lhs_type = typename result_types::lhs_type;                      \
        using rhs_type = typename result_types::rhs_type;                      \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, std::move(rhs)}}; \
    }                                                                          \
    template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        T && lhs, expr_template<Kind, Tuple> const & rhs)                      \
        ->::boost::yap::detail::free_binary_op_result_t<                       \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> const &>                                \
    {                                                                          \
        using result_types = ::boost::yap::detail::free_binary_op_result<      \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> const &>;                               \
        using lhs_type = typename result_types::lhs_type;                      \
        using rhs_type = typename result_types::rhs_type;                      \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        using rhs_tuple_type = typename result_types::rhs_tuple_type;          \
        return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
                           rhs_type{rhs_tuple_type{std::addressof(rhs)}}}};    \
    }                                                                          \
    template<typename T, ::boost::yap::expr_kind Kind, typename Tuple>         \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(                  \
        T && lhs, expr_template<Kind, Tuple> & rhs)                            \
        ->::boost::yap::detail::free_binary_op_result_t<                       \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> &>                                      \
    {                                                                          \
        using result_types = ::boost::yap::detail::free_binary_op_result<      \
            result_expr_template,                                              \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            expr_template<Kind, Tuple> &>;                                     \
        using lhs_type = typename result_types::lhs_type;                      \
        using rhs_type = typename result_types::rhs_type;                      \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        using rhs_tuple_type = typename result_types::rhs_tuple_type;          \
        return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
                           rhs_type{rhs_tuple_type{std::addressof(rhs)}}}};    \
    }

/** Defines operator overloads for \a operator=() that each produce an
    expression instantiated from the \a expr_template expression template.
    One overload is defined for each of the qualifiers const &,
    &, and &&.  For the lvalue reference overloads,
    *this is captured by reference into the resulting expression.
    For the rvalue reference overload, *this is moved into the
    resulting expression.

    The \a rhs parameter to each of the defined overloads may be any type,
    including an expression, except that the overloads are constrained by
    std::enable_if<> not to conflict with the assignment and move assignement
    operators.  If \a rhs is a non-expression, it is wrapped in a terminal
    expression.

    Example:
    \snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR

    \param this_type The type of the class the operator is a member of; this
    is required to avoid clashing with the assignment and move assignement
    operators.

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template)               \
    template<                                                                  \
        typename Expr,                                                         \
        typename = std::enable_if_t<                                           \
            !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
    constexpr auto operator=(Expr && rhs) const &                              \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, this_type const &>;                  \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<                                                                  \
        typename Expr,                                                         \
        typename = std::enable_if_t<                                           \
            !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
    constexpr auto operator=(Expr && rhs) &                                    \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<                                                                  \
        typename Expr,                                                         \
        typename = std::enable_if_t<                                           \
            !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>>   \
    constexpr auto operator=(Expr && rhs) &&                                   \
    {                                                                          \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<this_type, rhs_type>;          \
        return expr_template<::boost::yap::expr_kind::assign, tuple_type>{     \
            tuple_type{std::move(*this),                                       \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }

/** Defines operator overloads for \a operator[]() that each produce an
    expression instantiated from the \a expr_template expression template.
    One overload is defined for each of the qualifiers const &,
    &, and &&.  For the lvalue reference overloads,
    *this is captured by reference into the resulting expression.
    For the rvalue reference overload, *this is moved into the
    resulting expression.

    The \a rhs parameter to each of the defined overloads may be any type,
    including an expression, except that the overloads are constrained by
    std::enable_if<> not to conflict with the assignment and move assignement
    operators.  If \a rhs is a non-expression, it is wrapped in a terminal
    expression.

    Example:
    \snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template)                       \
    template<typename Expr>                                                    \
    constexpr auto operator[](Expr && rhs) const &                             \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<typename Expr>                                                    \
    constexpr auto operator[](Expr && rhs) &                                   \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }                                                                          \
    template<typename Expr>                                                    \
    constexpr auto operator[](Expr && rhs) &&                                  \
    {                                                                          \
        using lhs_type =                                                       \
            ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
        using rhs_type =                                                       \
            ::boost::yap::detail::operand_type_t<expr_template, Expr>;         \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{  \
            tuple_type{std::move(*this),                                       \
                       ::boost::yap::detail::make_operand<rhs_type>{}(         \
                           static_cast<Expr &&>(rhs))}};                       \
    }

/** Defines operator overloads for the call operator taking any number of
    parameters ("operator()") that each produce an expression instantiated
    from the \a expr_template expression template.  One overload is defined
    for each of the qualifiers const &, &, and
    &&.  For the lvalue reference overloads, *this
    is captured by reference into the resulting expression.  For the rvalue
    reference overload, *this is moved into the resulting
    expression.

    The \a u parameters to each of the defined overloads may be any type,
    including an expression.  Each non-expression is wrapped in a terminal
    expression.

    Example:
    \snippet user_macros_snippets.cpp USER_CALL_OPERATOR

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_CALL_OPERATOR(expr_template)                            \
    template<typename... U>                                                    \
    constexpr auto operator()(U &&... u) const &                               \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using tuple_type = ::boost::hana::tuple<                               \
            lhs_type,                                                          \
            ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{                                                        \
                ::boost::yap::detail::make_operand<lhs_type>{}(*this),         \
                ::boost::yap::detail::make_operand<                            \
                    ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
                    static_cast(u))...}};                                \
    }                                                                          \
    template<typename... U>                                                    \
    constexpr auto operator()(U &&... u) &                                     \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using tuple_type = ::boost::hana::tuple<                               \
            lhs_type,                                                          \
            ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{                                                        \
                ::boost::yap::detail::make_operand<lhs_type>{}(*this),         \
                ::boost::yap::detail::make_operand<                            \
                    ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
                    static_cast(u))...}};                                \
    }                                                                          \
    template<typename... U>                                                    \
    constexpr auto operator()(U &&... u) &&                                    \
    {                                                                          \
        using this_type =                                                      \
            ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
        using tuple_type = ::boost::hana::tuple<                               \
            this_type,                                                         \
            ::boost::yap::detail::operand_type_t<expr_template, U>...>;        \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{                                                        \
                std::move(*this),                                              \
                ::boost::yap::detail::make_operand<                            \
                    ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
                    static_cast(u))...}};                                \
    }

#ifndef BOOST_YAP_DOXYGEN

#define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template)            \
    ::boost::yap::detail::operand_type_t<expr_template, BOOST_PP_CAT(U, n)>
#define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template)         \
    ::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t<   \
        expr_template,                                                         \
        BOOST_PP_CAT(U, n)>>{}(                                                \
        static_cast<BOOST_PP_CAT(U, n) &&>(BOOST_PP_CAT(u, n)))

#endif

/** Defines operator overloads for the call operator taking N parameters
    ("operator()(t0, t1, ... tn-1)") that each produce an expression
    instantiated from the \a expr_template expression template.  One overload
    is defined for each of the qualifiers const &,
    &, and &&.  For the lvalue reference overloads,
    *this is captured by reference into the resulting expression.
    For the rvalue reference overload, *this is moved into the
    resulting expression.

    The \a u parameters to each of the defined overloads may be any type,
    including an expression.  Each non-expression is wrapped in a terminal
    expression.

    Example:
    \snippet user_macros_snippets.cpp USER_CALL_OPERATOR

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.

    \param n The number of parameters accepted by the operator() overloads.  n
    must be <= BOOST_PP_LIMIT_REPEAT.
*/
#define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n)                       \
    template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
    constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const &  \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using tuple_type = ::boost::hana::tuple<                               \
            lhs_type,                                                          \
            BOOST_PP_ENUM(                                                     \
                n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       BOOST_PP_ENUM(                                          \
                           n,                                                  \
                           BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
                           expr_template)}};                                   \
    }                                                                          \
    template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
    constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) &        \
    {                                                                          \
        using lhs_type = ::boost::yap::detail::                                \
            operand_type_t<expr_template, decltype(*this)>;                    \
        using tuple_type = ::boost::hana::tuple<                               \
            lhs_type,                                                          \
            BOOST_PP_ENUM(                                                     \
                n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this),  \
                       BOOST_PP_ENUM(                                          \
                           n,                                                  \
                           BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
                           expr_template)}};                                   \
    }                                                                          \
    template<BOOST_PP_ENUM_PARAMS(n, typename U)>                              \
    constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) &&       \
    {                                                                          \
        using this_type =                                                      \
            ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>;            \
        using tuple_type = ::boost::hana::tuple<                               \
            this_type,                                                         \
            BOOST_PP_ENUM(                                                     \
                n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>;    \
        return expr_template<::boost::yap::expr_kind::call, tuple_type>{       \
            tuple_type{std::move(*this),                                       \
                       BOOST_PP_ENUM(                                          \
                           n,                                                  \
                           BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND,          \
                           expr_template)}};                                   \
    }

/** Defines a 3-parameter function if_else() that acts as an
    analogue to the ternary operator (?:), since the ternary
    operator is not user-overloadable.  The return type of
    if_else() is an expression instantiated from the \a
    expr_template expression template.

    At least one parameter to if_else() must be an expression.

    For each parameter E passed to if_else(), if E is an rvalue,
    E is moved into the result, and otherwise E is captured by reference into
    the result.

    Example:
    \snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template)                             \
    template<typename Expr1, typename Expr2, typename Expr3>                   \
    constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3)     \
        ->::boost::yap::detail::                                               \
            ternary_op_result_t<expr_template, Expr1, Expr2, Expr3>            \
    {                                                                          \
        using result_types = ::boost::yap::detail::                            \
            ternary_op_result<expr_template, Expr1, Expr2, Expr3>;             \
        using cond_type = typename result_types::cond_type;                    \
        using then_type = typename result_types::then_type;                    \
        using else_type = typename result_types::else_type;                    \
        using tuple_type =                                                     \
            ::boost::hana::tuple<cond_type, then_type, else_type>;             \
        return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}(    \
                               static_cast<Expr1 &&>(expr1)),                  \
                           ::boost::yap::detail::make_operand<then_type>{}(    \
                               static_cast<Expr2 &&>(expr2)),                  \
                           ::boost::yap::detail::make_operand<else_type>{}(    \
                               static_cast<Expr3 &&>(expr3))}};                \
    }

/** Defines a function if_else() that acts as an analogue to the
    ternary operator (?:), since the ternary operator is not
    user-overloadable.  The return type of if_else() is an
    expression instantiated from the \a expr_template expression template.

    Each parameter to if_else() may be any type that is \b not an
    expression.  At least on parameter must be a type T for which
    \code udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value
    \endcode is true.  Each parameter is wrapped in a terminal expression.

    Example:
    \snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.

    \param udt_trait A trait template to use to constrain which types are
    accepted as template parameters to if_else().
*/
#define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait)               \
    template<typename Expr1, typename Expr2, typename Expr3>                   \
    constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3)     \
        ->::boost::yap::detail::udt_any_ternary_op_result_t<                   \
            expr_template,                                                     \
            Expr1,                                                             \
            Expr2,                                                             \
            Expr3,                                                             \
            udt_trait>                                                         \
    {                                                                          \
        using result_types = ::boost::yap::detail::udt_any_ternary_op_result<  \
            expr_template,                                                     \
            Expr1,                                                             \
            Expr2,                                                             \
            Expr3,                                                             \
            udt_trait>;                                                        \
        using cond_type = typename result_types::cond_type;                    \
        using then_type = typename result_types::then_type;                    \
        using else_type = typename result_types::else_type;                    \
        using tuple_type =                                                     \
            ::boost::hana::tuple<cond_type, then_type, else_type>;             \
        return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}(    \
                               static_cast<Expr1 &&>(expr1)),                  \
                           ::boost::yap::detail::make_operand<then_type>{}(    \
                               static_cast<Expr2 &&>(expr2)),                  \
                           ::boost::yap::detail::make_operand<else_type>{}(    \
                               static_cast<Expr3 &&>(expr3))}};                \
    }

/** Defines a free/non-member operator overload for unary operator \a op_name
    that produces an expression instantiated from the \a expr_template
    expression template.

    The parameter to the defined operator overload may be any type that is \b
    not an expression and for which \code
    udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
    true.  The parameter is wrapped in a terminal expression.

    Example:
    \snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR

    \param op_name The operator to be overloaded; this must be one of the \b
    unary enumerators in expr_kind, without the
    expr_kind:: qualification.

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.

    \param udt_trait A trait template to use to constrain which types are
    accepted as template parameters to the defined operator overload.
*/
#define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait)   \
    template<typename T>                                                       \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x)           \
        ->::boost::yap::detail::udt_unary_op_result_t<                         \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            udt_trait>                                                         \
    {                                                                          \
        using result_types = ::boost::yap::detail::udt_unary_op_result<        \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            udt_trait>;                                                        \
        using x_type = typename result_types::x_type;                          \
        using tuple_type = ::boost::hana::tuple<x_type>;                       \
        return {tuple_type{x_type{static_cast<T &&>(x)}}};                     \
    }

/** Defines a free/non-member operator overload for binary operator \a op_name
    that produces an expression instantiated from the \a expr_template
    expression template.

    The \a lhs parameter to the defined operator overload may be any type that
    is \b not an expression and for which \code
    t_udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
    true.  The parameter is wrapped in a terminal expression.

    The \a rhs parameter to the defined operator overload may be any type that
    is \b not an expression and for which \code
    u_udt_trait<std::remove_cv_t<std::remove_reference_t>>::value \endcode is
    true.  The parameter is wrapped in a terminal expression.

    Example:
    \snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR

    \param op_name The operator to be overloaded; this must be one of the \b
    binary enumerators in expr_kind, without the
    expr_kind:: qualification.

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.

    \param t_udt_trait A trait template to use to constrain which types are
    accepted as \a T template parameters to the defined operator overload.

    \param u_udt_trait A trait template to use to constrain which types are
    accepted as \a U template parameters to the defined operator overload.
*/
#define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR(                                \
    op_name, expr_template, t_udt_trait, u_udt_trait)                          \
    template<typename T, typename U>                                           \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
        ->::boost::yap::detail::udt_udt_binary_op_result_t<                    \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            U,                                                                 \
            t_udt_trait,                                                       \
            u_udt_trait>                                                       \
    {                                                                          \
        using result_types = ::boost::yap::detail::udt_udt_binary_op_result<   \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            U,                                                                 \
            t_udt_trait,                                                       \
            u_udt_trait>;                                                      \
        using lhs_type = typename result_types::lhs_type;                      \
        using rhs_type = typename result_types::rhs_type;                      \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return {tuple_type{                                                    \
            lhs_type{static_cast<T &&>(lhs)},                                  \
            rhs_type{static_cast(rhs)},                                  \
        }};                                                                    \
    }

/** Defines a free/non-member operator overload for binary operator \a op_name
    that produces an expression instantiated from the \a expr_template
    expression template.

    The \a lhs and \a rhs parameters to the defined operator overload may be any
   types that are \b not expressions.  Each parameter is wrapped in a terminal
   expression.

    At least one of the parameters to the defined operator overload must be a
    type \c T for which \code
    udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
    true.

    Example:
    \snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR

    \param op_name The operator to be overloaded; this must be one of the \b
    binary enumerators in expr_kind, without the
    expr_kind:: qualification.

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.

    \param udt_trait A trait template to use to constrain which types are
    accepted as template parameters to the defined operator overload.
*/
#define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(                                \
    op_name, expr_template, udt_trait)                                         \
    template<typename T, typename U>                                           \
    constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
        ->::boost::yap::detail::udt_any_binary_op_result_t<                    \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            U,                                                                 \
            udt_trait>                                                         \
    {                                                                          \
        using result_types = ::boost::yap::detail::udt_any_binary_op_result<   \
            expr_template,                                                     \
            ::boost::yap::expr_kind::op_name,                                  \
            T,                                                                 \
            U,                                                                 \
            udt_trait>;                                                        \
        using lhs_type = typename result_types::lhs_type;                      \
        using rhs_type = typename result_types::rhs_type;                      \
        using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>;           \
        return {tuple_type{lhs_type{static_cast<T &&>(lhs)},                   \
                           rhs_type{static_cast(rhs)}}};                 \
    }

/** Defines user defined literal template that creates literal placeholders
    instantiated from the \a expr_template expression template.  It is
    recommended that you put this in its own namespace.

    \param expr_template The expression template to use to instantiate the
    result expression.  \a expr_template must be an \ref
    ExpressionTemplate.
*/
#define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template)             \
    template<char... c>                                                        \
    constexpr auto operator"" _p()                                             \
    {                                                                          \
        using i = ::boost::hana::llong<                                        \
            ::boost::hana::ic_detail::parse<sizeof...(c)>({c...})>;            \
        static_assert(1 <= i::value, "Placeholders must be >= 1.");            \
        return expr_template<                                                  \
            ::boost::yap::expr_kind::terminal,                                 \
            ::boost::hana::tuple<::boost::yap::placeholder>>{};      \
    }

#endif

ext: hpp

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
#pragma once

#ifndef _common_local_service_hpp
#define _common_local_service_hpp

#include <vector>
#include <boost/thread.hpp>
#include <unordered_map>
#include "utime.hpp"

namespace prologcoin { namespace common {

class local_service {
public:
    local_service(utime::us tick = utime::us(100000))
  	: tick_(tick), killed_(false), num_workers_(0) {
    }

    ~local_service() {
	kill();
	join();
    }

    void run();

    void join() {
	for (auto w : workers_) {
	    w->join();
	    delete w;
	}
	workers_.clear();
	for (auto &m : label_locks_) {
	    delete m.second;
	}
    }

    void kill() {
	boost::unique_lock<boost::mutex> lockit(lock_);
	killed_ = true;
	queue_changed_.notify_all();
    }

    void add(const std::function<void ()> &fn, const std::string &label = "") {
	boost::unique_lock<boost::mutex> lockit(lock_);
	size_t n = queue_.size();
	for (size_t i = 0; i < n; i++) {
	    if (queue_[i].second == nullptr) {
		queue_[i].first = label;
		queue_[i].second = fn;
		queue_changed_.notify_one();
		return;
	    }
	}
	queue_.push_back(std::make_pair(label, fn));
	queue_changed_.notify_one();
    }

    size_t num_workers() const {
	return num_workers_;
    }

    void add_workers(size_t cnt) {
	boost::lock_guard<boost::mutex> lockit(lock_);
	internal_add_workers(cnt);
    }

    void ensure_workers(size_t cnt) {
	boost::unique_lock<boost::mutex> lockit(lock_);
	if (num_workers_ >= cnt) {
	    return;
	}
	size_t dcnt = cnt - num_workers_;
	internal_add_workers(dcnt);
    }

private:
    boost::mutex & get_label_mutex(const std::string &label) {
	boost::unique_lock<boost::mutex> lockit(lock_);
	auto it = label_locks_.find(label);
	if (it == label_locks_.end()) {
	    label_locks_[label] = new boost::mutex();
	}
	return *label_locks_[label];
    }

    void internal_add_workers(size_t cnt) {
	num_workers_ += cnt;
	for (size_t i = 0; i < cnt; i++) {
	    workers_.push_back(new boost::thread( [&]{ run(); } ));
	}
    }

    std::pair<std::function<void ()>, std::string> get_next_function() {
	size_t n = queue_.size();
	for (size_t i = 0; i < n; i++) {
	    if (auto f = queue_[i].second) {
		queue_[i].second = nullptr;
		return std::make_pair(f, queue_[i].first);
	    }
	}
	return std::make_pair(nullptr, "");
    }

    utime::us tick_;
    bool killed_;
    boost::mutex lock_;
    std::vector<std::pair<std::string, std::function<void ()> > > queue_;
    boost::condition_variable queue_changed_;
    std::vector<boost::thread *> workers_;
    size_t num_workers_;
    std::unordered_map<std::string, boost::mutex *> label_locks_;
};

}}

#endif

max_stars_repo_name: datavetaren/prologcoin

max_issues_repo_name: datavetaren/prologcoin

max_forks_repo_name: datavetaren/prologcoin


text:
// Copyright David Abrahams 2004. 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)

#include <boost/python/class.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/make_constructor.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/module.hpp>

using namespace boost::python;

class Foo
{
 public:
    Foo(tuple args, dict kw)
      : args(args), kw(kw) {}

    tuple args;
    dict kw;
};

object init_foo(tuple args, dict kw)
{
    tuple rest(args.slice(1,_));
    return args[0].attr("__init__")(rest, kw);
}

BOOST_PYTHON_MODULE(raw_ctor_ext)
{
    // using no_init postpones defining __init__ function until after
    // raw_function for proper overload resolution order, since later
    // defs get higher priority.
    class_<Foo>("Foo", no_init)
        .def("__init__", raw_function(&init_foo))
        .def(init<tuple, dict>())
        .def_readwrite("args", &Foo::args)
        .def_readwrite("kw", &Foo::kw)
        ;
}

#include "module_tail.cpp"

ext: cpp

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema