<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "BeaconOrder.h"
#include "PatternString.h"
#include "array_init.h"

// Library/third-party includes
// - none

// Standard includes
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

/// 1-based indices WRT the tracking software of beacons we'd like to disable.
/// Masked LEDs determined by BrightNeighbors using distance-cost method, 7 passes (6 LEDs).
static const auto DISABLED_TARGET0_BEACONS = {33, 13, 18, 32, 34, 5};

/// 1-based indices WRT the tracking software of the beacons on the rear that never light up anyway.
static const auto DISABLED_TARGET1_BEACONS = {1, 4};

static const int BITS_PER_BYTE = 8;

/// needs a bidirectional iterator
template <typename Iterator> inline uint8_t byteFromBoolContainer(Iterator lsb) {
  uint8_t ret = 0;
  Iterator it = lsb;
  // advancing one too far is OK because of the "one past the end" iterator.
  std::advance(it, BITS_PER_BYTE);
  for (int count = BITS_PER_BYTE; count != 0; --count) {
    // can unconditionally move backwards because we moved it one too far.
    --it;
    if (*it) {
      ret = ret << 1 | static_cast<uint8_t>(0x01);
    } else {
      ret = ret << 1;
    }
  }
  return ret;
}

template <typename Container> inline uint8_t byteFromBoolContainerAtBit(Container &&c, std::size_t bit) {
  auto it = begin(std::forward<Container>(c));
  if (bit > 0) {
    std::advance(it, bit);
  }
  return byteFromBoolContainer(it);
}

template <typename Container> inline uint8_t byteFromBoolContainerAtByte(Container &&c, std::size_t b) {
  return byteFromBoolContainerAtBit(std::forward<Container>(c), b * BITS_PER_BYTE);
}

int main() {
  std::vector<bool> mask(NUM_LEDS, true);
  for (auto &beacon1based : DISABLED_TARGET0_BEACONS) {
    auto bit = oneBasedTarget0BeaconToFirmwareBit(beacon1based);
    mask[bit] = false;
  }

  for (auto &beacon1based : DISABLED_TARGET1_BEACONS) {
    auto bit = oneBasedTarget1BeaconToFirmwareBit(beacon1based);
    mask[bit] = false;
  }

  for (int i = 0; i < LED_LINE_LENGTH; ++i) {
    auto b = byteFromBoolContainerAtByte(mask, i);
    std::cout << "0x" << std::hex << static_cast<unsigned>(b) << ", ";
  }
  std::cout << std::endl;

  return 0;
}
<commit_msg>Generate the bitmask for the HDK2<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "BeaconOrder.h"
#include "PatternString.h"
#include "array_init.h"

// Library/third-party includes
// - none

// Standard includes
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

/// 1-based indices WRT the tracking software of beacons we'd like to disable.
#if 0
/// HDK 1.3
/// Masked LEDs determined by BrightNeighbors using distance-cost method, 7 passes (6 LEDs).
static const auto DISABLED_TARGET0_BEACONS = {33, 13, 18, 32, 34, 5};
#else
/// HDK 2
/// Masked LEDs include the six not present in this hardware revision, with additional masked LEDs
/// informed by BrightNeighbors using the distance-cost method with 5 passes (4 LEDs). The last LED
/// suggsted by the algorithm would have been #5, which would have left one side of the HMD quite low
/// in LEDs, so the second-highest cost from that round, #26, was hand chosen instead.
static const auto DISABLED_TARGET0_BEACONS = {
    /// beacons not present in this hardware revision
    12, 13, 14, 25, 27, 28,
    /// beacons disabled due to interference
    33, 18, 32, 26};
#endif
/// 1-based indices WRT the tracking software of the beacons on the rear that never light up anyway.
static const auto DISABLED_TARGET1_BEACONS = {1, 4};

static const int BITS_PER_BYTE = 8;

/// needs a bidirectional iterator
template <typename Iterator> inline uint8_t byteFromBoolContainer(Iterator lsb) {
  uint8_t ret = 0;
  Iterator it = lsb;
  // advancing one too far is OK because of the "one past the end" iterator.
  std::advance(it, BITS_PER_BYTE);
  for (int count = BITS_PER_BYTE; count != 0; --count) {
    // can unconditionally move backwards because we moved it one too far.
    --it;
    if (*it) {
      ret = ret << 1 | static_cast<uint8_t>(0x01);
    } else {
      ret = ret << 1;
    }
  }
  return ret;
}

template <typename Container> inline uint8_t byteFromBoolContainerAtBit(Container &&c, std::size_t bit) {
  auto it = begin(std::forward<Container>(c));
  if (bit > 0) {
    std::advance(it, bit);
  }
  return byteFromBoolContainer(it);
}

template <typename Container> inline uint8_t byteFromBoolContainerAtByte(Container &&c, std::size_t b) {
  return byteFromBoolContainerAtBit(std::forward<Container>(c), b * BITS_PER_BYTE);
}

int main() {
  std::vector<bool> mask(NUM_LEDS, true);
  for (auto &beacon1based : DISABLED_TARGET0_BEACONS) {
    auto bit = oneBasedTarget0BeaconToFirmwareBit(beacon1based);
    mask[bit] = false;
  }

  for (auto &beacon1based : DISABLED_TARGET1_BEACONS) {
    auto bit = oneBasedTarget1BeaconToFirmwareBit(beacon1based);
    mask[bit] = false;
  }

  for (int i = 0; i < LED_LINE_LENGTH; ++i) {
    auto b = byteFromBoolContainerAtByte(mask, i);
    std::cout << "0x" << std::hex << static_cast<unsigned>(b) << ", ";
  }
  std::cout << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>// Time:  seat:  O(logn),
//        leave: O(logn)
// Space: O(n)

class ExamRoom {
public:
    ExamRoom(int N) : num_(N) {
        max_heap.emplace(new Segment(-1, num_, num_, 0));
        neighbors[-1] = make_pair(-1, num_);
        neighbors[num_] = make_pair(-1, num_);
    }

    int seat() {
        while (!neighbors.count(max_heap.top()->l) ||
               !neighbors.count(max_heap.top()->r) ||
               neighbors.count(max_heap.top()->pos)) {
            max_heap.pop();  // lazy deletion
        }
        const auto curr = max_heap.top(); max_heap.pop();
        if (curr->l == -1 && curr->r == num_) {
            max_heap.emplace(
                new Segment(curr->l + 1, curr->r,
                            curr->r - 1,
                            curr->r - 1));
            neighbors[curr->l + 1] = make_pair(curr->l, curr->r);
        } else if (curr->l == -1) {
            max_heap.emplace(
                new Segment(curr->l + 1, curr->r,
                            curr->r / 2,
                            curr->r / 2));
            neighbors[curr->l + 1] = make_pair(curr->l, curr->r);
            neighbors[curr->r].first = curr->l + 1;
        } else if (curr->r == num_) {
            max_heap.emplace(
                new Segment(curr->l, curr->r - 1,
                            (curr->r - 1 - curr->l) / 2,
                            (curr->r - 1 - curr->l) / 2 + curr->l));
            neighbors[curr->r - 1] = make_pair(curr->l, curr->r);
            neighbors[curr->l].second = curr->r - 1;
        } else {
            max_heap.emplace(
                new Segment(curr->l, curr->pos,
                            (curr->pos - curr->l) / 2,
                            (curr->pos - curr->l) / 2 + curr->l));
            max_heap.emplace(
                new Segment(curr->pos, curr->r,
                            (curr->r - curr->pos) / 2,
                            (curr->r - curr->pos) / 2 + curr->pos));
            neighbors[curr->pos] = make_pair(curr->l, curr->r);
            neighbors[curr->l].second = curr->pos;
            neighbors[curr->r].first = curr->pos;
        }
        return curr->pos;
    }

    void leave(int p) {
        const auto nei = neighbors[p];
        neighbors.erase(p);
        if (nei.first == -1 && nei.second == num_) {
            max_heap.emplace(
                new Segment(nei.first, nei.second,
                            nei.second,
                            nei.first + 1));
        } else if (nei.first == -1) {
            max_heap.emplace(
                new Segment(nei.first, nei.second,
                            nei.second,
                            nei.first + 1));
            neighbors[nei.second].first = -1;
        } else if (nei.second == num_) {
            max_heap.emplace(
                new Segment(nei.first, nei.second,
                            nei.second - 1 - nei.first,
                            nei.second - 1));
            neighbors[nei.first].second = nei.second;
        } else {
            max_heap.emplace(
                new Segment(nei.first, nei.second,
                            (nei.second - nei.first) / 2,
                            (nei.second - nei.first) / 2 + nei.first));
            neighbors[nei.first].second = nei.second;
            neighbors[nei.second].first = nei.first;
        }
    }

private:
    struct Segment {
        int l;
        int r;
        int dis;
        int pos;
        Segment(int l, int r, int dis, int pos) :
            l(l), r(r), dis(dis), pos(pos) {
        }
    };

    using S = shared_ptr<Segment>;
    struct Compare {
        bool operator()(const S& a, const S& b) {
            return a->dis == b->dis ?
                greater<int>()(a->l, b->l) :
                less<int>()(a->dis, b->dis);
        }
    };

    int num_;
    priority_queue<S, vector<S>, Compare> max_heap;
    unordered_map<int, pair<int, int>> neighbors;
};

/**
 * Your ExamRoom object will be instantiated and called as such:
 * ExamRoom obj = new ExamRoom(N);
 * int param_1 = obj.seat();
 * obj.leave(p);
 */
<commit_msg>Update exam-room.cpp<commit_after>// Time:  seat:  O(logn),
//        leave: O(logn)
// Space: O(n)

class ExamRoom {
public:
    ExamRoom(int N) : num_(N) {
        max_heap.emplace(make_shared<Segment>(-1, num_, num_, 0));
        neighbors[-1] = make_pair(-1, num_);
        neighbors[num_] = make_pair(-1, num_);
    }

    int seat() {
        while (!neighbors.count(max_heap.top()->l) ||
               !neighbors.count(max_heap.top()->r) ||
               neighbors.count(max_heap.top()->pos)) {
            max_heap.pop();  // lazy deletion
        }
        const auto curr = max_heap.top(); max_heap.pop();
        if (curr->l == -1 && curr->r == num_) {
            max_heap.emplace(
                make_shared<Segment>(curr->l + 1, curr->r,
                                     curr->r - 1,
                                     curr->r - 1));
            neighbors[curr->l + 1] = make_pair(curr->l, curr->r);
        } else if (curr->l == -1) {
            max_heap.emplace(
                make_shared<Segment>(curr->l + 1, curr->r,
                                    curr->r / 2,
                                    curr->r / 2));
            neighbors[curr->l + 1] = make_pair(curr->l, curr->r);
            neighbors[curr->r].first = curr->l + 1;
        } else if (curr->r == num_) {
            max_heap.emplace(
                make_shared<Segment>(curr->l, curr->r - 1,
                                    (curr->r - 1 - curr->l) / 2,
                                    (curr->r - 1 - curr->l) / 2 + curr->l));
            neighbors[curr->r - 1] = make_pair(curr->l, curr->r);
            neighbors[curr->l].second = curr->r - 1;
        } else {
            max_heap.emplace(
                make_shared<Segment>(curr->l, curr->pos,
                                    (curr->pos - curr->l) / 2,
                                    (curr->pos - curr->l) / 2 + curr->l));
            max_heap.emplace(
                make_shared<Segment>(curr->pos, curr->r,
                                    (curr->r - curr->pos) / 2,
                                    (curr->r - curr->pos) / 2 + curr->pos));
            neighbors[curr->pos] = make_pair(curr->l, curr->r);
            neighbors[curr->l].second = curr->pos;
            neighbors[curr->r].first = curr->pos;
        }
        return curr->pos;
    }

    void leave(int p) {
        const auto nei = neighbors[p];
        neighbors.erase(p);
        if (nei.first == -1 && nei.second == num_) {
            max_heap.emplace(
                make_shared<Segment>(nei.first, nei.second,
                                    nei.second,
                                    nei.first + 1));
        } else if (nei.first == -1) {
            max_heap.emplace(
                make_shared<Segment>(nei.first, nei.second,
                                     nei.second,
                                     nei.first + 1));
            neighbors[nei.second].first = -1;
        } else if (nei.second == num_) {
            max_heap.emplace(
                make_shared<Segment>(nei.first, nei.second,
                                     nei.second - 1 - nei.first,
                                     nei.second - 1));
            neighbors[nei.first].second = nei.second;
        } else {
            max_heap.emplace(
                make_shared<Segment>(nei.first, nei.second,
                                     (nei.second - nei.first) / 2,
                                     (nei.second - nei.first) / 2 + nei.first));
            neighbors[nei.first].second = nei.second;
            neighbors[nei.second].first = nei.first;
        }
    }

private:
    struct Segment {
        int l;
        int r;
        int dis;
        int pos;
        Segment(int l, int r, int dis, int pos) :
            l(l), r(r), dis(dis), pos(pos) {
        }
    };

    using S = shared_ptr<Segment>;
    struct Compare {
        bool operator()(const S& a, const S& b) {
            return a->dis == b->dis ?
                greater<int>()(a->l, b->l) :
                less<int>()(a->dis, b->dis);
        }
    };

    int num_;
    priority_queue<S, vector<S>, Compare> max_heap;
    unordered_map<int, pair<int, int>> neighbors;
};

/**
 * Your ExamRoom object will be instantiated and called as such:
 * ExamRoom obj = new ExamRoom(N);
 * int param_1 = obj.seat();
 * obj.leave(p);
 */
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <string>
#include <utility>

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "mlir/IR/AsmState.h"  // from @llvm-project
#include "mlir/IR/BuiltinOps.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/Pass/PassManager.h"  // from @llvm-project
#include "mlir/Pass/PassRegistry.h"  // from @llvm-project
#include "mlir/Transforms/Passes.h"  // from @llvm-project
#include "tensorflow/compiler/mlir/init_mlir.h"
#include "tensorflow/compiler/mlir/tensorflow/dialect_registration.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"
#include "tensorflow/core/ir/importexport/export.h"
#include "tensorflow/core/ir/importexport/import.h"
#include "tensorflow/core/ir/ops.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/core/transforms/pass_registration.h"
#include "tensorflow/tools/tfg_graph_transforms/utils.h"

namespace {

llvm::cl::OptionCategory tfg_graph_transform_category(
    "TFG graph transform options");

// NOLINTNEXTLINE
llvm::cl::opt<std::string> input_file(
    llvm::cl::Positional, llvm::cl::desc("<Input model>"),
    llvm::cl::value_desc("Full path to the input model"),
    llvm::cl::cat(tfg_graph_transform_category), llvm::cl::Required);

// NOLINTNEXTLINE
llvm::cl::opt<std::string> output_file(
    "o", llvm::cl::desc("Output model"),
    llvm::cl::value_desc("Full path to the output model"),
    llvm::cl::cat(tfg_graph_transform_category), llvm::cl::Required);

enum class DataFormat { SavedModel = 0, GraphDef = 1 };

// NOLINTNEXTLINE
llvm::cl::opt<DataFormat> data_format(
    "data_format",
    llvm::cl::desc(
        "Data format for both input and output, e.g., SavedModel or GraphDef"),
    values(clEnumValN(DataFormat::SavedModel, "savedmodel",
                      "SavedModel format"),
           clEnumValN(DataFormat::GraphDef, "graphdef", "GraphDef format")),
    llvm::cl::init(DataFormat::SavedModel),
    llvm::cl::cat(tfg_graph_transform_category));

// Validate CL options and returns false in case of an error.
bool CheckCLParams() {
  if (input_file == output_file) {
    LOG(WARNING)
        << "Input and output files are set to the same location. "
           "The resulted model protobuf will overwrite the original one.\n";
  }
  if (!tensorflow::Env::Default()->FileExists(input_file).ok()) {
    LOG(ERROR) << "Provided file or directory does not exist: '" << input_file
               << "'\n";
    return false;
  }

  if (tensorflow::Env::Default()->IsDirectory(input_file).ok()) {
    LOG(ERROR)
        << "Expected full path to the model protobuf file, given directory: '"
        << input_file << "'\n";
    return false;
  }

  return true;
}

void RegisterDialects(mlir::DialectRegistry& registry) {
  // This potentially could be limited, for now keep all TF.
  mlir::RegisterAllTensorFlowDialects(registry);
}

tensorflow::Status RunOptimizationPasses(
    const mlir::PassPipelineCLParser& passPipeline, mlir::ModuleOp module,
    mlir::MLIRContext* context) {
  mlir::PassManager pm(context);
  auto error_handler = [&](const llvm::Twine& msg) {
    emitError(mlir::UnknownLoc::get(pm.getContext())) << msg;
    return mlir::failure();
  };
  if (failed(passPipeline.addToPipeline(pm, error_handler))) {
    return tensorflow::errors::InvalidArgument(
        "Pipeline initialization failed");
  }

  mlir::StatusScopedDiagnosticHandler diagnostics_handler(context);
  if (failed(pm.run(module))) {
    return diagnostics_handler.Combine(
        tensorflow::errors::InvalidArgument("MLIR Pass Manager failure: "));
  }

  return diagnostics_handler.ConsumeStatus();
}

// Import model to the TFG MLIR module.
tensorflow::StatusOr<mlir::OwningOpRef<mlir::ModuleOp>> ImportModel(
    DataFormat data_format, const std::string& input_file,
    mlir::MLIRContext* mlir_context) {
  tensorflow::GraphDebugInfo debug_info;

  switch (data_format) {
    case DataFormat::SavedModel: {
      tensorflow::SavedModel saved_model;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::SavedModel>(
              input_file, saved_model));
      return mlir::tfg::ImportSavedModelToMlir(mlir_context, debug_info,
                                               saved_model);
    }
    case DataFormat::GraphDef: {
      tensorflow::GraphDef graph_def;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::GraphDef>(
              input_file, graph_def));
      return mlir::tfg::ImportGraphDefToMlir(mlir_context, debug_info,
                                             graph_def);
    }
  }
}

tensorflow::Status ExportTFGModule(mlir::ModuleOp module_op,
                                   DataFormat data_format,
                                   const std::string& input_file,
                                   const std::string& output_file) {
  switch (data_format) {
    case DataFormat::SavedModel: {
      tensorflow::SavedModel original_saved_model;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::SavedModel>(
              input_file, original_saved_model));
      tensorflow::SavedModel final_saved_model;

      TF_RETURN_WITH_CONTEXT_IF_ERROR(
          tensorflow::ExportMlirToSavedModel(module_op, original_saved_model,
                                             &final_saved_model),
          "while converting TFG to SavedModel");

      VLOG(1) << "Serializing resulting SavedModel to " << output_file;
      return mlir::tfg::graph_transforms::SerializeProto<
          tensorflow::SavedModel>(final_saved_model, output_file);
    }
    case DataFormat::GraphDef: {
      tensorflow::GraphDef new_graphdef;
      TF_RETURN_WITH_CONTEXT_IF_ERROR(
          tensorflow::ExportMlirToGraphdef(module_op, &new_graphdef),
          "while converting TFG to GraphDef");

      VLOG(1) << "Serializing resulting GraphDef to " << output_file;
      return mlir::tfg::graph_transforms::SerializeProto<tensorflow::GraphDef>(
          new_graphdef, output_file);
    }
  }
}

}  // namespace

int main(int argc, char** argv) {
  tensorflow::InitMlir y(&argc, &argv);
  mlir::registerAsmPrinterCLOptions();
  mlir::registerMLIRContextCLOptions();
  mlir::registerPassManagerCLOptions();
  mlir::tfg::registerTFGraphPasses();
  mlir::registerSymbolPrivatizePass();
  mlir::registerSymbolDCEPass();

  mlir::PassPipelineCLParser pass_pipeline("", "TFG passes to run");
  llvm::cl::ParseCommandLineOptions(argc, argv, "TFG optimization tool\n");

  if (!CheckCLParams()) {
    LOG(QFATAL) << "Command line parameters are invalid";
  }

  mlir::DialectRegistry registry;
  RegisterDialects(registry);
  mlir::MLIRContext context(registry);

  // Import model to the TFG MLIR module.
  auto module_ref_status = ImportModel(data_format, input_file, &context);

  if (!module_ref_status.ok()) {
    LOG(QFATAL) << "Model import failed: "
                << module_ref_status.status().ToString();
  }
  auto module_ref = std::move(module_ref_status.ValueOrDie());

  // Parse the optimization pipeline configuration and run requested graph
  // optimizations.
  tensorflow::Status pass_pipeline_status =
      RunOptimizationPasses(pass_pipeline, *module_ref, &context);
  if (!pass_pipeline_status.ok()) {
    LOG(QFATAL) << pass_pipeline_status.ToString() << "\n";
  }

  // Export MLIR TFG module to the resulting model proto.
  tensorflow::Status export_status =
      ExportTFGModule(*module_ref, data_format, input_file, output_file);

  if (!export_status.ok()) {
    LOG(QFATAL) << "Export of TFG module failed: " << export_status.ToString()
                << "\n";
  }

  return EXIT_SUCCESS;
}
<commit_msg>[tools] Apply MLIR pass manager CL options.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <string>
#include <utility>

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "mlir/IR/AsmState.h"  // from @llvm-project
#include "mlir/IR/BuiltinOps.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/Pass/PassManager.h"  // from @llvm-project
#include "mlir/Pass/PassRegistry.h"  // from @llvm-project
#include "mlir/Transforms/Passes.h"  // from @llvm-project
#include "tensorflow/compiler/mlir/init_mlir.h"
#include "tensorflow/compiler/mlir/tensorflow/dialect_registration.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"
#include "tensorflow/core/ir/importexport/export.h"
#include "tensorflow/core/ir/importexport/import.h"
#include "tensorflow/core/ir/ops.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/core/transforms/pass_registration.h"
#include "tensorflow/tools/tfg_graph_transforms/utils.h"

namespace {

llvm::cl::OptionCategory tfg_graph_transform_category(
    "TFG graph transform options");

// NOLINTNEXTLINE
llvm::cl::opt<std::string> input_file(
    llvm::cl::Positional, llvm::cl::desc("<Input model>"),
    llvm::cl::value_desc("Full path to the input model"),
    llvm::cl::cat(tfg_graph_transform_category), llvm::cl::Required);

// NOLINTNEXTLINE
llvm::cl::opt<std::string> output_file(
    "o", llvm::cl::desc("Output model"),
    llvm::cl::value_desc("Full path to the output model"),
    llvm::cl::cat(tfg_graph_transform_category), llvm::cl::Required);

enum class DataFormat { SavedModel = 0, GraphDef = 1 };

// NOLINTNEXTLINE
llvm::cl::opt<DataFormat> data_format(
    "data_format",
    llvm::cl::desc(
        "Data format for both input and output, e.g., SavedModel or GraphDef"),
    values(clEnumValN(DataFormat::SavedModel, "savedmodel",
                      "SavedModel format"),
           clEnumValN(DataFormat::GraphDef, "graphdef", "GraphDef format")),
    llvm::cl::init(DataFormat::SavedModel),
    llvm::cl::cat(tfg_graph_transform_category));

// Validate CL options and returns false in case of an error.
bool CheckCLParams() {
  if (input_file == output_file) {
    LOG(WARNING)
        << "Input and output files are set to the same location. "
           "The resulted model protobuf will overwrite the original one.\n";
  }
  if (!tensorflow::Env::Default()->FileExists(input_file).ok()) {
    LOG(ERROR) << "Provided file or directory does not exist: '" << input_file
               << "'\n";
    return false;
  }

  if (tensorflow::Env::Default()->IsDirectory(input_file).ok()) {
    LOG(ERROR)
        << "Expected full path to the model protobuf file, given directory: '"
        << input_file << "'\n";
    return false;
  }

  return true;
}

void RegisterDialects(mlir::DialectRegistry& registry) {
  // This potentially could be limited, for now keep all TF.
  mlir::RegisterAllTensorFlowDialects(registry);
}

tensorflow::Status RunOptimizationPasses(
    const mlir::PassPipelineCLParser& passPipeline, mlir::ModuleOp module,
    mlir::MLIRContext* context) {
  mlir::PassManager pm(context);
  mlir::applyPassManagerCLOptions(pm);

  auto error_handler = [&](const llvm::Twine& msg) {
    emitError(mlir::UnknownLoc::get(pm.getContext())) << msg;
    return mlir::failure();
  };
  if (failed(passPipeline.addToPipeline(pm, error_handler))) {
    return tensorflow::errors::InvalidArgument(
        "Pipeline initialization failed");
  }

  mlir::StatusScopedDiagnosticHandler diagnostics_handler(context);
  if (failed(pm.run(module))) {
    return diagnostics_handler.Combine(
        tensorflow::errors::InvalidArgument("MLIR Pass Manager failure: "));
  }

  return diagnostics_handler.ConsumeStatus();
}

// Import model to the TFG MLIR module.
tensorflow::StatusOr<mlir::OwningOpRef<mlir::ModuleOp>> ImportModel(
    DataFormat data_format, const std::string& input_file,
    mlir::MLIRContext* mlir_context) {
  tensorflow::GraphDebugInfo debug_info;

  switch (data_format) {
    case DataFormat::SavedModel: {
      tensorflow::SavedModel saved_model;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::SavedModel>(
              input_file, saved_model));
      return mlir::tfg::ImportSavedModelToMlir(mlir_context, debug_info,
                                               saved_model);
    }
    case DataFormat::GraphDef: {
      tensorflow::GraphDef graph_def;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::GraphDef>(
              input_file, graph_def));
      return mlir::tfg::ImportGraphDefToMlir(mlir_context, debug_info,
                                             graph_def);
    }
  }
}

tensorflow::Status ExportTFGModule(mlir::ModuleOp module_op,
                                   DataFormat data_format,
                                   const std::string& input_file,
                                   const std::string& output_file) {
  switch (data_format) {
    case DataFormat::SavedModel: {
      tensorflow::SavedModel original_saved_model;
      TF_RETURN_IF_ERROR(
          mlir::tfg::graph_transforms::ReadModelProto<tensorflow::SavedModel>(
              input_file, original_saved_model));
      tensorflow::SavedModel final_saved_model;

      TF_RETURN_WITH_CONTEXT_IF_ERROR(
          tensorflow::ExportMlirToSavedModel(module_op, original_saved_model,
                                             &final_saved_model),
          "while converting TFG to SavedModel");

      VLOG(1) << "Serializing resulting SavedModel to " << output_file;
      return mlir::tfg::graph_transforms::SerializeProto<
          tensorflow::SavedModel>(final_saved_model, output_file);
    }
    case DataFormat::GraphDef: {
      tensorflow::GraphDef new_graphdef;
      TF_RETURN_WITH_CONTEXT_IF_ERROR(
          tensorflow::ExportMlirToGraphdef(module_op, &new_graphdef),
          "while converting TFG to GraphDef");

      VLOG(1) << "Serializing resulting GraphDef to " << output_file;
      return mlir::tfg::graph_transforms::SerializeProto<tensorflow::GraphDef>(
          new_graphdef, output_file);
    }
  }
}

}  // namespace

int main(int argc, char** argv) {
  tensorflow::InitMlir y(&argc, &argv);
  mlir::registerAsmPrinterCLOptions();
  mlir::registerMLIRContextCLOptions();
  mlir::registerPassManagerCLOptions();
  mlir::tfg::registerTFGraphPasses();
  mlir::registerSymbolPrivatizePass();
  mlir::registerSymbolDCEPass();

  mlir::PassPipelineCLParser pass_pipeline("", "TFG passes to run");
  llvm::cl::ParseCommandLineOptions(argc, argv, "TFG optimization tool\n");

  if (!CheckCLParams()) {
    LOG(QFATAL) << "Command line parameters are invalid";
  }

  mlir::DialectRegistry registry;
  RegisterDialects(registry);
  mlir::MLIRContext context(registry);

  // Import model to the TFG MLIR module.
  auto module_ref_status = ImportModel(data_format, input_file, &context);

  if (!module_ref_status.ok()) {
    LOG(QFATAL) << "Model import failed: "
                << module_ref_status.status().ToString();
  }
  auto module_ref = std::move(module_ref_status.ValueOrDie());

  // Parse the optimization pipeline configuration and run requested graph
  // optimizations.
  tensorflow::Status pass_pipeline_status =
      RunOptimizationPasses(pass_pipeline, *module_ref, &context);
  if (!pass_pipeline_status.ok()) {
    LOG(QFATAL) << pass_pipeline_status.ToString() << "\n";
  }

  // Export MLIR TFG module to the resulting model proto.
  tensorflow::Status export_status =
      ExportTFGModule(*module_ref, data_format, input_file, output_file);

  if (!export_status.ok()) {
    LOG(QFATAL) << "Export of TFG module failed: " << export_status.ToString()
                << "\n";
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Records For Living, Inc. 2004-2011.  All rights reserved
 */
#include	"Stroika/Foundation/StroikaPreComp.h"

#include	<iostream>
#include	<sstream>

#include	"Stroika/Foundation/Execution/CriticalSection.h"
#include	"Stroika/Foundation/Execution/Event.h"
#include	"Stroika/Foundation/Execution/Lockable.h"
#include	"Stroika/Foundation/Execution/Sleep.h"
#include	"Stroika/Foundation/Execution/SimpleRunnable.h"
#include	"Stroika/Foundation/Execution/Thread.h"
#include	"Stroika/Foundation/Execution/ThreadPool.h"
#include	"Stroika/Foundation/Execution/WaitTimedOutException.h"

#include	"../TestHarness/TestHarness.h"

using	namespace	Stroika::Foundation;

using	Execution::CriticalSection;
using	Execution::Lockable;
using	Execution::AutoCriticalSection;
using	Execution::SimpleRunnable;
using	Execution::Thread;
using	Execution::ThreadPool;

namespace	{
	void	RegressionTest1_ ()
		{
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						for (int i = 1; i < 10; i++) {
							Execution::Sleep (.1);
						}
					}
			};

			Thread	thread (&FRED::DoIt, const_cast<char*> ("foo"));
			thread.Start ();
			thread.WaitForDone ();
		}
}

namespace	{
	CriticalSection	sharedCriticalSection_;
	void	RegressionTest2_ ()
		{

			// Make 2 concurrent threads, which share a critical section object to take turns updating a variable
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							AutoCriticalSection	critSect (sharedCriticalSection_);
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
							*argP = tmp + 1;
						}
					}
			};

			int	updaterValue	=	0;
			Thread	thread1 (&FRED::DoIt, &updaterValue);
			Thread	thread2 (&FRED::DoIt, &updaterValue);
			thread1.Start ();
			thread2.Start ();
			thread1.WaitForDone ();
			thread2.WaitForDone ();
			VerifyTestResult (updaterValue == 2 * 10);
		}
}

namespace	{
	Execution::Event	sRegTest3Event_T1_;
	Execution::Event	sRegTest3Event_T2_;
	void	RegressionTest3_ ()
		{

			// Make 2 concurrent threads, which share a critical section object to take turns updating a variable
			struct	FRED1 {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							sRegTest3Event_T1_.Wait ();
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("FRED1: Updating value in of %d", tmp);
							*argP = tmp + 1;
							sRegTest3Event_T2_.Set ();
						}
					}
			};
			struct	FRED2 {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							sRegTest3Event_T2_.Wait ();
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("FRED2: Updating value in of %d", tmp);
							*argP = tmp + 1;
							sRegTest3Event_T1_.Set ();
						}
					}
			};

			sRegTest3Event_T1_.Reset ();
			sRegTest3Event_T2_.Reset ();
			int	updaterValue	=	0;
			Thread	thread1 (&FRED1::DoIt, &updaterValue);
			Thread	thread2 (&FRED2::DoIt, &updaterValue);
			thread1.Start ();
			thread2.Start ();
			sRegTest3Event_T1_.Set ();
			thread1.WaitForDone ();
			thread2.WaitForDone ();
			//DbgTrace ("Test3 - updaterValue = %d", updaterValue);
			VerifyTestResult (updaterValue == 2 * 10);
		}
}

namespace	{
	struct	data_ {};
	void	RegressionTest4_Lockable_ ()
		{
			{
				Lockable<data_>	x;
				Lockable<data_>	y = data_ ();
				x = data_ ();
			}
			{
				Lockable<int>	x;
				Lockable<int>	y = 3;
				x = 4;
			}
			{
				// Make 2 concurrent threads, which update a lockable variable
				struct	FRED {
					static	void	DoIt (void* ignored)
						{
							Lockable<int>*	argP	=	reinterpret_cast<Lockable<int>*> (ignored);
							for (int i = 0; i < 10; i++) {
								AutoCriticalSection	critSect (*argP);
								int	tmp = *argP;
								Execution::Sleep (.01);
								//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
								*argP = tmp + 1;
							}
						}
				};
				Lockable<int>	updaterValue	=	0;
				Thread	thread1 (&FRED::DoIt, &updaterValue);
				Thread	thread2 (&FRED::DoIt, &updaterValue);
				thread1.Start ();
				thread2.Start ();
				thread1.WaitForDone ();
				thread2.WaitForDone ();
				VerifyTestResult (updaterValue == 2 * 10);
			}
		}
}

namespace	{
	void	RegressionTest5_Aborting_ ()
		{
			struct	FRED {
				static	void	DoIt ()
					{
						while (true) {
							Execution::CheckForThreadAborting ();
						}
					}
			};
			Thread	thread (&FRED::DoIt);
			thread.Start ();
			try {
				thread.WaitForDone (1.0);	// should timeout
				VerifyTestResult (false);
			}
			catch (const Execution::WaitTimedOutException&) {
				// GOOD
			}
			catch (...) {
				VerifyTestResult (false);
			}
			// Now - abort it, and wait
			thread.AbortAndWaitForDone ();
		}
}

namespace	{
	void	RegressionTest6_ThreadWaiting_ ()
		{
			struct	FRED {
				static	void	DoIt ()
					{
						Execution::Sleep (1.0);
					}
			};

			// Normal usage
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
				thread.WaitForDone ();
			}

			// OK to never wait
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
			}

			// OK to wait and wait
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
				thread.WaitForDone ();
				thread.WaitForDone (1.0);
				thread.WaitForDone ();
				thread.WaitForDone ();
			}
		}
}

namespace	{
	void	RegressionTest7_SimpleThreadPool_ ()
		{
			{
				ThreadPool	p;
				p.SetPoolSize (1);
				p.Abort ();
				p.WaitForDone ();
			}
			{
				ThreadPool	p;
				p.SetPoolSize (1);
				struct	FRED {
					static	void	DoIt (void* arg)
						{
							int*	p	=	reinterpret_cast<int*> (arg);
							(*p)++;
						}
				};
				int	intVal	=	3;
				Memory::SharedPtr<Execution::IRunnable>	task	=	SimpleRunnable::MAKE (FRED::DoIt, &intVal);
				p.AddTask (task);
				p.WaitForTask (task);
				p.AbortAndWaitForDone ();
				VerifyTestResult (intVal == 4);
			}
		}
}

namespace	{
	void	RegressionTest8_ThreadPool_ ()
		{
			// Make 2 concurrent tasks, which share a critical section object to take turns updating a variable
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							AutoCriticalSection	critSect (sharedCriticalSection_);
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
							*argP = tmp + 1;
						}
					}
			};

			for (unsigned int threadPoolSize = 1; threadPoolSize < 10; ++threadPoolSize) {
				ThreadPool	p;
				p.SetPoolSize (threadPoolSize);
				int	updaterValue	=	0;
				Memory::SharedPtr<Execution::IRunnable>	task1	=	SimpleRunnable::MAKE (&FRED::DoIt, &updaterValue);
				Memory::SharedPtr<Execution::IRunnable>	task2	=	SimpleRunnable::MAKE (&FRED::DoIt, &updaterValue);
				p.AddTask (task1);
				p.AddTask (task2);
				p.WaitForTask (task1);
				p.WaitForTask (task2);
				p.AbortAndWaitForDone ();
				VerifyTestResult (updaterValue == 2 * 10);
			}
		}
}

namespace	{

	void	DoRegressionTests_ ()
		{
			RegressionTest1_ ();
			RegressionTest2_ ();
			RegressionTest3_ ();
			RegressionTest4_Lockable_ ();
			RegressionTest5_Aborting_ ();
			RegressionTest6_ThreadWaiting_ ();
#if qPlatform_Windows
//tmphack disable test on posix til we have it working!
			RegressionTest7_SimpleThreadPool_ ();
			RegressionTest8_ThreadPool_ ();
#endif
		}
}

#if qOnlyOneMain
extern  int TestThreads ()
#else
int main (int argc, const char* argv[])
#endif
{
	Stroika::TestHarness::Setup ();
	Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
	return EXIT_SUCCESS;
}

<commit_msg>Enable ThreadPool automated tests on POSIX<commit_after>/*
 * Copyright(c) Records For Living, Inc. 2004-2011.  All rights reserved
 */
#include	"Stroika/Foundation/StroikaPreComp.h"

#include	<iostream>
#include	<sstream>

#include	"Stroika/Foundation/Execution/CriticalSection.h"
#include	"Stroika/Foundation/Execution/Event.h"
#include	"Stroika/Foundation/Execution/Lockable.h"
#include	"Stroika/Foundation/Execution/Sleep.h"
#include	"Stroika/Foundation/Execution/SimpleRunnable.h"
#include	"Stroika/Foundation/Execution/Thread.h"
#include	"Stroika/Foundation/Execution/ThreadPool.h"
#include	"Stroika/Foundation/Execution/WaitTimedOutException.h"

#include	"../TestHarness/TestHarness.h"

using	namespace	Stroika::Foundation;

using	Execution::CriticalSection;
using	Execution::Lockable;
using	Execution::AutoCriticalSection;
using	Execution::SimpleRunnable;
using	Execution::Thread;
using	Execution::ThreadPool;

namespace	{
	void	RegressionTest1_ ()
		{
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						for (int i = 1; i < 10; i++) {
							Execution::Sleep (.1);
						}
					}
			};

			Thread	thread (&FRED::DoIt, const_cast<char*> ("foo"));
			thread.Start ();
			thread.WaitForDone ();
		}
}

namespace	{
	CriticalSection	sharedCriticalSection_;
	void	RegressionTest2_ ()
		{

			// Make 2 concurrent threads, which share a critical section object to take turns updating a variable
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							AutoCriticalSection	critSect (sharedCriticalSection_);
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
							*argP = tmp + 1;
						}
					}
			};

			int	updaterValue	=	0;
			Thread	thread1 (&FRED::DoIt, &updaterValue);
			Thread	thread2 (&FRED::DoIt, &updaterValue);
			thread1.Start ();
			thread2.Start ();
			thread1.WaitForDone ();
			thread2.WaitForDone ();
			VerifyTestResult (updaterValue == 2 * 10);
		}
}

namespace	{
	Execution::Event	sRegTest3Event_T1_;
	Execution::Event	sRegTest3Event_T2_;
	void	RegressionTest3_ ()
		{

			// Make 2 concurrent threads, which share a critical section object to take turns updating a variable
			struct	FRED1 {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							sRegTest3Event_T1_.Wait ();
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("FRED1: Updating value in of %d", tmp);
							*argP = tmp + 1;
							sRegTest3Event_T2_.Set ();
						}
					}
			};
			struct	FRED2 {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							sRegTest3Event_T2_.Wait ();
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("FRED2: Updating value in of %d", tmp);
							*argP = tmp + 1;
							sRegTest3Event_T1_.Set ();
						}
					}
			};

			sRegTest3Event_T1_.Reset ();
			sRegTest3Event_T2_.Reset ();
			int	updaterValue	=	0;
			Thread	thread1 (&FRED1::DoIt, &updaterValue);
			Thread	thread2 (&FRED2::DoIt, &updaterValue);
			thread1.Start ();
			thread2.Start ();
			sRegTest3Event_T1_.Set ();
			thread1.WaitForDone ();
			thread2.WaitForDone ();
			//DbgTrace ("Test3 - updaterValue = %d", updaterValue);
			VerifyTestResult (updaterValue == 2 * 10);
		}
}

namespace	{
	struct	data_ {};
	void	RegressionTest4_Lockable_ ()
		{
			{
				Lockable<data_>	x;
				Lockable<data_>	y = data_ ();
				x = data_ ();
			}
			{
				Lockable<int>	x;
				Lockable<int>	y = 3;
				x = 4;
			}
			{
				// Make 2 concurrent threads, which update a lockable variable
				struct	FRED {
					static	void	DoIt (void* ignored)
						{
							Lockable<int>*	argP	=	reinterpret_cast<Lockable<int>*> (ignored);
							for (int i = 0; i < 10; i++) {
								AutoCriticalSection	critSect (*argP);
								int	tmp = *argP;
								Execution::Sleep (.01);
								//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
								*argP = tmp + 1;
							}
						}
				};
				Lockable<int>	updaterValue	=	0;
				Thread	thread1 (&FRED::DoIt, &updaterValue);
				Thread	thread2 (&FRED::DoIt, &updaterValue);
				thread1.Start ();
				thread2.Start ();
				thread1.WaitForDone ();
				thread2.WaitForDone ();
				VerifyTestResult (updaterValue == 2 * 10);
			}
		}
}

namespace	{
	void	RegressionTest5_Aborting_ ()
		{
			struct	FRED {
				static	void	DoIt ()
					{
						while (true) {
							Execution::CheckForThreadAborting ();
						}
					}
			};
			Thread	thread (&FRED::DoIt);
			thread.Start ();
			try {
				thread.WaitForDone (1.0);	// should timeout
				VerifyTestResult (false);
			}
			catch (const Execution::WaitTimedOutException&) {
				// GOOD
			}
			catch (...) {
				VerifyTestResult (false);
			}
			// Now - abort it, and wait
			thread.AbortAndWaitForDone ();
		}
}

namespace	{
	void	RegressionTest6_ThreadWaiting_ ()
		{
			struct	FRED {
				static	void	DoIt ()
					{
						Execution::Sleep (1.0);
					}
			};

			// Normal usage
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
				thread.WaitForDone ();
			}

			// OK to never wait
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
			}

			// OK to wait and wait
			{
				Thread	thread (&FRED::DoIt);
				thread.Start ();
				thread.WaitForDone ();
				thread.WaitForDone (1.0);
				thread.WaitForDone ();
				thread.WaitForDone ();
			}
		}
}

namespace	{
	void	RegressionTest7_SimpleThreadPool_ ()
		{
			{
				ThreadPool	p;
				p.SetPoolSize (1);
				p.Abort ();
				p.WaitForDone ();
			}
			{
				ThreadPool	p;
				p.SetPoolSize (1);
				struct	FRED {
					static	void	DoIt (void* arg)
						{
							int*	p	=	reinterpret_cast<int*> (arg);
							(*p)++;
						}
				};
				int	intVal	=	3;
				Memory::SharedPtr<Execution::IRunnable>	task	=	SimpleRunnable::MAKE (FRED::DoIt, &intVal);
				p.AddTask (task);
				p.WaitForTask (task);
				p.AbortAndWaitForDone ();
				VerifyTestResult (intVal == 4);
			}
		}
}

namespace	{
	void	RegressionTest8_ThreadPool_ ()
		{
			// Make 2 concurrent tasks, which share a critical section object to take turns updating a variable
			struct	FRED {
				static	void	DoIt (void* ignored)
					{
						int*	argP	=	reinterpret_cast<int*> (ignored);
						for (int i = 0; i < 10; i++) {
							AutoCriticalSection	critSect (sharedCriticalSection_);
							int	tmp = *argP;
							Execution::Sleep (.01);
							//DbgTrace ("Updating value in thread id %d", ::GetCurrentThreadId  ());
							*argP = tmp + 1;
						}
					}
			};

			for (unsigned int threadPoolSize = 1; threadPoolSize < 10; ++threadPoolSize) {
				ThreadPool	p;
				p.SetPoolSize (threadPoolSize);
				int	updaterValue	=	0;
				Memory::SharedPtr<Execution::IRunnable>	task1	=	SimpleRunnable::MAKE (&FRED::DoIt, &updaterValue);
				Memory::SharedPtr<Execution::IRunnable>	task2	=	SimpleRunnable::MAKE (&FRED::DoIt, &updaterValue);
				p.AddTask (task1);
				p.AddTask (task2);
				p.WaitForTask (task1);
				p.WaitForTask (task2);
				p.AbortAndWaitForDone ();
				VerifyTestResult (updaterValue == 2 * 10);
			}
		}
}

namespace	{

	void	DoRegressionTests_ ()
		{
			RegressionTest1_ ();
			RegressionTest2_ ();
			RegressionTest3_ ();
			RegressionTest4_Lockable_ ();
			RegressionTest5_Aborting_ ();
			RegressionTest6_ThreadWaiting_ ();
			RegressionTest7_SimpleThreadPool_ ();
			RegressionTest8_ThreadPool_ ();
		}
}

#if qOnlyOneMain
extern  int TestThreads ()
#else
int main (int argc, const char* argv[])
#endif
{
	Stroika::TestHarness::Setup ();
	Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "../common.h"

#include <cthun-client/connector/connector.hpp>  // Connector
#include <cthun-client/connector/errors.hpp>     // connection_config_error

#include <cthun-client/protocol/schemas.hpp>     // Protocol::

#include  <leatherman/json_container/json_container.hpp>  // JsonContainer

#include <string>
#include <iostream>
#include <memory>    // unique_ptr
#include <unistd.h>  // sleep

namespace Tutorial {

const std::string CA   { "../../resources/controller_certs/ca.pem" };
const std::string CERT { "../../resources/controller_certs/crt.pem" };
const std::string KEY  { "../../resources/controller_certs/key.pem" };

//
// controller_error
//

class controller_error : public std::runtime_error {
  public:
    explicit controller_error(std::string const& msg) : std::runtime_error(msg) {}
};

//
// Controller
//

class Controller {
  public:
    Controller();
    void sendRequests();

  private:
    int num_connect_attempts_;
    CthunClient::Schema response_schema_;
    CthunClient::Schema inventory_response_schema_;
    std::unique_ptr<CthunClient::Connector> connector_ptr_;

    void processResponse(const CthunClient::ParsedChunks& parsed_chunks);
    void processError(const CthunClient::ParsedChunks& parsed_chunks);
    void processInventoryResponse(const CthunClient::ParsedChunks& parsed_chunks);
};

Controller::Controller()
    try
        : num_connect_attempts_ { 2 },
          response_schema_ { getResponseMessageSchema() },
          inventory_response_schema_ {
                CthunClient::Protocol::InventoryResponseSchema() },
          connector_ptr_ { new CthunClient::Connector { SERVER_URL,
                                                        CONTROLLER_CLIENT_TYPE,
                                                        CA,
                                                        CERT,
                                                        KEY } } {
    // Connector::registerMessageCallback()

    connector_ptr_->registerMessageCallback(
        response_schema_,
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processResponse(parsed_chunks);
        });

    connector_ptr_->setCthunErrorCallback(
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processError(parsed_chunks);
        });

    connector_ptr_->registerMessageCallback(
        inventory_response_schema_,
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processInventoryResponse(parsed_chunks);
        });
} catch (CthunClient::connection_config_error& e) {
    std::string err_msg { "failed to configure the Cthun Connector: " };
    throw controller_error { err_msg + e.what() };
}

void Controller::sendRequests() {
    // Connector::connect()

    try {
        connector_ptr_->connect(num_connect_attempts_);
    } catch (CthunClient::connection_config_error& e) {
        std::string err_msg { "failed to configure WebSocket: " };
        throw controller_error { err_msg + e.what() };
    } catch (CthunClient::connection_fatal_error& e) {
        std::string err_msg { "failed to connect to " + SERVER_URL + " after "
                              + std::to_string(num_connect_attempts_)
                              + "attempts: " };
        throw controller_error { err_msg + e.what() };
    }

    // Connector::isConnected()

    if (connector_ptr_->isConnected()) {
        std::cout << "Successfully connected to " << SERVER_URL << "\n";
    } else {
        // The connection has dropped; we can't send anything
        throw controller_error { "connection dropped" };
    }

    // Send a valid request - a response is expected

    leatherman::json_container::JsonContainer track {
        "{\"artist\" : \"Captain Beefheart\"}" };
    leatherman::json_container::JsonContainer valid_request {};
    valid_request.set<leatherman::json_container::JsonContainer>("request", track);
    valid_request.set<std::string>("details", "please send some good music");

    std::vector<std::string> endpoints { "cth://*/" + AGENT_CLIENT_TYPE };

    try {
        connector_ptr_->send(endpoints,
                             REQUEST_SCHEMA_NAME,
                             MSG_TIMEOUT_S,
                             valid_request);
        std::cout << "Valid request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an invalid request - an error message should arrive

    leatherman::json_container::JsonContainer bad_json {
        "{\"genre\" : \"experimental rock\"}" };
    leatherman::json_container::JsonContainer bad_request {};
    bad_request.set<leatherman::json_container::JsonContainer>("request", bad_json);
    bad_request.set<std::string>("details", "I'm not sure about this");

    try {
        connector_ptr_->send(endpoints,
                             REQUEST_SCHEMA_NAME,
                             MSG_TIMEOUT_S,
                             bad_request);
        std::cout << "Bad request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an inventory request to the server

    leatherman::json_container::JsonContainer inventory_request {};
    std::vector<std::string> query { "cth://*/" + AGENT_CLIENT_TYPE };
    inventory_request.set<std::vector<std::string>>("query", query);

    // TODO(ale): use the complete server URI once we apply the specs

    try {
        connector_ptr_->send(std::vector<std::string> { "cth://server" },
                             CthunClient::Protocol::INVENTORY_REQ_TYPE,
                             MSG_TIMEOUT_S,
                             inventory_request);
        std::cout << "Inventory request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the inventory request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Wait for the response and error messages
    sleep(2);
}

void Controller::processResponse(const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto agent_endpoint = parsed_chunks.envelope.get<std::string>("sender");

    std::cout << "Received response " << response_id
              << " from " << agent_endpoint << ":\n  "
              << parsed_chunks.data.get<std::string>("response") << "\n";
}

void Controller::processError(const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto agent_endpoint = parsed_chunks.envelope.get<std::string>("sender");

    auto request_id = parsed_chunks.data.get<std::string>("id");
    auto error_description = parsed_chunks.data.get<std::string>("description");

    std::cout << "Received error " << response_id
              << " from " << agent_endpoint << " for request " << request_id
              <<  ":\n  " << error_description << "\n";
}

void Controller::processInventoryResponse(
            const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto server_endpoint = parsed_chunks.envelope.get<std::string>("sender");
    auto inventoried_nodes =
        parsed_chunks.data.get<std::vector<std::string>>("endpoints");

    std::cout << "Received inventory response " << response_id
              << " from " << server_endpoint << " -  number of nodes: "
              << inventoried_nodes.size();

    for (auto& node : inventoried_nodes) {
        std::cout << "\n  " << node;
    }

    std::cout << "\n";
}

//
// main
//

int main(int argc, char *argv[]) {
    try {
        Controller controller {};

        try {
            controller.sendRequests();
        } catch (controller_error& e) {
            std::cout << "Failed to process requests: " << e.what() << std::endl;
            return 2;
        }
    } catch (controller_error& e) {
        std::cout << "Failed to initialize the controller: " << e.what()
                  << std::endl;
        return 1;
    }

    return 0;
}

}  // namespace Tutorial

int main(int argc, char** argv) {
    return Tutorial::main(argc, argv);
}
<commit_msg>(maint) Update server URI in tutorial request<commit_after>#include "../common.h"

#include <cthun-client/connector/connector.hpp>  // Connector
#include <cthun-client/connector/errors.hpp>     // connection_config_error

#include <cthun-client/protocol/schemas.hpp>     // Protocol::

#include  <leatherman/json_container/json_container.hpp>  // JsonContainer

#include <string>
#include <iostream>
#include <memory>    // unique_ptr
#include <unistd.h>  // sleep

namespace Tutorial {

const std::string CA   { "../../resources/controller_certs/ca.pem" };
const std::string CERT { "../../resources/controller_certs/crt.pem" };
const std::string KEY  { "../../resources/controller_certs/key.pem" };

//
// controller_error
//

class controller_error : public std::runtime_error {
  public:
    explicit controller_error(std::string const& msg) : std::runtime_error(msg) {}
};

//
// Controller
//

class Controller {
  public:
    Controller();
    void sendRequests();

  private:
    int num_connect_attempts_;
    CthunClient::Schema response_schema_;
    CthunClient::Schema inventory_response_schema_;
    std::unique_ptr<CthunClient::Connector> connector_ptr_;

    void processResponse(const CthunClient::ParsedChunks& parsed_chunks);
    void processError(const CthunClient::ParsedChunks& parsed_chunks);
    void processInventoryResponse(const CthunClient::ParsedChunks& parsed_chunks);
};

Controller::Controller()
    try
        : num_connect_attempts_ { 2 },
          response_schema_ { getResponseMessageSchema() },
          inventory_response_schema_ {
                CthunClient::Protocol::InventoryResponseSchema() },
          connector_ptr_ { new CthunClient::Connector { SERVER_URL,
                                                        CONTROLLER_CLIENT_TYPE,
                                                        CA,
                                                        CERT,
                                                        KEY } } {
    // Connector::registerMessageCallback()

    connector_ptr_->registerMessageCallback(
        response_schema_,
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processResponse(parsed_chunks);
        });

    connector_ptr_->setCthunErrorCallback(
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processError(parsed_chunks);
        });

    connector_ptr_->registerMessageCallback(
        inventory_response_schema_,
        [this](const CthunClient::ParsedChunks& parsed_chunks) {
            processInventoryResponse(parsed_chunks);
        });
} catch (CthunClient::connection_config_error& e) {
    std::string err_msg { "failed to configure the Cthun Connector: " };
    throw controller_error { err_msg + e.what() };
}

void Controller::sendRequests() {
    // Connector::connect()

    try {
        connector_ptr_->connect(num_connect_attempts_);
    } catch (CthunClient::connection_config_error& e) {
        std::string err_msg { "failed to configure WebSocket: " };
        throw controller_error { err_msg + e.what() };
    } catch (CthunClient::connection_fatal_error& e) {
        std::string err_msg { "failed to connect to " + SERVER_URL + " after "
                              + std::to_string(num_connect_attempts_)
                              + "attempts: " };
        throw controller_error { err_msg + e.what() };
    }

    // Connector::isConnected()

    if (connector_ptr_->isConnected()) {
        std::cout << "Successfully connected to " << SERVER_URL << "\n";
    } else {
        // The connection has dropped; we can't send anything
        throw controller_error { "connection dropped" };
    }

    // Send a valid request - a response is expected

    leatherman::json_container::JsonContainer track {
        "{\"artist\" : \"Captain Beefheart\"}" };
    leatherman::json_container::JsonContainer valid_request {};
    valid_request.set<leatherman::json_container::JsonContainer>("request", track);
    valid_request.set<std::string>("details", "please send some good music");

    std::vector<std::string> endpoints { "cth://*/" + AGENT_CLIENT_TYPE };

    try {
        connector_ptr_->send(endpoints,
                             REQUEST_SCHEMA_NAME,
                             MSG_TIMEOUT_S,
                             valid_request);
        std::cout << "Valid request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an invalid request - an error message should arrive

    leatherman::json_container::JsonContainer bad_json {
        "{\"genre\" : \"experimental rock\"}" };
    leatherman::json_container::JsonContainer bad_request {};
    bad_request.set<leatherman::json_container::JsonContainer>("request", bad_json);
    bad_request.set<std::string>("details", "I'm not sure about this");

    try {
        connector_ptr_->send(endpoints,
                             REQUEST_SCHEMA_NAME,
                             MSG_TIMEOUT_S,
                             bad_request);
        std::cout << "Bad request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an inventory request to the server

    leatherman::json_container::JsonContainer inventory_request {};
    std::vector<std::string> query { "cth://*/" + AGENT_CLIENT_TYPE };
    inventory_request.set<std::vector<std::string>>("query", query);

    // TODO(ale): use the complete server URI once we apply the specs

    try {
        // NB: use "cth:///server" with 3 '/' as the server URI
        connector_ptr_->send(std::vector<std::string> { "cth:///server" },
                             CthunClient::Protocol::INVENTORY_REQ_TYPE,
                             MSG_TIMEOUT_S,
                             inventory_request);
        std::cout << "Inventory request message sent\n";
    } catch (CthunClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the inventory request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Wait for the response and error messages
    sleep(2);
}

void Controller::processResponse(const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto agent_endpoint = parsed_chunks.envelope.get<std::string>("sender");

    std::cout << "Received response " << response_id
              << " from " << agent_endpoint << ":\n  "
              << parsed_chunks.data.get<std::string>("response") << "\n";
}

void Controller::processError(const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto agent_endpoint = parsed_chunks.envelope.get<std::string>("sender");

    auto request_id = parsed_chunks.data.get<std::string>("id");
    auto error_description = parsed_chunks.data.get<std::string>("description");

    std::cout << "Received error " << response_id
              << " from " << agent_endpoint << " for request " << request_id
              <<  ":\n  " << error_description << "\n";
}

void Controller::processInventoryResponse(
            const CthunClient::ParsedChunks& parsed_chunks) {
    auto response_id = parsed_chunks.envelope.get<std::string>("id");
    auto server_endpoint = parsed_chunks.envelope.get<std::string>("sender");
    auto inventoried_nodes =
        parsed_chunks.data.get<std::vector<std::string>>("endpoints");

    std::cout << "Received inventory response " << response_id
              << " from " << server_endpoint << " -  number of nodes: "
              << inventoried_nodes.size();

    for (auto& node : inventoried_nodes) {
        std::cout << "\n  " << node;
    }

    std::cout << "\n";
}

//
// main
//

int main(int argc, char *argv[]) {
    try {
        Controller controller {};

        try {
            controller.sendRequests();
        } catch (controller_error& e) {
            std::cout << "Failed to process requests: " << e.what() << std::endl;
            return 2;
        }
    } catch (controller_error& e) {
        std::cout << "Failed to initialize the controller: " << e.what()
                  << std::endl;
        return 1;
    }

    return 0;
}

}  // namespace Tutorial

int main(int argc, char** argv) {
    return Tutorial::main(argc, argv);
}
<|endoftext|>


<commit_before>#include "ArgumentParser.h"

static const unsigned LINEWIDTH=160;

ArgumentParser::ArgumentParser(int argc, char** argv){
  m_argc=argc;
  m_argv=argv;
  m_brief="";
  m_desc=new po::options_description("General options",LINEWIDTH,LINEWIDTH/2);
  m_optional=new po::options_description("Experimental and legacy options",LINEWIDTH,LINEWIDTH/2);
  m_desc->add_options()("help,h","display brief help");
  m_desc->add_options()("experimental","display full help, including experimental and deprecated options");

}

ArgumentParser::ArgumentParser(){
  m_argc=0; m_argv=NULL;
  m_brief="";
  m_desc=new po::options_description("General options",LINEWIDTH,LINEWIDTH/2);
  m_optional=new po::options_description("Experimental and legacy options",LINEWIDTH,LINEWIDTH/2);
  m_desc->add_options()("help,h","display brief help");
  m_desc->add_options()("experimental","display full help, including experimental and deprecated options");
}
void ArgumentParser::option(const char * opt, bool & variable, const char * descr, bool optional){
  if (!optional){
    m_desc->add_options()
      (opt,po::bool_switch(&variable) ,descr) ;
  }else{
    m_optional->add_options()
      (opt,po::bool_switch(&variable) ,descr) ;
  }
}

bool ArgumentParser::parse(){
  std::string appName = boost::filesystem::basename(m_argv[0]);
  po::variables_map vm;
  po::options_description all("Allowed options",LINEWIDTH);
  all.add(*m_desc);
  all.add(*m_optional);

  try
    {
      po::store(po::parse_command_line(m_argc, m_argv, all),
		vm); // can throw

      /** --help option
       */
      if ( vm.count("help")  )
	{
	  std::cout << m_brief << std::endl <<*m_desc<<std::endl;;
	  exit(0);
	}
      if ( vm.count("experimental")  )
	{
	  std::cout << m_brief << std::endl <<all<<std::endl;;

	  exit(0);
	}

      po::notify(vm); // throws on error, so do after help in case
      // there are any problems
    }
  catch(boost::program_options::required_option& e)
    {
      //rad::OptionPrinter::formatRequiredOptionError(e);
      std::cerr << "ERROR: " << e.what() << std::endl ;
      std::cout<<m_desc<<std::endl;
      //rad::OptionPrinter::printStandardAppDesc(appName,
      //                                         std::cout,
      //                                        m_desc                                               );
      exit(0);
    }
  catch(po::error& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
      std::cout << m_desc << std::endl;
      exit(0);
    }
}
void ArgumentParser::help(){}
<commit_msg>bugfix for argument parser, did not ouput help in case of parse error<commit_after>#include "ArgumentParser.h"

static const unsigned LINEWIDTH=160;

ArgumentParser::ArgumentParser(int argc, char** argv){
  m_argc=argc;
  m_argv=argv;
  m_brief="";
  m_desc=new po::options_description("General options",LINEWIDTH,LINEWIDTH/2);
  m_optional=new po::options_description("Experimental and legacy options",LINEWIDTH,LINEWIDTH/2);
  m_desc->add_options()("help,h","display brief help");
  m_desc->add_options()("experimental","display full help, including experimental and deprecated options");

}

ArgumentParser::ArgumentParser(){
  m_argc=0; m_argv=NULL;
  m_brief="";
  m_desc=new po::options_description("General options",LINEWIDTH,LINEWIDTH/2);
  m_optional=new po::options_description("Experimental and legacy options",LINEWIDTH,LINEWIDTH/2);
  m_desc->add_options()("help,h","display brief help");
  m_desc->add_options()("experimental","display full help, including experimental and deprecated options");
}
void ArgumentParser::option(const char * opt, bool & variable, const char * descr, bool optional){
  if (!optional){
    m_desc->add_options()
      (opt,po::bool_switch(&variable) ,descr) ;
  }else{
    m_optional->add_options()
      (opt,po::bool_switch(&variable) ,descr) ;
  }
}

bool ArgumentParser::parse(){
  std::string appName = boost::filesystem::basename(m_argv[0]);
  po::variables_map vm;
  po::options_description all("Allowed options",LINEWIDTH);
  all.add(*m_desc);
  all.add(*m_optional);

  try
    {
      po::store(po::parse_command_line(m_argc, m_argv, all),
		vm); // can throw

      /** --help option
       */
      if ( vm.count("help")  )
	{
	  std::cout << m_brief << std::endl <<*m_desc<<std::endl;;
	  exit(0);
	}
      if ( vm.count("experimental")  )
	{
	  std::cout << m_brief << std::endl <<all<<std::endl;;

	  exit(0);
	}

      po::notify(vm); // throws on error, so do after help in case
      // there are any problems
    }
  catch(boost::program_options::required_option& e)
    {
      //rad::OptionPrinter::formatRequiredOptionError(e);
      std::cerr << "ERROR: " << e.what() << std::endl ;
      std::cout<<*m_desc<<std::endl;
      //rad::OptionPrinter::printStandardAppDesc(appName,
      //                                         std::cout,
      //                                        m_desc                                               );
      exit(0);
    }
  catch(po::error& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
      std::cout <<* m_desc << std::endl;
      exit(0);
    }
  return 1;
}
void ArgumentParser::help(){}
<|endoftext|>


<commit_before>#include <BALL/VIEW/KERNEL/iconLoader.h>

#include <QtCore/QDir>
#include <QtCore/QString>
#include <QtGui/QIcon>

#include <BALL/SYSTEM/path.h>
#include <BALL/DATATYPE/string.h>

namespace BALL
{
	namespace VIEW
	{

		QMutex IconLoader::mutex_;
		boost::shared_ptr<IconLoader> IconLoader::loader_;

		IconLoader::IconLoader()
			: invalid_(new QIcon())
		{
			Path p;
			QStringList splitpaths = QString(p.getDataPath().c_str()).split("\n");
			foreach(QString str, splitpaths) {
				icon_dirs_.append(str + "/graphics/icons");
			}

			setup_();
		}

		IconLoader::IconLoader(const QStringList& icon_dirs)
			: invalid_(new QIcon()), icon_dirs_(icon_dirs)
		{
			setup_();
		}

		IconLoader::IconLoader(const std::list<String>& icon_dirs)
			: invalid_(new QIcon())
		{
			for(std::list<String>::const_iterator it = icon_dirs.begin(); it != icon_dirs.end(); ++it) {
				icon_dirs_.append(it->c_str());
			}

			setup_();
		}

		IconLoader::~IconLoader()
		{
			for(HashMap<String, QIcon*>::iterator it = icon_map_.begin(); it != icon_map_.end(); ++it) {
				delete it->second;
			}

			delete invalid_;
		}

		void IconLoader::setup_()
		{
			sizes_.push_back(16);
			sizes_.push_back(22);
			sizes_.push_back(32);
			sizes_.push_back(48);
			sizes_.push_back(64);
			sizes_.push_back(128);
		}

		void IconLoader::appendIconPath(const String& path)
		{
			icon_dirs_.append(path.c_str());
		}

		const QIcon& IconLoader::getIcon(const String& name)
		{
			//See if we have already loaded this icon
			hash_map_lock_.lockForRead();
			HashMap<String, QIcon*>::iterator res = icon_map_.find(name);
			hash_map_lock_.unlock();

			if(res != icon_map_.end()) {
				return *res->second;
			}

			hash_map_lock_.lockForWrite();
			//We cannot be sure that another thread did not yet load the icon.
			//This must be rechecked or memory leaks will occur
			res = icon_map_.find(name);
			if(res != icon_map_.end()) {
				hash_map_lock_.unlock();
				return *res->second;
			}
			QIcon* tmp = loadIcon_(name);
			hash_map_lock_.unlock();

			if(!tmp) {
				Log.error() << "IconLoader: Could not find the icon " << name << std::endl;
				return *invalid_;
			}

			return *tmp;
		}

		IconLoader& IconLoader::instance()
		{
			if(!loader_)
			{
				mutex_.lock();

				// Double check that the instance has not been created while we were aquiring the lock
				// Yes, it has to look like this ;-)
				if(!loader_)
				{
					loader_ = boost::shared_ptr<IconLoader>(new IconLoader());
				}

				mutex_.unlock();
			}

			return *loader_;
		}

		QIcon* IconLoader::loadIcon_(const String& name)
		{
			const QString filename = QString(name.c_str()) + ".png";

			for(QStringList::iterator it = icon_dirs_.begin(); it != icon_dirs_.end(); ++it) {
				QDir base_dir(*it);

				if(!base_dir.exists()) {
					Log.error() << "Could not locate the icon directory: " << it->toAscii().data() << std::endl;
					return 0;
				}

				QString category_name;
				QIcon* result = 0;

				for(std::list<int>::iterator sit = sizes_.begin(); sit != sizes_.end(); ++sit) {
					QDir size_dir = *it + "/" + QString::number(*sit) + "x" + QString::number(*sit);

					if(!size_dir.exists()) {
						continue;
					}

					if(size_dir.exists(filename)) {
						if(!result) {
							result = new QIcon();
						}
						result->addFile(size_dir.path() + "/" + filename);
					}
				}

				if(result) {
					icon_map_[name] = result;
					return result;
				}
			}

			return 0;
		}

	}
}

<commit_msg>Replaced some "/" by FileSystem::PATH_SEPARATOR in IconLoader<commit_after>#include <BALL/VIEW/KERNEL/iconLoader.h>

#include <QtCore/QDir>
#include <QtCore/QString>
#include <QtGui/QIcon>

#include <BALL/SYSTEM/path.h>
#include <BALL/SYSTEM/fileSystem.h>
#include <BALL/DATATYPE/string.h>

namespace BALL
{
	namespace VIEW
	{

		QMutex IconLoader::mutex_;
		boost::shared_ptr<IconLoader> IconLoader::loader_;

		IconLoader::IconLoader()
			: invalid_(new QIcon())
		{
			Path p;
			QStringList splitpaths = QString(p.getDataPath().c_str()).split("\n");
			foreach(QString str, splitpaths) {
				icon_dirs_.append(str + FileSystem::PATH_SEPARATOR + "graphics"
				                      + FileSystem::PATH_SEPARATOR + "icons");
			}

			setup_();
		}

		IconLoader::IconLoader(const QStringList& icon_dirs)
			: invalid_(new QIcon()), icon_dirs_(icon_dirs)
		{
			setup_();
		}

		IconLoader::IconLoader(const std::list<String>& icon_dirs)
			: invalid_(new QIcon())
		{
			for(std::list<String>::const_iterator it = icon_dirs.begin(); it != icon_dirs.end(); ++it) {
				icon_dirs_.append(it->c_str());
			}

			setup_();
		}

		IconLoader::~IconLoader()
		{
			for(HashMap<String, QIcon*>::iterator it = icon_map_.begin(); it != icon_map_.end(); ++it) {
				delete it->second;
			}

			delete invalid_;
		}

		void IconLoader::setup_()
		{
			sizes_.push_back(16);
			sizes_.push_back(22);
			sizes_.push_back(32);
			sizes_.push_back(48);
			sizes_.push_back(64);
			sizes_.push_back(128);
		}

		void IconLoader::appendIconPath(const String& path)
		{
			icon_dirs_.append(path.c_str());
		}

		const QIcon& IconLoader::getIcon(const String& name)
		{
			//See if we have already loaded this icon
			hash_map_lock_.lockForRead();
			HashMap<String, QIcon*>::iterator res = icon_map_.find(name);
			hash_map_lock_.unlock();

			if(res != icon_map_.end()) {
				return *res->second;
			}

			hash_map_lock_.lockForWrite();
			//We cannot be sure that another thread did not yet load the icon.
			//This must be rechecked or memory leaks will occur
			res = icon_map_.find(name);
			if(res != icon_map_.end()) {
				hash_map_lock_.unlock();
				return *res->second;
			}
			QIcon* tmp = loadIcon_(name);
			hash_map_lock_.unlock();

			if(!tmp) {
				Log.error() << "IconLoader: Could not find the icon " << name << std::endl;
				return *invalid_;
			}

			return *tmp;
		}

		IconLoader& IconLoader::instance()
		{
			if(!loader_)
			{
				mutex_.lock();

				// Double check that the instance has not been created while we were aquiring the lock
				// Yes, it has to look like this ;-)
				if(!loader_)
				{
					loader_ = boost::shared_ptr<IconLoader>(new IconLoader());
				}

				mutex_.unlock();
			}

			return *loader_;
		}

		QIcon* IconLoader::loadIcon_(const String& name)
		{
			const QString filename = QString(name.c_str()) + ".png";

			for(QStringList::iterator it = icon_dirs_.begin(); it != icon_dirs_.end(); ++it) {
				QDir base_dir(*it);

				if(!base_dir.exists()) {
					Log.error() << "Could not locate the icon directory: " << it->toAscii().data() << std::endl;
					return 0;
				}

				QString category_name;
				QIcon* result = 0;

				for(std::list<int>::iterator sit = sizes_.begin(); sit != sizes_.end(); ++sit) {
					QDir size_dir = *it + FileSystem::PATH_SEPARATOR + QString::number(*sit) + "x" + QString::number(*sit);

					if(!size_dir.exists()) {
						continue;
					}

					if(size_dir.exists(filename)) {
						if(!result) {
							result = new QIcon();
						}
						result->addFile(size_dir.path() + FileSystem::PATH_SEPARATOR + filename);
					}
				}

				if(result) {
					icon_map_[name] = result;
					return result;
				}
			}

			return 0;
		}

	}
}

<|endoftext|>