<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/containers/circular_buffer.h>
#include <mrpt/random.h>
#include <mrpt/core/common.h>
#include <CTraitsTest.h>

#include <gtest/gtest.h>

template class mrpt::CTraitsTest<mrpt::containers::circular_buffer<char>>;

using cb_t = int;

TEST(circular_buffer_tests, EmptyPop)
{
	mrpt::containers::circular_buffer<cb_t> cb(10);
	try
	{
		cb_t ret;
		cb.pop(ret);
		GTEST_FAIL() << "Exception was expected but didn't happen!";
	}
	catch (std::exception&)
	{
		// OK
	}
}
TEST(circular_buffer_tests, EmptyPopAfterPushes)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);
	for (size_t nWr = 0; nWr < LEN; nWr++)
	{
		for (size_t i = 0; i < nWr; i++) cb.push(12);
		cb_t ret;
		for (size_t i = 0; i < nWr; i++) cb.pop(ret);
		// The next one must fail:
		try
		{
			cb.pop(ret);
			GTEST_FAIL() << "Exception was expected but didn't happen!";
		}
		catch (std::exception&)
		{
			// OK
		}
	}
}

TEST(circular_buffer_tests, RandomWriteAndPeek)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);

	for (size_t iter = 0; iter < 1000; iter++)
	{
		const size_t nWr =
			mrpt::random::getRandomGenerator().drawUniform32bit() % LEN;
		for (size_t i = 0; i < nWr; i++) cb.push(i);
		cb_t ret;
		for (size_t i = 0; i < nWr; i++)
		{
			ret = cb.peek(i);
			EXPECT_EQ(ret, cb_t(i));
		}
		for (size_t i = 0; i < nWr; i++)
		{
			cb.pop(ret);
			EXPECT_EQ(ret, cb_t(i));
		}
	}
}
TEST(circular_buffer_tests, RandomWriteManyAndPeek)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);
	std::vector<cb_t> dum_buf;

	for (size_t iter = 0; iter < 1000; iter++)
	{
		const size_t nWr =
			1 +
			mrpt::random::getRandomGenerator().drawUniform32bit() % (LEN - 1);
		dum_buf.resize(nWr);
		cb.push_many(&dum_buf[0], nWr);
		cb_t ret;
		if (iter % 1)
		{
			for (size_t i = 0; i < nWr; i++) ret = cb.peek(i);
			MRPT_UNUSED_PARAM(ret);
		}
		else
		{
			cb.peek_many(&dum_buf[0], nWr);
		}
		cb.pop_many(&dum_buf[0], nWr);
	}
}
TEST(circular_buffer_tests, RandomWriteAndPeekOverrun)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);

	for (size_t iter = 0; iter < 100; iter++)
	{
		const size_t nWr =
			mrpt::random::getRandomGenerator().drawUniform32bit() % LEN;
		for (size_t i = 0; i < nWr; i++) cb.push(i);
		cb_t ret;
		for (unsigned k = 0; k < 5; k++)
		{
			try
			{
				ret = cb.peek(nWr + k);
				GTEST_FAIL() << "Exception was expected but didn't happen!";
			}
			catch (std::exception&)
			{
				// OK
			}
		}
		for (size_t i = 0; i < nWr; i++) cb.pop(ret);
	}
}

TEST(circular_buffer_tests, Size)
{
	mrpt::containers::circular_buffer<cb_t> cb(10);
	for (size_t i = 0; i < cb.capacity() - 1; i++)
	{
		cb.push(0);
		EXPECT_EQ(cb.size(), i + 1);
	}
	EXPECT_ANY_THROW(cb.push(0));
	for (size_t i = 0; i < cb.capacity() - 1; i++)
	{
		cb.pop();
		EXPECT_EQ(cb.size(), cb.capacity() - 2 - i);
	}
}
<commit_msg>EXPECT_THROW in circularbuffer_unittest<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/containers/circular_buffer.h>
#include <mrpt/random.h>
#include <mrpt/core/common.h>
#include <CTraitsTest.h>

#include <gtest/gtest.h>

template class mrpt::CTraitsTest<mrpt::containers::circular_buffer<char>>;

using cb_t = int;

TEST(circular_buffer_tests, EmptyPop)
{
	mrpt::containers::circular_buffer<cb_t> cb(10);
	try
	{
		cb_t ret;
	EXPECT_THROW(cb.pop(ret),std::exception);
}
TEST(circular_buffer_tests, EmptyPopAfterPushes)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);
	for (size_t nWr = 0; nWr < LEN; nWr++)
	{
		for (size_t i = 0; i < nWr; i++) cb.push(12);
		cb_t ret;
		for (size_t i = 0; i < nWr; i++) cb.pop(ret);
		// The next one must fail:
		EXPECT_THROW(cb.pop(ret),std::exception);
	}
}

TEST(circular_buffer_tests, RandomWriteAndPeek)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);

	for (size_t iter = 0; iter < 1000; iter++)
	{
		const size_t nWr =
			mrpt::random::getRandomGenerator().drawUniform32bit() % LEN;
		for (size_t i = 0; i < nWr; i++) cb.push(i);
		cb_t ret;
		for (size_t i = 0; i < nWr; i++)
		{
			ret = cb.peek(i);
			EXPECT_EQ(ret, cb_t(i));
		}
		for (size_t i = 0; i < nWr; i++)
		{
			cb.pop(ret);
			EXPECT_EQ(ret, cb_t(i));
		}
	}
}
TEST(circular_buffer_tests, RandomWriteManyAndPeek)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);
	std::vector<cb_t> dum_buf;

	for (size_t iter = 0; iter < 1000; iter++)
	{
		const size_t nWr =
			1 +
			mrpt::random::getRandomGenerator().drawUniform32bit() % (LEN - 1);
		dum_buf.resize(nWr);
		cb.push_many(&dum_buf[0], nWr);
		cb_t ret;
		if (iter % 1)
		{
			for (size_t i = 0; i < nWr; i++) ret = cb.peek(i);
			MRPT_UNUSED_PARAM(ret);
		}
		else
		{
			cb.peek_many(&dum_buf[0], nWr);
		}
		cb.pop_many(&dum_buf[0], nWr);
	}
}
TEST(circular_buffer_tests, RandomWriteAndPeekOverrun)
{
	const size_t LEN = 20;
	mrpt::containers::circular_buffer<cb_t> cb(LEN);

	for (size_t iter = 0; iter < 100; iter++)
	{
		const size_t nWr =
			mrpt::random::getRandomGenerator().drawUniform32bit() % LEN;
		for (size_t i = 0; i < nWr; i++) cb.push(i);
		cb_t ret;
		for (unsigned k = 0; k < 5; k++)
		{
			try
			{
				ret = cb.peek(nWr + k);
				GTEST_FAIL() << "Exception was expected but didn't happen!";
			}
			catch (std::exception&)
			{
				// OK
			}
		}
		for (size_t i = 0; i < nWr; i++) cb.pop(ret);
	}
}

TEST(circular_buffer_tests, Size)
{
	mrpt::containers::circular_buffer<cb_t> cb(10);
	for (size_t i = 0; i < cb.capacity() - 1; i++)
	{
		cb.push(0);
		EXPECT_EQ(cb.size(), i + 1);
	}
	EXPECT_ANY_THROW(cb.push(0));
	for (size_t i = 0; i < cb.capacity() - 1; i++)
	{
		cb.pop();
		EXPECT_EQ(cb.size(), cb.capacity() - 2 - i);
	}
}
<|endoftext|>


<commit_before><commit_msg>`yli::load::load_CSV_texture`: use `std::holds_alternative`.<commit_after><|endoftext|>


<commit_before><commit_msg>Remove a CHECK() which was firing.<commit_after><|endoftext|>


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

#include "chrome/browser/ui/webui/extensions/extension_loader_handler.h"

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/path_util.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/zipfile_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/file_highlighter.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "third_party/re2/re2/re2.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/shell_dialogs/select_file_dialog.h"

namespace extensions {

namespace {

// Read a file to a string and return.
std::string ReadFileToString(const base::FilePath& path) {
  std::string data;
  // This call can fail, but it doesn't matter for our purposes. If it fails,
  // we simply return an empty string for the manifest, and ignore it.
  base::ReadFileToString(path, &data);
  return data;
}

}  // namespace

class ExtensionLoaderHandler::FileHelper
    : public ui::SelectFileDialog::Listener {
 public:
  explicit FileHelper(ExtensionLoaderHandler* loader_handler);
  ~FileHelper() override;

  // Create a FileDialog for the user to select the unpacked extension
  // directory.
  void ChooseFile();

 private:
  // ui::SelectFileDialog::Listener implementation.
  void FileSelected(const base::FilePath& path,
                    int index,
                    void* params) override;
  void MultiFilesSelected(const std::vector<base::FilePath>& files,
                          void* params) override;

  // The associated ExtensionLoaderHandler. Weak, but guaranteed to be alive,
  // as it owns this object.
  ExtensionLoaderHandler* loader_handler_;

  // The dialog used to pick a directory when loading an unpacked extension.
  scoped_refptr<ui::SelectFileDialog> load_extension_dialog_;

  // The last selected directory, so we can start in the same spot.
  base::FilePath last_unpacked_directory_;

  // The title of the dialog.
  base::string16 title_;

  DISALLOW_COPY_AND_ASSIGN(FileHelper);
};

ExtensionLoaderHandler::FileHelper::FileHelper(
    ExtensionLoaderHandler* loader_handler)
    : loader_handler_(loader_handler),
      title_(l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY)) {
}

ExtensionLoaderHandler::FileHelper::~FileHelper() {
  // There may be a pending file dialog; inform it the listener is destroyed so
  // it doesn't try and call back.
  if (load_extension_dialog_.get())
    load_extension_dialog_->ListenerDestroyed();
}

void ExtensionLoaderHandler::FileHelper::ChooseFile() {
  static const int kFileTypeIndex = 0;  // No file type information to index.
  static const ui::SelectFileDialog::Type kSelectType =
      ui::SelectFileDialog::SELECT_FOLDER;

  if (!load_extension_dialog_.get()) {
    load_extension_dialog_ = ui::SelectFileDialog::Create(
        this,
        new ChromeSelectFilePolicy(
            loader_handler_->web_ui()->GetWebContents()));
  }

  load_extension_dialog_->SelectFile(
      kSelectType,
      title_,
      last_unpacked_directory_,
      NULL,
      kFileTypeIndex,
      base::FilePath::StringType(),
      loader_handler_->web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
      NULL);

  content::RecordComputedAction("Options_LoadUnpackedExtension");
}

void ExtensionLoaderHandler::FileHelper::FileSelected(
    const base::FilePath& path, int index, void* params) {
  loader_handler_->LoadUnpackedExtensionImpl(path);
}

void ExtensionLoaderHandler::FileHelper::MultiFilesSelected(
      const std::vector<base::FilePath>& files, void* params) {
  NOTREACHED();
}

ExtensionLoaderHandler::ExtensionLoaderHandler(Profile* profile)
    : profile_(profile),
      file_helper_(new FileHelper(this)),
      extension_error_reporter_observer_(this),
      ui_ready_(false),
      weak_ptr_factory_(this) {
  DCHECK(profile_);
  extension_error_reporter_observer_.Add(ExtensionErrorReporter::GetInstance());
}

ExtensionLoaderHandler::~ExtensionLoaderHandler() {
}

void ExtensionLoaderHandler::GetLocalizedValues(
    content::WebUIDataSource* source) {
  source->AddString(
      "extensionLoadErrorHeading",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_HEADING));
  source->AddString(
      "extensionLoadErrorMessage",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_MESSAGE));
  source->AddString(
      "extensionLoadErrorRetry",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_RETRY));
  source->AddString(
      "extensionLoadErrorGiveUp",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_GIVE_UP));
  source->AddString(
      "extensionLoadCouldNotLoadManifest",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_COULD_NOT_LOAD_MANIFEST));
  source->AddString(
      "extensionLoadAdditionalFailures",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ADDITIONAL_FAILURES));
}

void ExtensionLoaderHandler::RegisterMessages() {
  // We observe WebContents in order to detect page refreshes, since notifying
  // the frontend of load failures must be delayed until the page finishes
  // loading. We never call Observe(NULL) because this object is constructed
  // on page load and persists between refreshes.
  content::WebContentsObserver::Observe(web_ui()->GetWebContents());

  web_ui()->RegisterMessageCallback(
      "extensionLoaderLoadUnpacked",
      base::Bind(&ExtensionLoaderHandler::HandleLoadUnpacked,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderRetry",
      base::Bind(&ExtensionLoaderHandler::HandleRetry,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderIgnoreFailure",
      base::Bind(&ExtensionLoaderHandler::HandleIgnoreFailure,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderDisplayFailures",
      base::Bind(&ExtensionLoaderHandler::HandleDisplayFailures,
                 weak_ptr_factory_.GetWeakPtr()));
}

void ExtensionLoaderHandler::HandleLoadUnpacked(const base::ListValue* args) {
  DCHECK(args->empty());
  file_helper_->ChooseFile();
}

void ExtensionLoaderHandler::HandleRetry(const base::ListValue* args) {
  DCHECK(args->empty());
  const base::FilePath file_path = failed_paths_.back();
  failed_paths_.pop_back();
  LoadUnpackedExtensionImpl(file_path);
}

void ExtensionLoaderHandler::HandleIgnoreFailure(const base::ListValue* args) {
  DCHECK(args->empty());
  failed_paths_.pop_back();
}

void ExtensionLoaderHandler::HandleDisplayFailures(
    const base::ListValue* args) {
  DCHECK(args->empty());
  ui_ready_ = true;

  // Notify the frontend of any load failures that were triggered while the
  // chrome://extensions page was loading.
  if (!failures_.empty())
    NotifyFrontendOfFailure();
}

void ExtensionLoaderHandler::LoadUnpackedExtensionImpl(
    const base::FilePath& file_path) {
  if (EndsWith(file_path.AsUTF16Unsafe(),
               base::ASCIIToUTF16(".zip"),
               false /* case insensitive */)) {
    scoped_refptr<ZipFileInstaller> installer = ZipFileInstaller::Create(
        ExtensionSystem::Get(profile_)->extension_service());

    // We do our own error handling, so we don't want a load failure to trigger
    // a dialog.
    installer->set_be_noisy_on_failure(false);

    installer->LoadFromZipFile(file_path);
  } else {
    scoped_refptr<UnpackedInstaller> installer = UnpackedInstaller::Create(
        ExtensionSystem::Get(profile_)->extension_service());

    // We do our own error handling, so we don't want a load failure to trigger
    // a dialog.
    installer->set_be_noisy_on_failure(false);

    installer->Load(file_path);
  }
}

void ExtensionLoaderHandler::OnLoadFailure(
    content::BrowserContext* browser_context,
    const base::FilePath& file_path,
    const std::string& error) {
  // Only show errors from our browser context.
  if (web_ui()->GetWebContents()->GetBrowserContext() != browser_context)
    return;

  size_t line = 0u;
  size_t column = 0u;
  std::string regex =
      base::StringPrintf("%s  Line: (\\d+), column: (\\d+), .*",
                         manifest_errors::kManifestParseError);
  // If this was a JSON parse error, we can highlight the exact line with the
  // error. Otherwise, we should still display the manifest (for consistency,
  // reference, and so that if we ever make this really fancy and add an editor,
  // it's ready).
  //
  // This regex call can fail, but if it does, we just don't highlight anything.
  re2::RE2::FullMatch(error, regex, &line, &column);

  // This will read the manifest and call AddFailure with the read manifest
  // contents.
  base::PostTaskAndReplyWithResult(
      content::BrowserThread::GetBlockingPool(),
      FROM_HERE,
      base::Bind(&ReadFileToString, file_path.Append(kManifestFilename)),
      base::Bind(&ExtensionLoaderHandler::AddFailure,
                 weak_ptr_factory_.GetWeakPtr(),
                 file_path,
                 error,
                 line));
}

void ExtensionLoaderHandler::DidStartNavigationToPendingEntry(
    const GURL& url,
    content::NavigationController::ReloadType reload_type) {
  // In the event of a page reload, we ensure that the frontend is not notified
  // until the UI finishes loading, so we set |ui_ready_| to false. This is
  // balanced in HandleDisplayFailures, which is called when the frontend is
  // ready to receive failure notifications.
  if (reload_type != content::NavigationController::NO_RELOAD)
    ui_ready_ = false;
}

void ExtensionLoaderHandler::AddFailure(
    const base::FilePath& file_path,
    const std::string& error,
    size_t line_number,
    const std::string& manifest) {
  failed_paths_.push_back(file_path);
  base::FilePath prettified_path = path_util::PrettifyPath(file_path);

  scoped_ptr<base::DictionaryValue> manifest_value(new base::DictionaryValue());
  SourceHighlighter highlighter(manifest, line_number);
  // If the line number is 0, this highlights no regions, but still adds the
  // full manifest.
  highlighter.SetHighlightedRegions(manifest_value.get());

  scoped_ptr<base::DictionaryValue> failure(new base::DictionaryValue());
  failure->Set("path",
               new base::StringValue(prettified_path.LossyDisplayName()));
  failure->Set("error", new base::StringValue(base::UTF8ToUTF16(error)));
  failure->Set("manifest", manifest_value.release());
  failures_.Append(failure.release());

  // Only notify the frontend if the frontend UI is ready.
  if (ui_ready_)
    NotifyFrontendOfFailure();
}

void ExtensionLoaderHandler::NotifyFrontendOfFailure() {
  web_ui()->CallJavascriptFunction(
      "extensions.ExtensionLoader.notifyLoadFailed",
      failures_);
  failures_.Clear();
}

}  // namespace extensions
<commit_msg>Exclude zip-file loading from "Load Unpacked Extension"<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/extensions/extension_loader_handler.h"

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/path_util.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/zipfile_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/file_highlighter.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "third_party/re2/re2/re2.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/shell_dialogs/select_file_dialog.h"

namespace extensions {

namespace {

// Read a file to a string and return.
std::string ReadFileToString(const base::FilePath& path) {
  std::string data;
  // This call can fail, but it doesn't matter for our purposes. If it fails,
  // we simply return an empty string for the manifest, and ignore it.
  base::ReadFileToString(path, &data);
  return data;
}

}  // namespace

class ExtensionLoaderHandler::FileHelper
    : public ui::SelectFileDialog::Listener {
 public:
  explicit FileHelper(ExtensionLoaderHandler* loader_handler);
  ~FileHelper() override;

  // Create a FileDialog for the user to select the unpacked extension
  // directory.
  void ChooseFile();

 private:
  // ui::SelectFileDialog::Listener implementation.
  void FileSelected(const base::FilePath& path,
                    int index,
                    void* params) override;
  void MultiFilesSelected(const std::vector<base::FilePath>& files,
                          void* params) override;

  // The associated ExtensionLoaderHandler. Weak, but guaranteed to be alive,
  // as it owns this object.
  ExtensionLoaderHandler* loader_handler_;

  // The dialog used to pick a directory when loading an unpacked extension.
  scoped_refptr<ui::SelectFileDialog> load_extension_dialog_;

  // The last selected directory, so we can start in the same spot.
  base::FilePath last_unpacked_directory_;

  // The title of the dialog.
  base::string16 title_;

  DISALLOW_COPY_AND_ASSIGN(FileHelper);
};

ExtensionLoaderHandler::FileHelper::FileHelper(
    ExtensionLoaderHandler* loader_handler)
    : loader_handler_(loader_handler),
      title_(l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY)) {
}

ExtensionLoaderHandler::FileHelper::~FileHelper() {
  // There may be a pending file dialog; inform it the listener is destroyed so
  // it doesn't try and call back.
  if (load_extension_dialog_.get())
    load_extension_dialog_->ListenerDestroyed();
}

void ExtensionLoaderHandler::FileHelper::ChooseFile() {
  static const int kFileTypeIndex = 0;  // No file type information to index.
  static const ui::SelectFileDialog::Type kSelectType =
      ui::SelectFileDialog::SELECT_FOLDER;

  if (!load_extension_dialog_.get()) {
    load_extension_dialog_ = ui::SelectFileDialog::Create(
        this,
        new ChromeSelectFilePolicy(
            loader_handler_->web_ui()->GetWebContents()));
  }

  load_extension_dialog_->SelectFile(
      kSelectType,
      title_,
      last_unpacked_directory_,
      NULL,
      kFileTypeIndex,
      base::FilePath::StringType(),
      loader_handler_->web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
      NULL);

  content::RecordComputedAction("Options_LoadUnpackedExtension");
}

void ExtensionLoaderHandler::FileHelper::FileSelected(
    const base::FilePath& path, int index, void* params) {
  loader_handler_->LoadUnpackedExtensionImpl(path);
}

void ExtensionLoaderHandler::FileHelper::MultiFilesSelected(
      const std::vector<base::FilePath>& files, void* params) {
  NOTREACHED();
}

ExtensionLoaderHandler::ExtensionLoaderHandler(Profile* profile)
    : profile_(profile),
      file_helper_(new FileHelper(this)),
      extension_error_reporter_observer_(this),
      ui_ready_(false),
      weak_ptr_factory_(this) {
  DCHECK(profile_);
  extension_error_reporter_observer_.Add(ExtensionErrorReporter::GetInstance());
}

ExtensionLoaderHandler::~ExtensionLoaderHandler() {
}

void ExtensionLoaderHandler::GetLocalizedValues(
    content::WebUIDataSource* source) {
  source->AddString(
      "extensionLoadErrorHeading",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_HEADING));
  source->AddString(
      "extensionLoadErrorMessage",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_MESSAGE));
  source->AddString(
      "extensionLoadErrorRetry",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_RETRY));
  source->AddString(
      "extensionLoadErrorGiveUp",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_GIVE_UP));
  source->AddString(
      "extensionLoadCouldNotLoadManifest",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_COULD_NOT_LOAD_MANIFEST));
  source->AddString(
      "extensionLoadAdditionalFailures",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ADDITIONAL_FAILURES));
}

void ExtensionLoaderHandler::RegisterMessages() {
  // We observe WebContents in order to detect page refreshes, since notifying
  // the frontend of load failures must be delayed until the page finishes
  // loading. We never call Observe(NULL) because this object is constructed
  // on page load and persists between refreshes.
  content::WebContentsObserver::Observe(web_ui()->GetWebContents());

  web_ui()->RegisterMessageCallback(
      "extensionLoaderLoadUnpacked",
      base::Bind(&ExtensionLoaderHandler::HandleLoadUnpacked,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderRetry",
      base::Bind(&ExtensionLoaderHandler::HandleRetry,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderIgnoreFailure",
      base::Bind(&ExtensionLoaderHandler::HandleIgnoreFailure,
                 weak_ptr_factory_.GetWeakPtr()));
  web_ui()->RegisterMessageCallback(
      "extensionLoaderDisplayFailures",
      base::Bind(&ExtensionLoaderHandler::HandleDisplayFailures,
                 weak_ptr_factory_.GetWeakPtr()));
}

void ExtensionLoaderHandler::HandleLoadUnpacked(const base::ListValue* args) {
  DCHECK(args->empty());
  file_helper_->ChooseFile();
}

void ExtensionLoaderHandler::HandleRetry(const base::ListValue* args) {
  DCHECK(args->empty());
  const base::FilePath file_path = failed_paths_.back();
  failed_paths_.pop_back();
  LoadUnpackedExtensionImpl(file_path);
}

void ExtensionLoaderHandler::HandleIgnoreFailure(const base::ListValue* args) {
  DCHECK(args->empty());
  failed_paths_.pop_back();
}

void ExtensionLoaderHandler::HandleDisplayFailures(
    const base::ListValue* args) {
  DCHECK(args->empty());
  ui_ready_ = true;

  // Notify the frontend of any load failures that were triggered while the
  // chrome://extensions page was loading.
  if (!failures_.empty())
    NotifyFrontendOfFailure();
}

void ExtensionLoaderHandler::LoadUnpackedExtensionImpl(
    const base::FilePath& file_path) {
  scoped_refptr<UnpackedInstaller> installer = UnpackedInstaller::Create(
      ExtensionSystem::Get(profile_)->extension_service());

  // We do our own error handling, so we don't want a load failure to trigger
  // a dialog.
  installer->set_be_noisy_on_failure(false);

  installer->Load(file_path);
}

void ExtensionLoaderHandler::OnLoadFailure(
    content::BrowserContext* browser_context,
    const base::FilePath& file_path,
    const std::string& error) {
  // Only show errors from our browser context.
  if (web_ui()->GetWebContents()->GetBrowserContext() != browser_context)
    return;

  size_t line = 0u;
  size_t column = 0u;
  std::string regex =
      base::StringPrintf("%s  Line: (\\d+), column: (\\d+), .*",
                         manifest_errors::kManifestParseError);
  // If this was a JSON parse error, we can highlight the exact line with the
  // error. Otherwise, we should still display the manifest (for consistency,
  // reference, and so that if we ever make this really fancy and add an editor,
  // it's ready).
  //
  // This regex call can fail, but if it does, we just don't highlight anything.
  re2::RE2::FullMatch(error, regex, &line, &column);

  // This will read the manifest and call AddFailure with the read manifest
  // contents.
  base::PostTaskAndReplyWithResult(
      content::BrowserThread::GetBlockingPool(),
      FROM_HERE,
      base::Bind(&ReadFileToString, file_path.Append(kManifestFilename)),
      base::Bind(&ExtensionLoaderHandler::AddFailure,
                 weak_ptr_factory_.GetWeakPtr(),
                 file_path,
                 error,
                 line));
}

void ExtensionLoaderHandler::DidStartNavigationToPendingEntry(
    const GURL& url,
    content::NavigationController::ReloadType reload_type) {
  // In the event of a page reload, we ensure that the frontend is not notified
  // until the UI finishes loading, so we set |ui_ready_| to false. This is
  // balanced in HandleDisplayFailures, which is called when the frontend is
  // ready to receive failure notifications.
  if (reload_type != content::NavigationController::NO_RELOAD)
    ui_ready_ = false;
}

void ExtensionLoaderHandler::AddFailure(
    const base::FilePath& file_path,
    const std::string& error,
    size_t line_number,
    const std::string& manifest) {
  failed_paths_.push_back(file_path);
  base::FilePath prettified_path = path_util::PrettifyPath(file_path);

  scoped_ptr<base::DictionaryValue> manifest_value(new base::DictionaryValue());
  SourceHighlighter highlighter(manifest, line_number);
  // If the line number is 0, this highlights no regions, but still adds the
  // full manifest.
  highlighter.SetHighlightedRegions(manifest_value.get());

  scoped_ptr<base::DictionaryValue> failure(new base::DictionaryValue());
  failure->Set("path",
               new base::StringValue(prettified_path.LossyDisplayName()));
  failure->Set("error", new base::StringValue(base::UTF8ToUTF16(error)));
  failure->Set("manifest", manifest_value.release());
  failures_.Append(failure.release());

  // Only notify the frontend if the frontend UI is ready.
  if (ui_ready_)
    NotifyFrontendOfFailure();
}

void ExtensionLoaderHandler::NotifyFrontendOfFailure() {
  web_ui()->CallJavascriptFunction(
      "extensions.ExtensionLoader.notifyLoadFailed",
      failures_);
  failures_.Clear();
}

}  // namespace extensions
<|endoftext|>


<commit_before>#include<iostream>
#include<chrono>
#include<string.h>
#include"head.h"
#include<random>
using namespace std;
void str::disp()
{
        int i;
        cout<<n<<endl;
        cout<<len<<endl;
        for(i=0;i<26;i++)
        {
                cout<<count[i]<<"\t";
        }
}
void str::cal()
{
        len=strlen(n);
}
void str::getdata()
{
        cout<<"Name"<<endl;
        cin>>n;
}
void str::countocc()
{
        int i;
        for(i=0;i<len;i++)
        {
                if((n[i]>64)&&(n[i]<91))
                {
                        count[n[i]-65]+=1;
                }
                if((n[i]>96)&&(n[i]<123))
                {
                        count[n[i]-97]+=1;
                }
        }
}
str scase(str s)
{
        int i;
        for(i=0;i<s.len;i++)
        {
               if((s.n[i]>64)&&(s.n[i]<91))
                        s.n[i]=s.n[i]+32;
	       else if((s.n[i]>96)&&(s.n[i]<123))
	                s.n[i]=s.n[i]-32;
               else
	                s.n[i]+=0;
        }
	        return s;
}
str str::operator+(str s1)
{
        str s;
        s.n=strcat(n,s1.n);
        s.len=len+s1.len;
        return s;
}
void str::randomizer()
{
         int i;
         cout<<"Enter length"<<endl;
         cin>>len;
         n=new char[len+1];
         unsigned seed,b;
         b=rand()%len;
         seed=rand()%b;
         default_random_engine generator(seed);
         for(i=0;i<len;i++)
         {
                 uniform_int_distribution<int> distribution(65,122);
                 int a  = distribution(generator);
                 if(a<91||a>96)
	         {
	                  n[i]=a;
	         }
	         else
	         {
	                  uniform_int_distribution<int> distribution(65,90);
	                  a=distribution(generator);
	                  n[i]=a;
                 }
        }
}
void str::sort()
{
        int i,j;
        for(i=1;i<len;i++)
        {
                for(j=i+1;j<len;j++)
                {
                       if(n[i]>n[j])
                       {
                            char t;
                            t=n[i];
                            n[i]=n[j];
                            n[j]=t;
                       }
                       else  if(n[i]<n[j])
                       {
                            char t;
                            t=n[i];
                            n[i]=n[j];
                            n[j]=t;
                       }
                       cout<<n<<endl;
                 }
         }
}
void str::swap()
{
        char t;
        t=n[0];
        n[0]=n[1];
        n[1]=t;
}
int str::fact(int i)
{
        int f=1,j;
        for(j=1;j<=i;j++)
        {
              f=f*j;
        }
        return f;
}
void str::anagram()
{
       int a=0;
       for(int i=0;i<(fact(len)/2);i++)
       {
            sort();
            swap();
            cout<<n<<endl;
       }
}

<commit_msg>Delete functions.cpp<commit_after><|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// table_factory.cpp
//
// Identification: src/storage/table_factory.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "storage/table_factory.h"

#include "common/exception.h"
#include "common/logger.h"
#include "index/index.h"
#include "storage/data_table.h"
#include "storage/storage_manager.h"
#include "storage/temp_table.h"

#include <mutex>

namespace peloton {
namespace storage {

DataTable *TableFactory::GetDataTable(oid_t database_id, oid_t relation_id,
                                      catalog::Schema *schema,
                                      std::string table_name,
                                      size_t tuples_per_tilegroup_count,
                                      bool own_schema, bool adapt_table,
                                      bool is_catalog) {
  DataTable *table = new DataTable(schema, table_name, database_id, relation_id,
                                   tuples_per_tilegroup_count, own_schema,
                                   adapt_table, is_catalog);

  return table;
}

TempTable *TableFactory::GetTempTable(catalog::Schema *schema,
                                      bool own_schema) {
  TempTable *table = new TempTable(INVALID_OID, schema, own_schema);
  return (table);
}

bool TableFactory::DropDataTable(oid_t database_oid, oid_t table_oid) {
  auto storage_manager = storage::StorageManager::GetInstance();
  try {
    DataTable *table = (DataTable *)storage_manager->GetTableWithOid(
        database_oid, table_oid);
    delete table;
  } catch (CatalogException &e) {
    return false;
  }
  return true;
}

}  // namespace storage
}  // namespace peloton
<commit_msg>Removing unused header<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// table_factory.cpp
//
// Identification: src/storage/table_factory.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "storage/table_factory.h"

#include "common/exception.h"
#include "common/logger.h"
#include "index/index.h"
#include "storage/data_table.h"
#include "storage/storage_manager.h"
#include "storage/temp_table.h"

namespace peloton {
namespace storage {

DataTable *TableFactory::GetDataTable(oid_t database_id, oid_t relation_id,
                                      catalog::Schema *schema,
                                      std::string table_name,
                                      size_t tuples_per_tilegroup_count,
                                      bool own_schema, bool adapt_table,
                                      bool is_catalog) {
  DataTable *table = new DataTable(schema, table_name, database_id, relation_id,
                                   tuples_per_tilegroup_count, own_schema,
                                   adapt_table, is_catalog);

  return table;
}

TempTable *TableFactory::GetTempTable(catalog::Schema *schema,
                                      bool own_schema) {
  TempTable *table = new TempTable(INVALID_OID, schema, own_schema);
  return (table);
}

bool TableFactory::DropDataTable(oid_t database_oid, oid_t table_oid) {
  auto storage_manager = storage::StorageManager::GetInstance();
  try {
    DataTable *table = (DataTable *)storage_manager->GetTableWithOid(
        database_oid, table_oid);
    delete table;
  } catch (CatalogException &e) {
    return false;
  }
  return true;
}

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


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

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/ext/core/sc_main.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority),
    scMain(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _started(false), _paused(false), _stopped(false),
    maxTickEvent(this, false, MaxTickPriority),
    _numCycles(0), _current(nullptr), initDone(false),
    runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.
    clear();
}

void
Scheduler::clear()
{
    // Delta notifications.
    for (auto &e: deltas)
        e->deschedule();
    deltas.clear();

    // Timed notifications.
    for (auto &tsp: timeSlots) {
        TimeSlot *&ts = tsp.second;
        for (auto &e: ts->events)
            e->deschedule();
        deschedule(ts);
    }
    timeSlots.clear();

    // gem5 events.
    if (readyEvent.scheduled())
        deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);

    Process *p;
    while ((p = toFinalize.getNext()))
        p->popListNode();
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyList.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
        p->finalize();
        p->popListNode();
    }

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->finalize();
        p->popListNode();
        p->ready();
    }

    update();

    for (auto &e: deltas)
        e->run();
    deltas.clear();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If we're past initialization, finalize static sensitivity.
        p->finalize();
        // Mark the process as ready.
        p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::dontInitialize(Process *p)
{
    if (initDone) {
        // Pop this process off of the ready list.
        p->popListNode();
    } else {
        // Push this process onto the list of processes which still need
        // their static sensitivity to be finalized. That implicitly pops it
        // off the list of processes to be initialized/marked ready.
        toFinalize.pushLast(p);
    }
}

void
Scheduler::yield()
{
    _current = readyList.getNext();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart()) {
            _current->needsStart(false);
            _current->run();
        }
    }
    if (_current && _current->excWrapper) {
        // Make sure this isn't a method process.
        assert(!_current->needsStart());
        auto ew = _current->excWrapper;
        _current->excWrapper = nullptr;
        ew->throw_it();
    }
}

void
Scheduler::ready(Process *p)
{
    // Clump methods together to minimize context switching.
    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyList.pushFirst(p);
    else
        readyList.pushLast(p);

    scheduleReadyEvent();
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    bool empty = readyList.empty();

    // The evaluation phase.
    do {
        yield();
    } while (!readyList.empty());

    if (!empty)
        _numCycles++;

    // The update phase.
    update();

    if (starved() && !runToTime)
        scheduleStarvationEvent();

    // The delta phase.
    for (auto &e: deltas)
        e->run();
    deltas.clear();

    if (runOnce)
        schedulePause();
}

void
Scheduler::update()
{
    Channel *channel = updateList.getNext();
    while (channel) {
        channel->popListNode();
        channel->update();
        channel = updateList.getNext();
    }
}

void
Scheduler::pause()
{
    _paused = true;
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    scMain->run();
}

void
Scheduler::stop()
{
    _stopped = true;
    kernel->stop();

    clear();

    runOnce = false;
    scMain->run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    // We should be running from sc_main. Keep track of that Fiber to return
    // to later.
    scMain = Fiber::currentFiber();

    _started = true;
    _paused = false;
    _stopped = false;
    runToTime = run_to_time;

    maxTick = max_tick;

    if (initDone) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    schedule(&pauseEvent);
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        // If we're not supposed to finish the delta cycle, flush all
        // pending activity.
        clear();
    }
    schedule(&stopEvent);
}

Scheduler scheduler;

} // namespace sc_gem5
<commit_msg>systemc: When sc_start-ing with zero time, ensure the ready event runs.<commit_after>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/ext/core/sc_main.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority),
    scMain(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _started(false), _paused(false), _stopped(false),
    maxTickEvent(this, false, MaxTickPriority),
    _numCycles(0), _current(nullptr), initDone(false),
    runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.
    clear();
}

void
Scheduler::clear()
{
    // Delta notifications.
    for (auto &e: deltas)
        e->deschedule();
    deltas.clear();

    // Timed notifications.
    for (auto &tsp: timeSlots) {
        TimeSlot *&ts = tsp.second;
        for (auto &e: ts->events)
            e->deschedule();
        deschedule(ts);
    }
    timeSlots.clear();

    // gem5 events.
    if (readyEvent.scheduled())
        deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);

    Process *p;
    while ((p = toFinalize.getNext()))
        p->popListNode();
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyList.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
        p->finalize();
        p->popListNode();
    }

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->finalize();
        p->popListNode();
        p->ready();
    }

    update();

    for (auto &e: deltas)
        e->run();
    deltas.clear();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If we're past initialization, finalize static sensitivity.
        p->finalize();
        // Mark the process as ready.
        p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::dontInitialize(Process *p)
{
    if (initDone) {
        // Pop this process off of the ready list.
        p->popListNode();
    } else {
        // Push this process onto the list of processes which still need
        // their static sensitivity to be finalized. That implicitly pops it
        // off the list of processes to be initialized/marked ready.
        toFinalize.pushLast(p);
    }
}

void
Scheduler::yield()
{
    _current = readyList.getNext();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart()) {
            _current->needsStart(false);
            _current->run();
        }
    }
    if (_current && _current->excWrapper) {
        // Make sure this isn't a method process.
        assert(!_current->needsStart());
        auto ew = _current->excWrapper;
        _current->excWrapper = nullptr;
        ew->throw_it();
    }
}

void
Scheduler::ready(Process *p)
{
    // Clump methods together to minimize context switching.
    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyList.pushFirst(p);
    else
        readyList.pushLast(p);

    scheduleReadyEvent();
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    bool empty = readyList.empty();

    // The evaluation phase.
    do {
        yield();
    } while (!readyList.empty());

    if (!empty)
        _numCycles++;

    // The update phase.
    update();

    if (starved() && !runToTime)
        scheduleStarvationEvent();

    // The delta phase.
    for (auto &e: deltas)
        e->run();
    deltas.clear();

    if (runOnce)
        schedulePause();
}

void
Scheduler::update()
{
    Channel *channel = updateList.getNext();
    while (channel) {
        channel->popListNode();
        channel->update();
        channel = updateList.getNext();
    }
}

void
Scheduler::pause()
{
    _paused = true;
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    scMain->run();
}

void
Scheduler::stop()
{
    _stopped = true;
    kernel->stop();

    clear();

    runOnce = false;
    scMain->run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    // We should be running from sc_main. Keep track of that Fiber to return
    // to later.
    scMain = Fiber::currentFiber();

    _started = true;
    _paused = false;
    _stopped = false;
    runToTime = run_to_time;

    maxTick = max_tick;

    if (initDone) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    scheduleReadyEvent();
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    schedule(&pauseEvent);
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        // If we're not supposed to finish the delta cycle, flush all
        // pending activity.
        clear();
    }
    schedule(&stopEvent);
}

Scheduler scheduler;

} // namespace sc_gem5
<|endoftext|>


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

#ifndef __SYSTEMC_CORE_SCHEDULER_HH__
#define __SYSTEMC_CORE_SCHEDULER_HH__

#include <vector>

#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/channel.hh"
#include "systemc/core/list.hh"
#include "systemc/core/process.hh"

class Fiber;

namespace sc_gem5
{

typedef NodeList<Process> ProcessList;
typedef NodeList<Channel> ChannelList;

/*
 * The scheduler supports three different mechanisms, the initialization phase,
 * delta cycles, and timed notifications.
 *
 * INITIALIZATION PHASE
 *
 * The initialization phase has three parts:
 * 1. Run requested channel updates.
 * 2. Make processes which need to initialize runnable (methods and threads
 *    which didn't have dont_initialize called on them).
 * 3. Process delta notifications.
 *
 * First, the Kernel SimObject calls the update() method during its startup()
 * callback which handles the requested channel updates. The Kernel also
 * schedules an event to be run at time 0 with a slightly elevated priority
 * so that it happens before any "normal" event.
 *
 * When that t0 event happens, it calls the schedulers prepareForInit method
 * which performs step 2 above. That indirectly causes the scheduler's
 * readyEvent to be scheduled with slightly lowered priority, ensuring it
 * happens after any "normal" event.
 *
 * Because delta notifications are scheduled at the standard priority, all
 * of those events will happen next, performing step 3 above. Once they finish,
 * if the readyEvent was scheduled above, there shouldn't be any higher
 * priority events in front of it. When it runs, it will start the first
 * evaluate phase of the first delta cycle.
 *
 * DELTA CYCLE
 *
 * A delta cycle has three phases within it.
 * 1. The evaluate phase where runnable processes are allowed to run.
 * 2. The update phase where requested channel updates hapen.
 * 3. The delta notification phase where delta notifications happen.
 *
 * The readyEvent runs the first two steps of the delta cycle. It first goes
 * through the list of runnable processes and executes them until the set is
 * empty, and then immediately runs the update phase. Since these are all part
 * of the same event, there's no chance for other events to intervene and
 * break the required order above.
 *
 * During the update phase above, the spec forbids any action which would make
 * a process runnable. That means that once the update phase finishes, the set
 * of runnable processes will be empty. There may, however, have been some
 * delta notifications/timeouts which will have been scheduled during either
 * the evaluate or update phase above. Because those are scheduled at the
 * normal priority, they will now happen together until there aren't any
 * delta events left.
 *
 * If any processes became runnable during the delta notification phase, the
 * readyEvent will have been scheduled and will have been waiting patiently
 * behind the delta notification events. That will now run, effectively
 * starting the next delta cycle.
 *
 * TIMED NOTIFICATION PHASE
 *
 * If no processes became runnable, the event queue will continue to process
 * events until it comes across a timed notification, aka a notification
 * scheduled to happen in the future. Like delta notification events, those
 * will all happen together since the readyEvent priority is lower,
 * potentially marking new processes as ready. Once these events finish, the
 * readyEvent may run, starting the next delta cycle.
 *
 * PAUSE/STOP
 *
 * To inject a pause from sc_pause which should happen after the current delta
 * cycle's delta notification phase, an event is scheduled with a lower than
 * normal priority, but higher than the readyEvent. That ensures that any
 * delta notifications which are scheduled with normal priority will happen
 * first, since those are part of the current delta cycle. Then the pause
 * event will happen before the next readyEvent which would start the next
 * delta cycle. All of these events are scheduled for the current time, and so
 * would happen before any timed notifications went off.
 *
 * To inject a stop from sc_stop, the delta cycles should stop before even the
 * delta notifications have happened, but after the evaluate and update phases.
 * For that, a stop event with slightly higher than normal priority will be
 * scheduled so that it happens before any of the delta notification events
 * which are at normal priority.
 *
 * MAX RUN TIME
 *
 * When sc_start is called, it's possible to pass in a maximum time the
 * simulation should run to, at which point sc_pause is implicitly called.
 * That's implemented by scheduling an event at the max time with a priority
 * which is lower than all the others so that it happens only if time would
 * advance. When that event triggers, it calls the same function as the pause
 * event.
 */

class Scheduler
{
  public:
    Scheduler();

    const std::string name() const { return "systemc_scheduler"; }

    uint64_t numCycles() { return _numCycles; }
    Process *current() { return _current; }

    // Prepare for initialization.
    void prepareForInit();

    // Register a process with the scheduler.
    void reg(Process *p);

    // Tell the scheduler not to initialize a process.
    void dontInitialize(Process *p);

    // Run the next process, if there is one.
    void yield();

    // Put a process on the ready list.
    void ready(Process *p);

    // Schedule an update for a given channel.
    void requestUpdate(Channel *c);

    // Run the given process immediately, preempting whatever may be running.
    void
    runNow(Process *p)
    {
        // If a process is running, schedule it/us to run again.
        if (_current)
            readyList.pushFirst(_current);
        // Schedule p to run first.
        readyList.pushFirst(p);
        yield();
    }

    // Set an event queue for scheduling events.
    void setEventQueue(EventQueue *_eq) { eq = _eq; }

    // Get the current time according to gem5.
    Tick getCurTick() { return eq ? eq->getCurTick() : 0; }

    // For scheduling delayed/timed notifications/timeouts.
    void
    schedule(::Event *event, Tick tick)
    {
        pendingTicks[tick]++;

        if (initReady)
            eq->schedule(event, tick);
        else
            eventsToSchedule[event] = tick;
    }

    // For descheduling delayed/timed notifications/timeouts.
    void
    deschedule(::Event *event)
    {
        auto it = pendingTicks.find(event->when());
        if (--it->second == 0)
            pendingTicks.erase(it);

        if (initReady)
            eq->deschedule(event);
        else
            eventsToSchedule.erase(event);
    }

    // Tell the scheduler than an event fired for bookkeeping purposes.
    void
    eventHappened()
    {
        auto it = pendingTicks.begin();
        if (--it->second == 0)
            pendingTicks.erase(it);

        if (starved() && !runToTime)
            scheduleStarvationEvent();
    }

    // Pending activity ignores gem5 activity, much like how a systemc
    // simulation wouldn't know about asynchronous external events (socket IO
    // for instance) that might happen before time advances in a pure
    // systemc simulation. Also the spec lists what specific types of pending
    // activity needs to be counted, which obviously doesn't include gem5
    // events.

    // Return whether there's pending systemc activity at this time.
    bool
    pendingCurr()
    {
        if (!readyList.empty() || !updateList.empty())
            return true;
        return pendingTicks.size() &&
            pendingTicks.begin()->first == getCurTick();
    }

    // Return whether there are pending timed notifications or timeouts.
    bool
    pendingFuture()
    {
        switch (pendingTicks.size()) {
          case 0: return false;
          case 1: return pendingTicks.begin()->first > getCurTick();
          default: return true;
        }
    }

    // Return how many ticks there are until the first pending event, if any.
    Tick
    timeToPending()
    {
        if (!readyList.empty() || !updateList.empty())
            return 0;
        else if (pendingTicks.size())
            return pendingTicks.begin()->first - getCurTick();
        else
            return MaxTick - getCurTick();
    }

    // Run scheduled channel updates.
    void update();

    void setScMainFiber(Fiber *sc_main) { scMain = sc_main; }

    void start(Tick max_tick, bool run_to_time);

    void schedulePause();
    void scheduleStop(bool finish_delta);

    bool paused() { return _paused; }
    bool stopped() { return _stopped; }

  private:
    typedef const EventBase::Priority Priority;
    static Priority DefaultPriority = EventBase::Default_Pri;

    static Priority StopPriority = DefaultPriority - 1;
    static Priority PausePriority = DefaultPriority + 1;
    static Priority ReadyPriority = DefaultPriority + 2;
    static Priority StarvationPriority = ReadyPriority;
    static Priority MaxTickPriority = DefaultPriority + 3;

    EventQueue *eq;
    std::map<Tick, int> pendingTicks;

    void runReady();
    EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;
    void scheduleReadyEvent();

    void pause();
    void stop();
    EventWrapper<Scheduler, &Scheduler::pause> pauseEvent;
    EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
    Fiber *scMain;

    bool
    starved()
    {
        return (readyList.empty() && updateList.empty() &&
                (pendingTicks.empty() ||
                 pendingTicks.begin()->first > maxTick) &&
                initList.empty());
    }
    EventWrapper<Scheduler, &Scheduler::pause> starvationEvent;
    void scheduleStarvationEvent();

    bool _started;
    bool _paused;
    bool _stopped;

    Tick maxTick;
    EventWrapper<Scheduler, &Scheduler::pause> maxTickEvent;

    uint64_t _numCycles;

    Process *_current;

    bool initReady;
    bool runToTime;

    ProcessList initList;
    ProcessList toFinalize;
    ProcessList readyList;

    ChannelList updateList;

    std::map<::Event *, Tick> eventsToSchedule;
};

extern Scheduler scheduler;

} // namespace sc_gem5

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

#ifndef __SYSTEMC_CORE_SCHEDULER_HH__
#define __SYSTEMC_CORE_SCHEDULER_HH__

#include <vector>

#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/channel.hh"
#include "systemc/core/list.hh"
#include "systemc/core/process.hh"

class Fiber;

namespace sc_gem5
{

typedef NodeList<Process> ProcessList;
typedef NodeList<Channel> ChannelList;

/*
 * The scheduler supports three different mechanisms, the initialization phase,
 * delta cycles, and timed notifications.
 *
 * INITIALIZATION PHASE
 *
 * The initialization phase has three parts:
 * 1. Run requested channel updates.
 * 2. Make processes which need to initialize runnable (methods and threads
 *    which didn't have dont_initialize called on them).
 * 3. Process delta notifications.
 *
 * First, the Kernel SimObject calls the update() method during its startup()
 * callback which handles the requested channel updates. The Kernel also
 * schedules an event to be run at time 0 with a slightly elevated priority
 * so that it happens before any "normal" event.
 *
 * When that t0 event happens, it calls the schedulers prepareForInit method
 * which performs step 2 above. That indirectly causes the scheduler's
 * readyEvent to be scheduled with slightly lowered priority, ensuring it
 * happens after any "normal" event.
 *
 * Because delta notifications are scheduled at the standard priority, all
 * of those events will happen next, performing step 3 above. Once they finish,
 * if the readyEvent was scheduled above, there shouldn't be any higher
 * priority events in front of it. When it runs, it will start the first
 * evaluate phase of the first delta cycle.
 *
 * DELTA CYCLE
 *
 * A delta cycle has three phases within it.
 * 1. The evaluate phase where runnable processes are allowed to run.
 * 2. The update phase where requested channel updates hapen.
 * 3. The delta notification phase where delta notifications happen.
 *
 * The readyEvent runs the first two steps of the delta cycle. It first goes
 * through the list of runnable processes and executes them until the set is
 * empty, and then immediately runs the update phase. Since these are all part
 * of the same event, there's no chance for other events to intervene and
 * break the required order above.
 *
 * During the update phase above, the spec forbids any action which would make
 * a process runnable. That means that once the update phase finishes, the set
 * of runnable processes will be empty. There may, however, have been some
 * delta notifications/timeouts which will have been scheduled during either
 * the evaluate or update phase above. Because those are scheduled at the
 * normal priority, they will now happen together until there aren't any
 * delta events left.
 *
 * If any processes became runnable during the delta notification phase, the
 * readyEvent will have been scheduled and will have been waiting patiently
 * behind the delta notification events. That will now run, effectively
 * starting the next delta cycle.
 *
 * TIMED NOTIFICATION PHASE
 *
 * If no processes became runnable, the event queue will continue to process
 * events until it comes across a timed notification, aka a notification
 * scheduled to happen in the future. Like delta notification events, those
 * will all happen together since the readyEvent priority is lower,
 * potentially marking new processes as ready. Once these events finish, the
 * readyEvent may run, starting the next delta cycle.
 *
 * PAUSE/STOP
 *
 * To inject a pause from sc_pause which should happen after the current delta
 * cycle's delta notification phase, an event is scheduled with a lower than
 * normal priority, but higher than the readyEvent. That ensures that any
 * delta notifications which are scheduled with normal priority will happen
 * first, since those are part of the current delta cycle. Then the pause
 * event will happen before the next readyEvent which would start the next
 * delta cycle. All of these events are scheduled for the current time, and so
 * would happen before any timed notifications went off.
 *
 * To inject a stop from sc_stop, the delta cycles should stop before even the
 * delta notifications have happened, but after the evaluate and update phases.
 * For that, a stop event with slightly higher than normal priority will be
 * scheduled so that it happens before any of the delta notification events
 * which are at normal priority.
 *
 * MAX RUN TIME
 *
 * When sc_start is called, it's possible to pass in a maximum time the
 * simulation should run to, at which point sc_pause is implicitly called. The
 * simulation is supposed to run up to the latest timed notification phase
 * which is less than or equal to the maximum time. In other words it should
 * run timed notifications at the maximum time, but not the subsequent evaluate
 * phase. That's implemented by scheduling an event at the max time with a
 * priority which is lower than all the others except the ready event. Timed
 * notifications will happen before it fires, but it will override any ready
 * event and prevent the evaluate phase from starting.
 */

class Scheduler
{
  public:
    Scheduler();

    const std::string name() const { return "systemc_scheduler"; }

    uint64_t numCycles() { return _numCycles; }
    Process *current() { return _current; }

    // Prepare for initialization.
    void prepareForInit();

    // Register a process with the scheduler.
    void reg(Process *p);

    // Tell the scheduler not to initialize a process.
    void dontInitialize(Process *p);

    // Run the next process, if there is one.
    void yield();

    // Put a process on the ready list.
    void ready(Process *p);

    // Schedule an update for a given channel.
    void requestUpdate(Channel *c);

    // Run the given process immediately, preempting whatever may be running.
    void
    runNow(Process *p)
    {
        // If a process is running, schedule it/us to run again.
        if (_current)
            readyList.pushFirst(_current);
        // Schedule p to run first.
        readyList.pushFirst(p);
        yield();
    }

    // Set an event queue for scheduling events.
    void setEventQueue(EventQueue *_eq) { eq = _eq; }

    // Get the current time according to gem5.
    Tick getCurTick() { return eq ? eq->getCurTick() : 0; }

    // For scheduling delayed/timed notifications/timeouts.
    void
    schedule(::Event *event, Tick tick)
    {
        pendingTicks[tick]++;

        if (initReady)
            eq->schedule(event, tick);
        else
            eventsToSchedule[event] = tick;
    }

    // For descheduling delayed/timed notifications/timeouts.
    void
    deschedule(::Event *event)
    {
        auto it = pendingTicks.find(event->when());
        if (--it->second == 0)
            pendingTicks.erase(it);

        if (initReady)
            eq->deschedule(event);
        else
            eventsToSchedule.erase(event);
    }

    // Tell the scheduler than an event fired for bookkeeping purposes.
    void
    eventHappened()
    {
        auto it = pendingTicks.begin();
        if (--it->second == 0)
            pendingTicks.erase(it);

        if (starved() && !runToTime)
            scheduleStarvationEvent();
    }

    // Pending activity ignores gem5 activity, much like how a systemc
    // simulation wouldn't know about asynchronous external events (socket IO
    // for instance) that might happen before time advances in a pure
    // systemc simulation. Also the spec lists what specific types of pending
    // activity needs to be counted, which obviously doesn't include gem5
    // events.

    // Return whether there's pending systemc activity at this time.
    bool
    pendingCurr()
    {
        if (!readyList.empty() || !updateList.empty())
            return true;
        return pendingTicks.size() &&
            pendingTicks.begin()->first == getCurTick();
    }

    // Return whether there are pending timed notifications or timeouts.
    bool
    pendingFuture()
    {
        switch (pendingTicks.size()) {
          case 0: return false;
          case 1: return pendingTicks.begin()->first > getCurTick();
          default: return true;
        }
    }

    // Return how many ticks there are until the first pending event, if any.
    Tick
    timeToPending()
    {
        if (!readyList.empty() || !updateList.empty())
            return 0;
        else if (pendingTicks.size())
            return pendingTicks.begin()->first - getCurTick();
        else
            return MaxTick - getCurTick();
    }

    // Run scheduled channel updates.
    void update();

    void setScMainFiber(Fiber *sc_main) { scMain = sc_main; }

    void start(Tick max_tick, bool run_to_time);

    void schedulePause();
    void scheduleStop(bool finish_delta);

    bool paused() { return _paused; }
    bool stopped() { return _stopped; }

  private:
    typedef const EventBase::Priority Priority;
    static Priority DefaultPriority = EventBase::Default_Pri;

    static Priority StopPriority = DefaultPriority - 1;
    static Priority PausePriority = DefaultPriority + 1;
    static Priority MaxTickPriority = DefaultPriority + 2;
    static Priority ReadyPriority = DefaultPriority + 3;
    static Priority StarvationPriority = ReadyPriority;

    EventQueue *eq;
    std::map<Tick, int> pendingTicks;

    void runReady();
    EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;
    void scheduleReadyEvent();

    void pause();
    void stop();
    EventWrapper<Scheduler, &Scheduler::pause> pauseEvent;
    EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
    Fiber *scMain;

    bool
    starved()
    {
        return (readyList.empty() && updateList.empty() &&
                (pendingTicks.empty() ||
                 pendingTicks.begin()->first > maxTick) &&
                initList.empty());
    }
    EventWrapper<Scheduler, &Scheduler::pause> starvationEvent;
    void scheduleStarvationEvent();

    bool _started;
    bool _paused;
    bool _stopped;

    Tick maxTick;
    EventWrapper<Scheduler, &Scheduler::pause> maxTickEvent;

    uint64_t _numCycles;

    Process *_current;

    bool initReady;
    bool runToTime;

    ProcessList initList;
    ProcessList toFinalize;
    ProcessList readyList;

    ChannelList updateList;

    std::map<::Event *, Tick> eventsToSchedule;
};

extern Scheduler scheduler;

} // namespace sc_gem5

#endif // __SYSTEMC_CORE_SCHEDULER_H__
<|endoftext|>


<commit_before>#include <cassert>
#include <cctype>
#ifndef _MSC_VER
#include <dirent.h>
#include <unistd.h>
#include <x86intrin.h>
#else
#include <intrin.h>
#endif
#include <cinttypes>

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <chrono>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#include "linux-perf-events.h"
#ifdef __linux__
#include <libgen.h>
#endif
//#define DEBUG
#include "simdjson/common_defs.h"
#include "simdjson/jsonioutil.h"
#include "simdjson/jsonparser.h"
#include "simdjson/parsedjson.h"
#include "simdjson/stage1_find_marks.h"
#include "simdjson/stage2_build_tape.h"
using namespace std;

int main(int argc, char *argv[]) {
  bool verbose = false;
  bool dump = false;
  bool jsonoutput = false;
  bool forceoneiteration = false;
  bool justdata = false;
#ifndef _MSC_VER
  int c;

  while ((c = getopt(argc, argv, "1vdt")) != -1) {
    switch (c) {
    case 't':
      justdata = true;
      break;
    case 'v':
      verbose = true;
      break;
    case 'd':
      dump = true;
      break;
    case 'j':
      jsonoutput = true;
      break;
    case '1':
      forceoneiteration = true;
      break;
    default:
      abort();
    }
}
#else
  int optind = 1;
#endif
  if (optind >= argc) {
    cerr << "Usage: " << argv[0] << " <jsonfile>" << endl;
    exit(1);
  }
  const char *filename = argv[optind];
  if (optind + 1 < argc) {
    cerr << "warning: ignoring everything after " << argv[optind + 1] << endl;
  }
  if (verbose) {
    cout << "[verbose] loading " << filename << endl;
}
  std::string_view p;
  try {
    p = get_corpus(filename);
  } catch (const std::exception &e) { // caught by reference to base
    std::cout << "Could not load the file " << filename << std::endl;
    return EXIT_FAILURE;
  }
  if (verbose) {
    cout << "[verbose] loaded " << filename << " (" << p.size() << " bytes)"
         << endl;
}
#if defined(DEBUG)
  const uint32_t iterations = 1;
#else
  const uint32_t iterations =
      forceoneiteration ? 1 : (p.size() < 1 * 1000 * 1000 ? 1000 : 10);
#endif
  vector<double> res;
  res.resize(iterations);

#if !defined(__linux__)
#define SQUASH_COUNTERS
  if (justdata) {
    printf("justdata (-t) flag only works under linux.\n");
  }
#endif

#ifndef SQUASH_COUNTERS
  vector<int> evts;
  evts.push_back(PERF_COUNT_HW_CPU_CYCLES);
  evts.push_back(PERF_COUNT_HW_INSTRUCTIONS);
  evts.push_back(PERF_COUNT_HW_BRANCH_MISSES);
  evts.push_back(PERF_COUNT_HW_CACHE_REFERENCES);
  evts.push_back(PERF_COUNT_HW_CACHE_MISSES);
  LinuxEvents<PERF_TYPE_HARDWARE> unified(evts);
  vector<unsigned long long> results;
  results.resize(evts.size());
  unsigned long cy0 = 0, cy1 = 0, cy2 = 0;
  unsigned long cl0 = 0, cl1 = 0, cl2 = 0;
  unsigned long mis0 = 0, mis1 = 0, mis2 = 0;
  unsigned long cref0 = 0, cref1 = 0, cref2 = 0;
  unsigned long cmis0 = 0, cmis1 = 0, cmis2 = 0;
#endif
  bool isok = true;

  for (uint32_t i = 0; i < iterations; i++) {
    if (verbose) {
      cout << "[verbose] iteration # " << i << endl;
}
#ifndef SQUASH_COUNTERS
    unified.start();
#endif
    ParsedJson pj;
    bool allocok = pj.allocateCapacity(p.size());
    if (!allocok) {
      std::cerr << "failed to allocate memory" << std::endl;
      return EXIT_FAILURE;
    }
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy0 += results[0];
    cl0 += results[1];
    mis0 += results[2];
    cref0 += results[3];
    cmis0 += results[4];
#endif
    if (verbose) {
      cout << "[verbose] allocated memory for parsed JSON " << endl;
}

    auto start = std::chrono::steady_clock::now();
#ifndef SQUASH_COUNTERS
    unified.start();
#endif
    isok = find_structural_bits(p.data(), p.size(), pj);
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy1 += results[0];
    cl1 += results[1];
    mis1 += results[2];
    cref1 += results[3];
    cmis1 += results[4];
    if (!isok) {
      cout << "Failed out during stage 1\n";
      break;
    }
    unified.start();
#endif

    isok = isok && !unified_machine(p.data(), p.size(), pj);
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy2 += results[0];
    cl2 += results[1];
    mis2 += results[2];
    cref2 += results[3];
    cmis2 += results[4];
    if (!isok) {
      cout << "Failed out during stage 2\n";
      break;
    }
#endif

    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> secs = end - start;
    res[i] = secs.count();
  }
  ParsedJson pj = build_parsed_json(p); // do the parsing again to get the stats
  if (!pj.isValid()) {
    std::cerr << "Could not parse. " << std::endl;
    return EXIT_FAILURE;
  }
#ifndef SQUASH_COUNTERS
  unsigned long total = cy0 + cy1 + cy2;
  if (justdata) {
    float cpb0 = (double)cy0 / (iterations * p.size());
    float cpb1 = (double)cy1 / (iterations * p.size());
    float cpb2 = (double)cy2 / (iterations * p.size());
    float cpbtotal = (double)total / (iterations * p.size());
    char *newfile = (char *)malloc(strlen(filename) + 1);
    if (newfile == NULL)
      return EXIT_FAILURE;
    ::strcpy(newfile, filename);
    char *snewfile = ::basename(newfile);
    size_t nl = strlen(snewfile);
    for (size_t j = nl - 1; j > 0; j--) {
      if (snewfile[j] == '.') {
        snewfile[j] = '\0';
        break;
      }
    }
    printf("\"%s\"\t%f\t%f\t%f\t%f\n", snewfile, cpb0, cpb1, cpb2,
           cpbtotal);
    free(newfile);
  } else {
    printf("number of bytes %ld number of structural chars %u ratio %.3f\n",
           p.size(), pj.n_structural_indexes,
           (double)pj.n_structural_indexes / p.size());
    printf("mem alloc instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu (cycles/mis.branch %.2f) cache accesses: "
           "%10lu (failure %10lu)\n",
           cl0 / iterations, cy0 / iterations, 100. * cy0 / total,
           (double)cl0 / cy0, mis0 / iterations, (double)cy0 / mis0,
           cref1 / iterations, cmis0 / iterations);
    printf(" mem alloc runs at %.2f cycles per input byte.\n",
           (double)cy0 / (iterations * p.size()));
    printf("stage 1 instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu (cycles/mis.branch %.2f) cache accesses: "
           "%10lu (failure %10lu)\n",
           cl1 / iterations, cy1 / iterations, 100. * cy1 / total,
           (double)cl1 / cy1, mis1 / iterations, (double)cy1 / mis1,
           cref1 / iterations, cmis1 / iterations);
    printf(" stage 1 runs at %.2f cycles per input byte.\n",
           (double)cy1 / (iterations * p.size()));

    printf("stage 2 instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu  (cycles/mis.branch %.2f)  cache "
           "accesses: %10lu (failure %10lu)\n",
           cl2 / iterations, cy2 / iterations, 100. * cy2 / total,
           (double)cl2 / cy2, mis2 / iterations, (double)cy2 / mis2,
           cref2 / iterations, cmis2 / iterations);
    printf(" stage 2 runs at %.2f cycles per input byte and ",
           (double)cy2 / (iterations * p.size()));
    printf("%.2f cycles per structural character.\n",
           (double)cy2 / (iterations * pj.n_structural_indexes));

    printf(" all stages: %.2f cycles per input byte.\n",
           (double)total / (iterations * p.size()));
  }
#endif
  double min_result = *min_element(res.begin(), res.end());
  if (!justdata) {
    cout << "Min:  " << min_result << " bytes read: " << p.size()
         << " Gigabytes/second: " << (p.size()) / (min_result * 1000000000.0)
         << "\n";
}
  if (jsonoutput) {
    isok = isok && pj.printjson(std::cout);
  }
  if (dump) {
    isok = isok && pj.dump_raw_tape(std::cout);
  }
  aligned_free((void *)p.data());
  if (!isok) {
    fprintf(stderr, " Parsing failed. \n ");
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<commit_msg>benchmark/parse.cpp doesn't need intrinsics for itself.<commit_after>#include <cassert>
#include <cctype>
#ifndef _MSC_VER
#include <dirent.h>
#include <unistd.h>
#endif
#include <cinttypes>

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <chrono>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#include "linux-perf-events.h"
#ifdef __linux__
#include <libgen.h>
#endif
//#define DEBUG
#include "simdjson/common_defs.h"
#include "simdjson/jsonioutil.h"
#include "simdjson/jsonparser.h"
#include "simdjson/parsedjson.h"
#include "simdjson/stage1_find_marks.h"
#include "simdjson/stage2_build_tape.h"
using namespace std;

int main(int argc, char *argv[]) {
  bool verbose = false;
  bool dump = false;
  bool jsonoutput = false;
  bool forceoneiteration = false;
  bool justdata = false;
#ifndef _MSC_VER
  int c;

  while ((c = getopt(argc, argv, "1vdt")) != -1) {
    switch (c) {
    case 't':
      justdata = true;
      break;
    case 'v':
      verbose = true;
      break;
    case 'd':
      dump = true;
      break;
    case 'j':
      jsonoutput = true;
      break;
    case '1':
      forceoneiteration = true;
      break;
    default:
      abort();
    }
}
#else
  int optind = 1;
#endif
  if (optind >= argc) {
    cerr << "Usage: " << argv[0] << " <jsonfile>" << endl;
    exit(1);
  }
  const char *filename = argv[optind];
  if (optind + 1 < argc) {
    cerr << "warning: ignoring everything after " << argv[optind + 1] << endl;
  }
  if (verbose) {
    cout << "[verbose] loading " << filename << endl;
}
  std::string_view p;
  try {
    p = get_corpus(filename);
  } catch (const std::exception &e) { // caught by reference to base
    std::cout << "Could not load the file " << filename << std::endl;
    return EXIT_FAILURE;
  }
  if (verbose) {
    cout << "[verbose] loaded " << filename << " (" << p.size() << " bytes)"
         << endl;
}
#if defined(DEBUG)
  const uint32_t iterations = 1;
#else
  const uint32_t iterations =
      forceoneiteration ? 1 : (p.size() < 1 * 1000 * 1000 ? 1000 : 10);
#endif
  vector<double> res;
  res.resize(iterations);

#if !defined(__linux__)
#define SQUASH_COUNTERS
  if (justdata) {
    printf("justdata (-t) flag only works under linux.\n");
  }
#endif

#ifndef SQUASH_COUNTERS
  vector<int> evts;
  evts.push_back(PERF_COUNT_HW_CPU_CYCLES);
  evts.push_back(PERF_COUNT_HW_INSTRUCTIONS);
  evts.push_back(PERF_COUNT_HW_BRANCH_MISSES);
  evts.push_back(PERF_COUNT_HW_CACHE_REFERENCES);
  evts.push_back(PERF_COUNT_HW_CACHE_MISSES);
  LinuxEvents<PERF_TYPE_HARDWARE> unified(evts);
  vector<unsigned long long> results;
  results.resize(evts.size());
  unsigned long cy0 = 0, cy1 = 0, cy2 = 0;
  unsigned long cl0 = 0, cl1 = 0, cl2 = 0;
  unsigned long mis0 = 0, mis1 = 0, mis2 = 0;
  unsigned long cref0 = 0, cref1 = 0, cref2 = 0;
  unsigned long cmis0 = 0, cmis1 = 0, cmis2 = 0;
#endif
  bool isok = true;

  for (uint32_t i = 0; i < iterations; i++) {
    if (verbose) {
      cout << "[verbose] iteration # " << i << endl;
}
#ifndef SQUASH_COUNTERS
    unified.start();
#endif
    ParsedJson pj;
    bool allocok = pj.allocateCapacity(p.size());
    if (!allocok) {
      std::cerr << "failed to allocate memory" << std::endl;
      return EXIT_FAILURE;
    }
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy0 += results[0];
    cl0 += results[1];
    mis0 += results[2];
    cref0 += results[3];
    cmis0 += results[4];
#endif
    if (verbose) {
      cout << "[verbose] allocated memory for parsed JSON " << endl;
}

    auto start = std::chrono::steady_clock::now();
#ifndef SQUASH_COUNTERS
    unified.start();
#endif
    isok = find_structural_bits(p.data(), p.size(), pj);
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy1 += results[0];
    cl1 += results[1];
    mis1 += results[2];
    cref1 += results[3];
    cmis1 += results[4];
    if (!isok) {
      cout << "Failed out during stage 1\n";
      break;
    }
    unified.start();
#endif

    isok = isok && !unified_machine(p.data(), p.size(), pj);
#ifndef SQUASH_COUNTERS
    unified.end(results);
    cy2 += results[0];
    cl2 += results[1];
    mis2 += results[2];
    cref2 += results[3];
    cmis2 += results[4];
    if (!isok) {
      cout << "Failed out during stage 2\n";
      break;
    }
#endif

    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> secs = end - start;
    res[i] = secs.count();
  }
  ParsedJson pj = build_parsed_json(p); // do the parsing again to get the stats
  if (!pj.isValid()) {
    std::cerr << "Could not parse. " << std::endl;
    return EXIT_FAILURE;
  }
#ifndef SQUASH_COUNTERS
  unsigned long total = cy0 + cy1 + cy2;
  if (justdata) {
    float cpb0 = (double)cy0 / (iterations * p.size());
    float cpb1 = (double)cy1 / (iterations * p.size());
    float cpb2 = (double)cy2 / (iterations * p.size());
    float cpbtotal = (double)total / (iterations * p.size());
    char *newfile = (char *)malloc(strlen(filename) + 1);
    if (newfile == NULL)
      return EXIT_FAILURE;
    ::strcpy(newfile, filename);
    char *snewfile = ::basename(newfile);
    size_t nl = strlen(snewfile);
    for (size_t j = nl - 1; j > 0; j--) {
      if (snewfile[j] == '.') {
        snewfile[j] = '\0';
        break;
      }
    }
    printf("\"%s\"\t%f\t%f\t%f\t%f\n", snewfile, cpb0, cpb1, cpb2,
           cpbtotal);
    free(newfile);
  } else {
    printf("number of bytes %ld number of structural chars %u ratio %.3f\n",
           p.size(), pj.n_structural_indexes,
           (double)pj.n_structural_indexes / p.size());
    printf("mem alloc instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu (cycles/mis.branch %.2f) cache accesses: "
           "%10lu (failure %10lu)\n",
           cl0 / iterations, cy0 / iterations, 100. * cy0 / total,
           (double)cl0 / cy0, mis0 / iterations, (double)cy0 / mis0,
           cref1 / iterations, cmis0 / iterations);
    printf(" mem alloc runs at %.2f cycles per input byte.\n",
           (double)cy0 / (iterations * p.size()));
    printf("stage 1 instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu (cycles/mis.branch %.2f) cache accesses: "
           "%10lu (failure %10lu)\n",
           cl1 / iterations, cy1 / iterations, 100. * cy1 / total,
           (double)cl1 / cy1, mis1 / iterations, (double)cy1 / mis1,
           cref1 / iterations, cmis1 / iterations);
    printf(" stage 1 runs at %.2f cycles per input byte.\n",
           (double)cy1 / (iterations * p.size()));

    printf("stage 2 instructions: %10lu cycles: %10lu (%.2f %%) ins/cycles: "
           "%.2f mis. branches: %10lu  (cycles/mis.branch %.2f)  cache "
           "accesses: %10lu (failure %10lu)\n",
           cl2 / iterations, cy2 / iterations, 100. * cy2 / total,
           (double)cl2 / cy2, mis2 / iterations, (double)cy2 / mis2,
           cref2 / iterations, cmis2 / iterations);
    printf(" stage 2 runs at %.2f cycles per input byte and ",
           (double)cy2 / (iterations * p.size()));
    printf("%.2f cycles per structural character.\n",
           (double)cy2 / (iterations * pj.n_structural_indexes));

    printf(" all stages: %.2f cycles per input byte.\n",
           (double)total / (iterations * p.size()));
  }
#endif
  double min_result = *min_element(res.begin(), res.end());
  if (!justdata) {
    cout << "Min:  " << min_result << " bytes read: " << p.size()
         << " Gigabytes/second: " << (p.size()) / (min_result * 1000000000.0)
         << "\n";
}
  if (jsonoutput) {
    isok = isok && pj.printjson(std::cout);
  }
  if (dump) {
    isok = isok && pj.dump_raw_tape(std::cout);
  }
  aligned_free((void *)p.data());
  if (!isok) {
    fprintf(stderr, " Parsing failed. \n ");
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>planning: update scenario status member field to make scenario transfor work.<commit_after><|endoftext|>


<commit_before>#include "types/hit_record.hpp"

#include <limits>
#include <iostream>
#include <sstream>

using std::numeric_limits;
using std::string;
using std::stringstream;
using std::endl;

namespace fr {

HitRecord::HitRecord(uint32_t worker, uint32_t mesh) :
 worker(worker),
 mesh(mesh),
 geom(geom) {
    t = numeric_limits<float>::infinity();
}

HitRecord::HitRecord(uint32_t worker, uint32_t mesh, float t) :
 worker(worker),
 mesh(mesh),
 t(t),
 geom(geom) {}

HitRecord::HitRecord() :
 geom() {
    worker = numeric_limits<uint32_t>::max();
    mesh = numeric_limits<uint32_t>::max();
    t = numeric_limits<float>::infinity();
}

string ToString(const HitRecord& strong, const string& indent) {
    stringstream stream;
    string pad = indent + "| ";
    stream << "HitRecord {" << endl <<
     indent << "| worker = " << strong.worker << endl <<
     indent << "| mesh = " << strong.mesh << endl <<
     indent << "| t = " << strong.t << endl <<
     indent << "| geom = " << ToString(strong.geom, pad) <<
     indent << "}";
    return stream.str();
}

} // namespace fr
<commit_msg>Weird default initialization of local geometry.<commit_after>#include "types/hit_record.hpp"

#include <limits>
#include <iostream>
#include <sstream>

using std::numeric_limits;
using std::string;
using std::stringstream;
using std::endl;

namespace fr {

HitRecord::HitRecord(uint32_t worker, uint32_t mesh) :
 worker(worker),
 mesh(mesh),
 geom() {
    t = numeric_limits<float>::infinity();
}

HitRecord::HitRecord(uint32_t worker, uint32_t mesh, float t) :
 worker(worker),
 mesh(mesh),
 t(t),
 geom() {}

HitRecord::HitRecord() :
 geom() {
    worker = numeric_limits<uint32_t>::max();
    mesh = numeric_limits<uint32_t>::max();
    t = numeric_limits<float>::infinity();
}

string ToString(const HitRecord& strong, const string& indent) {
    stringstream stream;
    string pad = indent + "| ";
    stream << "HitRecord {" << endl <<
     indent << "| worker = " << strong.worker << endl <<
     indent << "| mesh = " << strong.mesh << endl <<
     indent << "| t = " << strong.t << endl <<
     indent << "| geom = " << ToString(strong.geom, pad) <<
     indent << "}";
    return stream.str();
}

} // namespace fr
<|endoftext|>