<commit_before>#pragma once
#include <map>
#include "string_utils.hpp"
#include "request.hpp"
#include "utils.hpp"
#include <boost/lexical_cast.hpp>
class token_parser
{
	std::vector<std::string> v_; //解析之后，v_的第一个元素为函数名，后面的元素均为参数.
	std::map<std::string, std::vector<std::string>> map_;
public:
	/*
	get("/hello/:name", (request, response) -> {
		return "Hello: " + request.params(":name");
	});
	hello/a/b->hello/a/b();hello/a(b);hello(a, b);
	*/
	//token_parser(std::string& s, char seperator)
	//{
	//	v_ = StringUtil::split(s, seperator);
	//}

	token_parser() = default;

	void add(const std::string& path, std::vector<std::string>& v)
	{
		map_.emplace(path, std::move(v));
	}

	const std::map<std::string, std::vector<std::string>>& get_map()
	{
		return map_;
	}

	void parse(cinatra::Request& req, const std::map<std::string, std::vector<std::string>>& kv)
	{
		string path = req.path();
 		if (kv.empty())
 		{
			if (path == "/")
			{
				v_.push_back(std::move(path));
				return;
			}

 			v_ = StringUtil::split(path, '/', 1);
 			return;
 		}

		v_.push_back(std::move(path));
		for (auto it : kv)
		{
			if (it.second.size() != req.query().size())
				continue;

			for (auto& itv : it.second)
			{
				auto& val = req.query().get_val(itv);
				if (val.empty())
					break;

				v_.push_back(val);
			}

			break;
		}
	}

	void parse(std::string& params)
	{
		v_ = StringUtil::split(params, '/');
	}

public:
	std::string get_function_name()
	{
		if (v_.empty())
			return "";

		auto it = v_.begin();
		std::string name = *it;
		v_.erase(it);
		return name;
	}

	template<typename RequestedType>
	bool get(typename std::decay<RequestedType>::type& param)
	{
		if (v_.empty())
		{
			LOG_DBG << "Params is invalid ";
			return false;
		}

		try
		{
			typedef typename std::decay<RequestedType>::type result_type;
			auto const & v = v_.back();
			param = boost::lexical_cast<typename std::decay<result_type>::type>(v);
			v_.pop_back();
			return true;
		}
		catch (std::exception& e)
		{
			LOG_DBG << "Error in param converting: " << e.what();
		}
		return false;
	}

	bool empty(){ return v_.empty(); }

	size_t size() const
	{
		return v_.size();
	}
};
<commit_msg>修改parse<commit_after>#pragma once
#include <map>
#include "string_utils.hpp"
#include "request.hpp"
#include "utils.hpp"
#include <boost/lexical_cast.hpp>
class token_parser
{
	std::vector<std::string> v_; //解析之后，v_的第一个元素为函数名，后面的元素均为参数.
	std::map<std::string, std::vector<std::string>> map_;
public:
	/*
	get("/hello/:name", (request, response) -> {
		return "Hello: " + request.params(":name");
	});
	hello/a/b->hello/a/b();hello/a(b);hello(a, b);
	*/
	//token_parser(std::string& s, char seperator)
	//{
	//	v_ = StringUtil::split(s, seperator);
	//}

	token_parser() = default;

	void add(const std::string& path, std::vector<std::string>& v)
	{
		map_.emplace(path, std::move(v));
	}

	const std::map<std::string, std::vector<std::string>>& get_map()
	{
		return map_;
	}

	void parse(cinatra::Request& req, const std::map<std::string, std::vector<std::string>>& kv)
	{
		string path = req.path();
 		if (kv.empty())
 		{
			if (path == "/")
			{
				v_.push_back(std::move(path));
				return;
			}

			if (req.query().empty())
 				v_ = StringUtil::split(path, '/', 1);

 			return;
 		}

		v_.push_back(std::move(path));
		for (auto it : kv)
		{
			if (it.second.size() != req.query().size())
				continue;

			for (auto& itv : it.second)
			{
				auto& val = req.query().get_val(itv);
				if (val.empty())
					break;

				v_.push_back(val);
			}

			break;
		}
	}

	void parse(std::string& params)
	{
		v_ = StringUtil::split(params, '/');
	}

public:
	std::string get_function_name()
	{
		if (v_.empty())
			return "";

		auto it = v_.begin();
		std::string name = *it;
		v_.erase(it);
		return name;
	}

	template<typename RequestedType>
	bool get(typename std::decay<RequestedType>::type& param)
	{
		if (v_.empty())
		{
			LOG_DBG << "Params is invalid ";
			return false;
		}

		try
		{
			typedef typename std::decay<RequestedType>::type result_type;
			auto const & v = v_.back();
			param = boost::lexical_cast<typename std::decay<result_type>::type>(v);
			v_.pop_back();
			return true;
		}
		catch (std::exception& e)
		{
			LOG_DBG << "Error in param converting: " << e.what();
		}
		return false;
	}

	bool empty(){ return v_.empty(); }

	size_t size() const
	{
		return v_.size();
	}
};
<|endoftext|>


<commit_before>#ifndef TIMER_HPP_
#define TIMER_HPP_

#include <boost/chrono/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <boost/chrono/system_clocks.hpp>

namespace clotho {
namespace utility {

typedef boost::chrono::high_resolution_clock    clock_type;
typedef clock_type::time_point                  time_point_type;
typedef clock_type::duration                    duration_type;

/*!  Basic timer class */
class timer {
public:

    static constexpr double hertz = (double)clock_type::period::num/clock_type::period::den;
    timer() : m_start( clock_type::now() ), m_end( time_point_type::max() ) {}

    /**
     * (re)start the timer
     */
    inline void start() {
        m_end = time_point_type::max();
        m_start = clock_type::now();
    }

    /**
     *  stop the timer
     */
    inline void stop() {
        m_end = clock_type::now();
    }

    /**
     * Calculates the elapsed time
     *
     * If the timer has been stopped, then the elasped time is stop - start.
     * Otherwise, the elapsed time is the time between "now" and the last start.
     *
     * \return elasped time
     * \note This does not stop a running timer
     */
    duration_type elapsed() const {
        time_point_type t = ((m_end == time_point_type::max()) ? clock_type::now() : m_end);
        return (t - m_start);
    }

    virtual ~timer() {}
protected:
    time_point_type m_start, m_end;
};

}   // namespace utility
}   // namespace clotho
#endif  // TIMER_HPP_
<commit_msg>Added method to get count directly from computed duration<commit_after>#ifndef TIMER_HPP_
#define TIMER_HPP_

#include <boost/chrono/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <boost/chrono/system_clocks.hpp>

namespace clotho {
namespace utility {

typedef boost::chrono::high_resolution_clock    clock_type;
typedef clock_type::time_point                  time_point_type;
typedef clock_type::duration                    duration_type;

/*!  Basic timer class */
class timer {
public:

    static constexpr double hertz = (double)clock_type::period::num/clock_type::period::den;
    timer() : m_start( clock_type::now() ), m_end( time_point_type::max() ) {}

    /**
     * (re)start the timer
     */
    inline void start() {
        m_end = time_point_type::max();
        m_start = clock_type::now();
    }

    /**
     *  stop the timer
     */
    inline void stop() {
        m_end = clock_type::now();
    }

    /**
     * Calculates the elapsed time
     *
     * If the timer has been stopped, then the elasped time is stop - start.
     * Otherwise, the elapsed time is the time between "now" and the last start.
     *
     * \return elasped time
     * \note This does not stop a running timer
     */
    duration_type elapsed() const {
        time_point_type t = ((m_end == time_point_type::max()) ? clock_type::now() : m_end);
        return (t - m_start);
    }

    unsigned long elapsed_long() const {
        time_point_type t = ((m_end == time_point_type::max()) ? clock_type::now() : m_end);
        return (t - m_start).count();
    }

    virtual ~timer() {}
protected:
    time_point_type m_start, m_end;
};

}   // namespace utility
}   // namespace clotho
#endif  // TIMER_HPP_
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "cuda_runtime.h"

namespace etl {

namespace impl {

namespace cuda {

template <typename T>
struct cuda_memory {
    T* memory;

    cuda_memory(T* memory) : memory(memory) {}

    //Delete copy operations
    cuda_memory(cuda_memory& rhs){
        cpp_assert(!is_set(), "copy of cuda_memory is only possible when not allocated");
        cpp_assert(!rhs.is_set(), "copy of cuda_memory is only possible when not allocated");
    }

    cuda_memory& operator=(cuda_memory& rhs){
        cpp_assert(!is_set(), "copy of cuda_memory is only possible when not allocated");
        cpp_assert(!rhs.is_set(), "copy of cuda_memory is only possible when not allocated");

        return *this;
    }

    cuda_memory(cuda_memory&& rhs) : memory(rhs.memory){
        rhs.memory = nullptr;
    }

    cuda_memory& operator=(cuda_memory&& rhs){
        if(memory){
            cudaFree(memory);
        }

        memory = rhs.memory;
        rhs.memory = nullptr;

        return *this;
    }

    cuda_memory& operator=(T* new_memory){
        if(memory){
            cudaFree(memory);
        }

        memory = new_memory;

        return *this;
    }

    T* get() const {
        return memory;
    }

    bool is_set() const {
        return memory;
    }

    void reset(){
        if(memory){
            cudaFree(memory);
        }

        memory = nullptr;
    }

    ~cuda_memory() {
        if(memory){
            cudaFree(memory);
        }
    }
};

template <typename E>
auto cuda_allocate(const E& expr, bool copy = false) -> cuda_memory<value_t<E>> {
    value_t<E>* memory;

    auto cuda_status = cudaMalloc(&memory, etl::size(expr) * sizeof(value_t<E>));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << etl::size(expr) * sizeof(value_t<E>) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, expr.memory_start(), etl::size(expr) * sizeof(value_t<E>), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(const E& expr) -> cuda_memory<value_t<E>> {
    return cuda_allocate(expr, true);
}

template <typename E>
auto cuda_allocate(E* ptr, std::size_t n, bool copy = false) -> cuda_memory<E> {
    E* memory;

    auto cuda_status = cudaMalloc(&memory, n * sizeof(E));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << n * sizeof(E) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, ptr, n * sizeof(E), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(E* ptr, std::size_t n) -> cuda_memory<E> {
    return cuda_allocate(ptr, n, true);
}

} //end of namespace cublas

} //end of namespace impl

} //end of namespace etl
<commit_msg>Fix constness<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "cuda_runtime.h"

namespace etl {

namespace impl {

namespace cuda {

template <typename T>
struct cuda_memory {
    T* memory;

    cuda_memory(T* memory) : memory(memory) {}

    //Delete copy operations
    cuda_memory(const cuda_memory& rhs){
        cpp_assert(!is_set(), "copy of cuda_memory is only possible when not allocated");
        cpp_assert(!rhs.is_set(), "copy of cuda_memory is only possible when not allocated");
    }

    cuda_memory& operator=(const cuda_memory& rhs){
        cpp_assert(!is_set(), "copy of cuda_memory is only possible when not allocated");
        cpp_assert(!rhs.is_set(), "copy of cuda_memory is only possible when not allocated");

        return *this;
    }

    cuda_memory(cuda_memory&& rhs) : memory(rhs.memory){
        rhs.memory = nullptr;
    }

    cuda_memory& operator=(cuda_memory&& rhs){
        if(memory){
            cudaFree(memory);
        }

        memory = rhs.memory;
        rhs.memory = nullptr;

        return *this;
    }

    cuda_memory& operator=(T* new_memory){
        if(memory){
            cudaFree(memory);
        }

        memory = new_memory;

        return *this;
    }

    T* get() const {
        return memory;
    }

    bool is_set() const {
        return memory;
    }

    void reset(){
        if(memory){
            cudaFree(memory);
        }

        memory = nullptr;
    }

    ~cuda_memory() {
        if(memory){
            cudaFree(memory);
        }
    }
};

template <typename E>
auto cuda_allocate(const E& expr, bool copy = false) -> cuda_memory<value_t<E>> {
    value_t<E>* memory;

    auto cuda_status = cudaMalloc(&memory, etl::size(expr) * sizeof(value_t<E>));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << etl::size(expr) * sizeof(value_t<E>) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, expr.memory_start(), etl::size(expr) * sizeof(value_t<E>), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(const E& expr) -> cuda_memory<value_t<E>> {
    return cuda_allocate(expr, true);
}

template <typename E>
auto cuda_allocate(E* ptr, std::size_t n, bool copy = false) -> cuda_memory<E> {
    E* memory;

    auto cuda_status = cudaMalloc(&memory, n * sizeof(E));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << n * sizeof(E) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, ptr, n * sizeof(E), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(E* ptr, std::size_t n) -> cuda_memory<E> {
    return cuda_allocate(ptr, n, true);
}

} //end of namespace cublas

} //end of namespace impl

} //end of namespace etl
<|endoftext|>


<commit_before><commit_msg>Register chrome-extension as a secure scheme so that adding resources from an extension doesn't trip the mixed content sensor.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2010 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.

#if defined(OS_MACOSX)
#include <signal.h>
#include <unistd.h>
#endif  // OS_MACOSX

#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/i18n/rtl.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/metrics/field_trial.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gfx_resource_provider.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/net/net_resource_provider.h"
#include "chrome/common/pepper_plugin_registry.h"
#include "chrome/renderer/renderer_main_platform_delegate.h"
#include "chrome/renderer/render_process_impl.h"
#include "chrome/renderer/render_thread.h"
#include "content/common/main_function_params.h"
#include "content/common/hi_res_timer_manager.h"
#include "grit/generated_resources.h"
#include "net/base/net_module.h"
#include "ui/base/system_monitor/system_monitor.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/gfx_module.h"

#if defined(OS_MACOSX)
#include "base/eintr_wrapper.h"
#include "chrome/app/breakpad_mac.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#endif  // OS_MACOSX

#if defined(OS_MACOSX)
namespace {

// TODO(viettrungluu): crbug.com/28547: The following signal handling is needed,
// as a stopgap, to avoid leaking due to not releasing Breakpad properly.
// Without this problem, this could all be eliminated. Remove when Breakpad is
// fixed?
// TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing).
// The code should be properly shared (or this code should be eliminated).
int g_shutdown_pipe_write_fd = -1;

void SIGTERMHandler(int signal) {
  RAW_CHECK(signal == SIGTERM);
  RAW_LOG(INFO, "Handling SIGTERM in renderer.");

  // Reinstall the default handler.  We had one shot at graceful shutdown.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_DFL;
  CHECK(sigaction(signal, &action, NULL) == 0);

  RAW_CHECK(g_shutdown_pipe_write_fd != -1);
  size_t bytes_written = 0;
  do {
    int rv = HANDLE_EINTR(
        write(g_shutdown_pipe_write_fd,
              reinterpret_cast<const char*>(&signal) + bytes_written,
              sizeof(signal) - bytes_written));
    RAW_CHECK(rv >= 0);
    bytes_written += rv;
  } while (bytes_written < sizeof(signal));

  RAW_LOG(INFO, "Wrote signal to shutdown pipe.");
}

class ShutdownDetector : public base::PlatformThread::Delegate {
 public:
  explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) {
    CHECK(shutdown_fd_ != -1);
  }

  virtual void ThreadMain() {
    int signal;
    size_t bytes_read = 0;
    ssize_t ret;
    do {
      ret = HANDLE_EINTR(
          read(shutdown_fd_,
               reinterpret_cast<char*>(&signal) + bytes_read,
               sizeof(signal) - bytes_read));
      if (ret < 0) {
        NOTREACHED() << "Unexpected error: " << strerror(errno);
        break;
      } else if (ret == 0) {
        NOTREACHED() << "Unexpected closure of shutdown pipe.";
        break;
      }
      bytes_read += ret;
    } while (bytes_read < sizeof(signal));

    if (bytes_read == sizeof(signal))
      VLOG(1) << "Handling shutdown for signal " << signal << ".";
    else
      VLOG(1) << "Handling shutdown for unknown signal.";

    // Clean up Breakpad if necessary.
    if (IsCrashReporterEnabled()) {
      VLOG(1) << "Cleaning up Breakpad.";
      DestructCrashReporter();
    } else {
      VLOG(1) << "Breakpad not enabled; no clean-up needed.";
    }

    // Something went seriously wrong, so get out.
    if (bytes_read != sizeof(signal)) {
      LOG(WARNING) << "Failed to get signal. Quitting ungracefully.";
      _exit(1);
    }

    // Re-raise the signal.
    kill(getpid(), signal);

    // The signal may be handled on another thread. Give that a chance to
    // happen.
    sleep(3);

    // We really should be dead by now.  For whatever reason, we're not. Exit
    // immediately, with the exit status set to the signal number with bit 8
    // set.  On the systems that we care about, this exit status is what is
    // normally used to indicate an exit by this signal's default handler.
    // This mechanism isn't a de jure standard, but even in the worst case, it
    // should at least result in an immediate exit.
    LOG(WARNING) << "Still here, exiting really ungracefully.";
    _exit(signal | (1 << 7));
  }

 private:
  const int shutdown_fd_;

  DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
};

}  // namespace
#endif  // OS_MACOSX

// This function provides some ways to test crash and assertion handling
// behavior of the renderer.
static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
  // This parameter causes an assertion.
  if (command_line.HasSwitch(switches::kRendererAssertTest)) {
    DCHECK(false);
  }

#if !defined(OFFICIAL_BUILD)
  // This parameter causes an assertion too.
  if (command_line.HasSwitch(switches::kRendererCheckFalseTest)) {
    CHECK(false);
  }
#endif  // !defined(OFFICIAL_BUILD)

  // This parameter causes a null pointer crash (crash reporter trigger).
  if (command_line.HasSwitch(switches::kRendererCrashTest)) {
    int* bad_pointer = NULL;
    *bad_pointer = 0;
  }

  if (command_line.HasSwitch(switches::kRendererStartupDialog)) {
    ChildProcess::WaitForDebugger("Renderer");
  }
}

// mainline routine for running as the Renderer process
int RendererMain(const MainFunctionParams& parameters) {
  TRACE_EVENT_BEGIN("RendererMain", 0, "");

  const CommandLine& parsed_command_line = parameters.command_line_;
  base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;

#if defined(OS_MACOSX)
  // TODO(viettrungluu): Code taken from browser_main.cc.
  int pipefd[2];
  int ret = pipe(pipefd);
  if (ret < 0) {
    PLOG(DFATAL) << "Failed to create pipe";
  } else {
    int shutdown_pipe_read_fd = pipefd[0];
    g_shutdown_pipe_write_fd = pipefd[1];
    const size_t kShutdownDetectorThreadStackSize = 4096;
    if (!base::PlatformThread::CreateNonJoinable(
            kShutdownDetectorThreadStackSize,
            new ShutdownDetector(shutdown_pipe_read_fd))) {
      LOG(DFATAL) << "Failed to create shutdown detector task.";
    }
  }

  // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking
  // Mach ports.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGTERMHandler;
  CHECK(sigaction(SIGTERM, &action, NULL) == 0);
#endif  // OS_MACOSX

#if defined(OS_CHROMEOS)
  // As Zygote process starts up earlier than browser process gets its own
  // locale (at login time for Chrome OS), we have to set the ICU default
  // locale for renderer process here.
  // ICU locale will be used for fallback font selection etc.
  if (parsed_command_line.HasSwitch(switches::kLang)) {
    const std::string locale =
        parsed_command_line.GetSwitchValueASCII(switches::kLang);
    base::i18n::SetICUDefaultLocale(locale);
  }
#endif

  // Configure modules that need access to resources.
  net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
  gfx::GfxModule::SetResourceProvider(chrome::GfxResourceProvider);

  // This function allows pausing execution using the --renderer-startup-dialog
  // flag allowing us to attach a debugger.
  // Do not move this function down since that would mean we can't easily debug
  // whatever occurs before it.
  HandleRendererErrorTestParameters(parsed_command_line);

  RendererMainPlatformDelegate platform(parameters);

  base::StatsScope<base::StatsCounterTimer>
      startup_timer(chrome::Counters::renderer_main());

#if defined(OS_MACOSX)
  // As long as we use Cocoa in the renderer (for the forseeable future as of
  // now; see http://crbug.com/13890 for info) we need to have a UI loop.
  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
#else
  // The main message loop of the renderer services doesn't have IO or UI tasks,
  // unless in-process-plugins is used.
  MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
              MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
#endif

  base::PlatformThread::SetName("CrRendererMain");

  ui::SystemMonitor system_monitor;
  HighResolutionTimerManager hi_res_timer_manager;

  platform.PlatformInitialize();

  bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
  platform.InitSandboxTests(no_sandbox);

  // Initialize histogram statistics gathering system.
  // Don't create StatisticsRecorder in the single process mode.
  scoped_ptr<base::StatisticsRecorder> statistics;
  if (!base::StatisticsRecorder::IsActive()) {
    statistics.reset(new base::StatisticsRecorder());
  }

  // Initialize statistical testing infrastructure.
  base::FieldTrialList field_trial;
  // Ensure any field trials in browser are reflected into renderer.
  if (parsed_command_line.HasSwitch(switches::kForceFieldTestNameAndValue)) {
    std::string persistent = parsed_command_line.GetSwitchValueASCII(
        switches::kForceFieldTestNameAndValue);
    bool ret = field_trial.CreateTrialsInChildProcess(persistent);
    DCHECK(ret);
  }

  // Load pepper plugins before engaging the sandbox.
  PepperPluginRegistry::GetInstance();

  {
#if !defined(OS_LINUX)
    // TODO(markus): Check if it is OK to unconditionally move this
    // instruction down.
    RenderProcessImpl render_process;
    render_process.set_main_thread(new RenderThread());
#endif
    bool run_loop = true;
    if (!no_sandbox) {
      run_loop = platform.EnableSandbox();
    } else {
      LOG(ERROR) << "Running without renderer sandbox";
    }
#if defined(OS_LINUX)
    RenderProcessImpl render_process;
    render_process.set_main_thread(new RenderThread());
#endif

    platform.RunSandboxTests();

    startup_timer.Stop();  // End of Startup Time Measurement.

    if (run_loop) {
      if (pool)
        pool->Recycle();
      TRACE_EVENT_BEGIN("RendererMain.START_MSG_LOOP", 0, 0);
      MessageLoop::current()->Run();
      TRACE_EVENT_END("RendererMain.START_MSG_LOOP", 0, 0);
    }
  }
  platform.PlatformUninitialize();
  TRACE_EVENT_END("RendererMain", 0, "");
  return 0;
}
<commit_msg>Add a histogram to measure task execution time for the render thread.<commit_after>// Copyright (c) 2010 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.

#if defined(OS_MACOSX)
#include <signal.h>
#include <unistd.h>
#endif  // OS_MACOSX

#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/i18n/rtl.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/metrics/field_trial.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gfx_resource_provider.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/net/net_resource_provider.h"
#include "chrome/common/pepper_plugin_registry.h"
#include "chrome/renderer/renderer_main_platform_delegate.h"
#include "chrome/renderer/render_process_impl.h"
#include "chrome/renderer/render_thread.h"
#include "content/common/main_function_params.h"
#include "content/common/hi_res_timer_manager.h"
#include "grit/generated_resources.h"
#include "net/base/net_module.h"
#include "ui/base/system_monitor/system_monitor.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/gfx_module.h"

#if defined(OS_MACOSX)
#include "base/eintr_wrapper.h"
#include "chrome/app/breakpad_mac.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#endif  // OS_MACOSX

#if defined(OS_MACOSX)
namespace {

// TODO(viettrungluu): crbug.com/28547: The following signal handling is needed,
// as a stopgap, to avoid leaking due to not releasing Breakpad properly.
// Without this problem, this could all be eliminated. Remove when Breakpad is
// fixed?
// TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing).
// The code should be properly shared (or this code should be eliminated).
int g_shutdown_pipe_write_fd = -1;

void SIGTERMHandler(int signal) {
  RAW_CHECK(signal == SIGTERM);
  RAW_LOG(INFO, "Handling SIGTERM in renderer.");

  // Reinstall the default handler.  We had one shot at graceful shutdown.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_DFL;
  CHECK(sigaction(signal, &action, NULL) == 0);

  RAW_CHECK(g_shutdown_pipe_write_fd != -1);
  size_t bytes_written = 0;
  do {
    int rv = HANDLE_EINTR(
        write(g_shutdown_pipe_write_fd,
              reinterpret_cast<const char*>(&signal) + bytes_written,
              sizeof(signal) - bytes_written));
    RAW_CHECK(rv >= 0);
    bytes_written += rv;
  } while (bytes_written < sizeof(signal));

  RAW_LOG(INFO, "Wrote signal to shutdown pipe.");
}

class ShutdownDetector : public base::PlatformThread::Delegate {
 public:
  explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) {
    CHECK(shutdown_fd_ != -1);
  }

  virtual void ThreadMain() {
    int signal;
    size_t bytes_read = 0;
    ssize_t ret;
    do {
      ret = HANDLE_EINTR(
          read(shutdown_fd_,
               reinterpret_cast<char*>(&signal) + bytes_read,
               sizeof(signal) - bytes_read));
      if (ret < 0) {
        NOTREACHED() << "Unexpected error: " << strerror(errno);
        break;
      } else if (ret == 0) {
        NOTREACHED() << "Unexpected closure of shutdown pipe.";
        break;
      }
      bytes_read += ret;
    } while (bytes_read < sizeof(signal));

    if (bytes_read == sizeof(signal))
      VLOG(1) << "Handling shutdown for signal " << signal << ".";
    else
      VLOG(1) << "Handling shutdown for unknown signal.";

    // Clean up Breakpad if necessary.
    if (IsCrashReporterEnabled()) {
      VLOG(1) << "Cleaning up Breakpad.";
      DestructCrashReporter();
    } else {
      VLOG(1) << "Breakpad not enabled; no clean-up needed.";
    }

    // Something went seriously wrong, so get out.
    if (bytes_read != sizeof(signal)) {
      LOG(WARNING) << "Failed to get signal. Quitting ungracefully.";
      _exit(1);
    }

    // Re-raise the signal.
    kill(getpid(), signal);

    // The signal may be handled on another thread. Give that a chance to
    // happen.
    sleep(3);

    // We really should be dead by now.  For whatever reason, we're not. Exit
    // immediately, with the exit status set to the signal number with bit 8
    // set.  On the systems that we care about, this exit status is what is
    // normally used to indicate an exit by this signal's default handler.
    // This mechanism isn't a de jure standard, but even in the worst case, it
    // should at least result in an immediate exit.
    LOG(WARNING) << "Still here, exiting really ungracefully.";
    _exit(signal | (1 << 7));
  }

 private:
  const int shutdown_fd_;

  DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
};

}  // namespace
#endif  // OS_MACOSX

// This function provides some ways to test crash and assertion handling
// behavior of the renderer.
static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
  // This parameter causes an assertion.
  if (command_line.HasSwitch(switches::kRendererAssertTest)) {
    DCHECK(false);
  }

#if !defined(OFFICIAL_BUILD)
  // This parameter causes an assertion too.
  if (command_line.HasSwitch(switches::kRendererCheckFalseTest)) {
    CHECK(false);
  }
#endif  // !defined(OFFICIAL_BUILD)

  // This parameter causes a null pointer crash (crash reporter trigger).
  if (command_line.HasSwitch(switches::kRendererCrashTest)) {
    int* bad_pointer = NULL;
    *bad_pointer = 0;
  }

  if (command_line.HasSwitch(switches::kRendererStartupDialog)) {
    ChildProcess::WaitForDebugger("Renderer");
  }
}

// This is a simplified version of the browser Jankometer, which measures
// the processing time of tasks on the render thread.
class RendererMessageLoopObserver : public MessageLoop::TaskObserver {
 public:
  RendererMessageLoopObserver()
      : process_times_(base::Histogram::FactoryGet(
            "Chrome.ProcMsgL RenderThread",
            1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag)) {}
  virtual ~RendererMessageLoopObserver() {}

  virtual void WillProcessTask(const Task* task) {
    begin_process_message_ = base::TimeTicks::Now();
  }

  virtual void DidProcessTask(const Task* task) {
    if (begin_process_message_ != base::TimeTicks())
      process_times_->AddTime(base::TimeTicks::Now() - begin_process_message_);
  }

 private:
  base::TimeTicks begin_process_message_;
  scoped_refptr<base::Histogram> process_times_;
  DISALLOW_COPY_AND_ASSIGN(RendererMessageLoopObserver);
};

// mainline routine for running as the Renderer process
int RendererMain(const MainFunctionParams& parameters) {
  TRACE_EVENT_BEGIN("RendererMain", 0, "");

  const CommandLine& parsed_command_line = parameters.command_line_;
  base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;

#if defined(OS_MACOSX)
  // TODO(viettrungluu): Code taken from browser_main.cc.
  int pipefd[2];
  int ret = pipe(pipefd);
  if (ret < 0) {
    PLOG(DFATAL) << "Failed to create pipe";
  } else {
    int shutdown_pipe_read_fd = pipefd[0];
    g_shutdown_pipe_write_fd = pipefd[1];
    const size_t kShutdownDetectorThreadStackSize = 4096;
    if (!base::PlatformThread::CreateNonJoinable(
            kShutdownDetectorThreadStackSize,
            new ShutdownDetector(shutdown_pipe_read_fd))) {
      LOG(DFATAL) << "Failed to create shutdown detector task.";
    }
  }

  // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking
  // Mach ports.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGTERMHandler;
  CHECK(sigaction(SIGTERM, &action, NULL) == 0);
#endif  // OS_MACOSX

#if defined(OS_CHROMEOS)
  // As Zygote process starts up earlier than browser process gets its own
  // locale (at login time for Chrome OS), we have to set the ICU default
  // locale for renderer process here.
  // ICU locale will be used for fallback font selection etc.
  if (parsed_command_line.HasSwitch(switches::kLang)) {
    const std::string locale =
        parsed_command_line.GetSwitchValueASCII(switches::kLang);
    base::i18n::SetICUDefaultLocale(locale);
  }
#endif

  // Configure modules that need access to resources.
  net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
  gfx::GfxModule::SetResourceProvider(chrome::GfxResourceProvider);

  // This function allows pausing execution using the --renderer-startup-dialog
  // flag allowing us to attach a debugger.
  // Do not move this function down since that would mean we can't easily debug
  // whatever occurs before it.
  HandleRendererErrorTestParameters(parsed_command_line);

  RendererMainPlatformDelegate platform(parameters);

  base::StatsScope<base::StatsCounterTimer>
      startup_timer(chrome::Counters::renderer_main());

  RendererMessageLoopObserver task_observer;
#if defined(OS_MACOSX)
  // As long as we use Cocoa in the renderer (for the forseeable future as of
  // now; see http://crbug.com/13890 for info) we need to have a UI loop.
  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
#else
  // The main message loop of the renderer services doesn't have IO or UI tasks,
  // unless in-process-plugins is used.
  MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
              MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
#endif
  main_message_loop.AddTaskObserver(&task_observer);

  base::PlatformThread::SetName("CrRendererMain");

  ui::SystemMonitor system_monitor;
  HighResolutionTimerManager hi_res_timer_manager;

  platform.PlatformInitialize();

  bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
  platform.InitSandboxTests(no_sandbox);

  // Initialize histogram statistics gathering system.
  // Don't create StatisticsRecorder in the single process mode.
  scoped_ptr<base::StatisticsRecorder> statistics;
  if (!base::StatisticsRecorder::IsActive()) {
    statistics.reset(new base::StatisticsRecorder());
  }

  // Initialize statistical testing infrastructure.
  base::FieldTrialList field_trial;
  // Ensure any field trials in browser are reflected into renderer.
  if (parsed_command_line.HasSwitch(switches::kForceFieldTestNameAndValue)) {
    std::string persistent = parsed_command_line.GetSwitchValueASCII(
        switches::kForceFieldTestNameAndValue);
    bool ret = field_trial.CreateTrialsInChildProcess(persistent);
    DCHECK(ret);
  }

  // Load pepper plugins before engaging the sandbox.
  PepperPluginRegistry::GetInstance();

  {
#if !defined(OS_LINUX)
    // TODO(markus): Check if it is OK to unconditionally move this
    // instruction down.
    RenderProcessImpl render_process;
    render_process.set_main_thread(new RenderThread());
#endif
    bool run_loop = true;
    if (!no_sandbox) {
      run_loop = platform.EnableSandbox();
    } else {
      LOG(ERROR) << "Running without renderer sandbox";
    }
#if defined(OS_LINUX)
    RenderProcessImpl render_process;
    render_process.set_main_thread(new RenderThread());
#endif

    platform.RunSandboxTests();

    startup_timer.Stop();  // End of Startup Time Measurement.

    if (run_loop) {
      if (pool)
        pool->Recycle();
      TRACE_EVENT_BEGIN("RendererMain.START_MSG_LOOP", 0, 0);
      MessageLoop::current()->Run();
      TRACE_EVENT_END("RendererMain.START_MSG_LOOP", 0, 0);
    }
  }
  platform.PlatformUninitialize();
  TRACE_EVENT_END("RendererMain", 0, "");
  return 0;
}
<|endoftext|>


<commit_before>#include "line.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "matrixstacksingleton.hpp"
#include "logicstate.hpp"

Line::Line(){
	vertices = 0;
}
void Line::setStartEnd(const glm::vec3 a, const glm::vec3 b){
	if(vertices == 0 || vertexSize != 6){
		vertices = new GLfloat[6];
	}
	vertices[0] = a[0];
	vertices[1] = a[1];
	vertices[2] = a[2];

	vertices[3] = b[0];
	vertices[4] = b[1];
	vertices[5] = b[2];
	setVertices(vertices, 2*3);

}
void Line::setVertices(GLfloat vertices[], unsigned int size){
	this->vertices = vertices;
	vertexSize = size;
}
GLfloat* Line::getVertices(){
	return vertices;
}
void Line::buildStatic(){
	glGenBuffers(1, &vboID[0]);
}
void Line::setShaderLocations(GLuint vertShaderLocation){
	this->vertShaderLocation = vertShaderLocation;
}
void Line::draw(struct LogicContext* state){
	glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);

	glBufferData(GL_ARRAY_BUFFER, vertexSize * sizeof(GLfloat), vertices, GL_DYNAMIC_DRAW);

	glUniformMatrix4fv(state->uloc_modelview, 1, GL_FALSE, glm::value_ptr(model_matrix));
	glEnableVertexAttribArray(vertShaderLocation);

	glVertexAttribPointer(
			vertShaderLocation,
			3, //size of attribute
			GL_FLOAT,
			GL_FALSE,
			0, //stride
			(void*)0 //Pointer to the off of the first component of the first element
			);
	glDrawArrays(
			GL_LINES,
			0,
			vertexSize //Amount of vertices to draw
			);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(vertShaderLocation);
	model_matrix = (MatrixStackSingleton::instance())->pop();

}
void Line::update(struct LogicContext* state){
	MatrixStackSingleton* instance = MatrixStackSingleton::instance();

	instance->push(model_matrix);
	model_matrix = state->modelview * model_matrix;

}
void Line::translate(glm::vec3 moveBy){
	model_matrix = glm::translate(model_matrix, moveBy);
}
void Line::rotate(glm::vec3 rotateAround, float rotateBy){
	model_matrix = glm::rotate(model_matrix, rotateBy, rotateAround);
}
glm::mat4* Line::getModelMatrix(){
	return &model_matrix;

}
Line::~Line(){
	delete vertices;
}
<commit_msg>Fixed creating and deleting vertices<commit_after>#include "line.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "matrixstacksingleton.hpp"
#include "logicstate.hpp"

Line::Line(){
	vertices = new GLfloat[6];
}
void Line::setStartEnd(const glm::vec3 a, const glm::vec3 b){
	vertices[0] = a[0];
	vertices[1] = a[1];
	vertices[2] = a[2];

	vertices[3] = b[0];
	vertices[4] = b[1];
	vertices[5] = b[2];
	setVertices(vertices, 2*3);

}
void Line::setVertices(GLfloat vertices[], unsigned int size){
	this->vertices = vertices;
	vertexSize = size;
}
GLfloat* Line::getVertices(){
	return vertices;
}
void Line::buildStatic(){
	glGenBuffers(1, &vboID[0]);
}
void Line::setShaderLocations(GLuint vertShaderLocation){
	this->vertShaderLocation = vertShaderLocation;
}
void Line::draw(struct LogicContext* state){
	glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);

	glBufferData(GL_ARRAY_BUFFER, vertexSize * sizeof(GLfloat), vertices, GL_DYNAMIC_DRAW);

	glUniformMatrix4fv(state->uloc_modelview, 1, GL_FALSE, glm::value_ptr(model_matrix));
	glEnableVertexAttribArray(vertShaderLocation);

	glVertexAttribPointer(
			vertShaderLocation,
			3, //size of attribute
			GL_FLOAT,
			GL_FALSE,
			0, //stride
			(void*)0 //Pointer to the off of the first component of the first element
			);
	glDrawArrays(
			GL_LINES,
			0,
			vertexSize //Amount of vertices to draw
			);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(vertShaderLocation);
	model_matrix = (MatrixStackSingleton::instance())->pop();

}
void Line::update(struct LogicContext* state){
	MatrixStackSingleton* instance = MatrixStackSingleton::instance();

	instance->push(model_matrix);
	model_matrix = state->modelview * model_matrix;

}
void Line::translate(glm::vec3 moveBy){
	model_matrix = glm::translate(model_matrix, moveBy);
}
void Line::rotate(glm::vec3 rotateAround, float rotateBy){
	model_matrix = glm::rotate(model_matrix, rotateBy, rotateAround);
}
glm::mat4* Line::getModelMatrix(){
	return &model_matrix;

}
Line::~Line(){
	delete[] vertices;
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <boost/intrusive/list.hpp>

namespace seastar {

/// A non-owning reference to an object.
///
/// weak_ptr allows one to keep a non-owning reference to an object. When the
/// object is destroyed, it notifies all weak_ptr instances pointing to it.
/// A weak_ptr instance pointing to a destroyed object is equivalent to a
/// `nullptr`.
///
/// The referenced object must inherit from weakly_referencable.
/// weak_ptr instances can only be obtained by calling weak_from_this() on
/// the to-be-referenced object.
///
/// \see weakly_referencable
template<typename T>
class weak_ptr {
    template<typename U>
    friend class weakly_referencable;
private:
    using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
    hook_type _hook;
    T* _ptr = nullptr;
    weak_ptr(T* p) noexcept : _ptr(p) {}
public:
    weak_ptr() noexcept = default;
    weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
    weak_ptr(weak_ptr&& o) noexcept
        : _ptr(o._ptr)
    {
        _hook.swap_nodes(o._hook);
        o._ptr = nullptr;
    }
    weak_ptr& operator=(weak_ptr&& o) noexcept {
        if (this != &o) {
            this->~weak_ptr();
            new (this) weak_ptr(std::move(o));
        }
        return *this;
    }
    explicit operator bool() const noexcept { return _ptr != nullptr; }
    T* operator->() const noexcept { return _ptr; }
    T& operator*() const noexcept { return *_ptr; }
    T* get() const noexcept { return _ptr; }
    bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
    bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
};

/// Allows obtaining a non-owning reference (weak_ptr) to the object.
///
/// A live weak_ptr object doesn't prevent the referenced object form being destroyed.
///
/// The underlying pointer held by weak_ptr is valid as long as the referenced object is alive.
/// When the object dies, all weak_ptr objects associated with it are emptied.
///
/// A weak reference is obtained like this:
///
///     class X : public weakly_referencable<X> {};
///     auto x = std::make_unique<X>();
///     weak_ptr<X> ptr = x->weak_from_this();
///
/// The user of weak_ptr can check if it still holds a valid pointer like this:
///
///     if (ptr) ptr->do_something();
///
template<typename T>
class weakly_referencable {
    boost::intrusive::list<weak_ptr<T>,
            boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
            boost::intrusive::constant_time_size<false>> _ptr_list;
public:
    weakly_referencable() noexcept = default;
    weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
    weakly_referencable(const weakly_referencable&) = delete;
    ~weakly_referencable() noexcept {
        _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
            wp->_ptr = nullptr;
        });
    }
    weak_ptr<T> weak_from_this() noexcept {
        weak_ptr<T> ptr(static_cast<T*>(this));
        _ptr_list.push_back(ptr);
        return ptr;
    }
};

}

<commit_msg>core: weak_ptr, weakly_referencable: implement empty default constructor<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <boost/intrusive/list.hpp>

namespace seastar {

/// A non-owning reference to an object.
///
/// weak_ptr allows one to keep a non-owning reference to an object. When the
/// object is destroyed, it notifies all weak_ptr instances pointing to it.
/// A weak_ptr instance pointing to a destroyed object is equivalent to a
/// `nullptr`.
///
/// The referenced object must inherit from weakly_referencable.
/// weak_ptr instances can only be obtained by calling weak_from_this() on
/// the to-be-referenced object.
///
/// \see weakly_referencable
template<typename T>
class weak_ptr {
    template<typename U>
    friend class weakly_referencable;
private:
    using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
    hook_type _hook;
    T* _ptr = nullptr;
    weak_ptr(T* p) noexcept : _ptr(p) {}
public:
    // Note: The default constructor's body is implemented as no-op
    // rather than `noexcept = default` due to a bug with gcc 9.3.1
    // that deletes the constructor since boost::intrusive::list_member_hook
    // is not default_nothrow_constructible.
    weak_ptr() noexcept {}
    weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
    weak_ptr(weak_ptr&& o) noexcept
        : _ptr(o._ptr)
    {
        _hook.swap_nodes(o._hook);
        o._ptr = nullptr;
    }
    weak_ptr& operator=(weak_ptr&& o) noexcept {
        if (this != &o) {
            this->~weak_ptr();
            new (this) weak_ptr(std::move(o));
        }
        return *this;
    }
    explicit operator bool() const noexcept { return _ptr != nullptr; }
    T* operator->() const noexcept { return _ptr; }
    T& operator*() const noexcept { return *_ptr; }
    T* get() const noexcept { return _ptr; }
    bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
    bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
};

/// Allows obtaining a non-owning reference (weak_ptr) to the object.
///
/// A live weak_ptr object doesn't prevent the referenced object form being destroyed.
///
/// The underlying pointer held by weak_ptr is valid as long as the referenced object is alive.
/// When the object dies, all weak_ptr objects associated with it are emptied.
///
/// A weak reference is obtained like this:
///
///     class X : public weakly_referencable<X> {};
///     auto x = std::make_unique<X>();
///     weak_ptr<X> ptr = x->weak_from_this();
///
/// The user of weak_ptr can check if it still holds a valid pointer like this:
///
///     if (ptr) ptr->do_something();
///
template<typename T>
class weakly_referencable {
    boost::intrusive::list<weak_ptr<T>,
            boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
            boost::intrusive::constant_time_size<false>> _ptr_list;
public:
    // Note: The default constructor's body is implemented as no-op
    // rather than `noexcept = default` due to a bug with gcc 9.3.1
    // that deletes the constructor since boost::intrusive::member_hook
    // is not default_nothrow_constructible.
    weakly_referencable() noexcept {}
    weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
    weakly_referencable(const weakly_referencable&) = delete;
    ~weakly_referencable() noexcept {
        _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
            wp->_ptr = nullptr;
        });
    }
    weak_ptr<T> weak_from_this() noexcept {
        weak_ptr<T> ptr(static_cast<T*>(this));
        _ptr_list.push_back(ptr);
        return ptr;
    }
};

}

<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/net/api.hh>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>
#include <boost/type.hpp>
#include <seastar/util/std-compat.hh>
#include <seastar/util/variant_utils.hh>
#include <seastar/core/timer.hh>
#include <seastar/core/circular_buffer.hh>
#include <seastar/core/simple-stream.hh>
#include <seastar/core/lowres_clock.hh>
#include <boost/functional/hash.hpp>
#include <seastar/core/sharded.hh>

namespace seastar {

namespace rpc {

using rpc_clock_type = lowres_clock;

// used to tag a type for serializers
template<typename T>
using type = boost::type<T>;

struct stats {
    using counter_type = uint64_t;
    counter_type replied = 0;
    counter_type pending = 0;
    counter_type exception_received = 0;
    counter_type sent_messages = 0;
    counter_type wait_reply = 0;
    counter_type timeout = 0;
};

struct client_info {
    socket_address addr;
    std::unordered_map<sstring, boost::any> user_data;
    template <typename T>
    void attach_auxiliary(const sstring& key, T&& object) {
        user_data.emplace(key, boost::any(std::forward<T>(object)));
    }
    template <typename T>
    T& retrieve_auxiliary(const sstring& key) {
        auto it = user_data.find(key);
        assert(it != user_data.end());
        return boost::any_cast<T&>(it->second);
    }
    template <typename T>
    typename std::add_const<T>::type& retrieve_auxiliary(const sstring& key) const {
        return const_cast<client_info*>(this)->retrieve_auxiliary<typename std::add_const<T>::type>(key);
    }
};

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

class closed_error : public error {
public:
    closed_error() : error("connection is closed") {}
};

class timeout_error : public error {
public:
    timeout_error() : error("rpc call timed out") {}
};

class unknown_verb_error : public error {
public:
    uint64_t type;
    unknown_verb_error(uint64_t type_) : error("unknown verb"), type(type_) {}
};

class unknown_exception_error : public error {
public:
    unknown_exception_error() : error("unknown exception") {}
};

class rpc_protocol_error : public error {
public:
    rpc_protocol_error() : error("rpc protocol exception") {}
};

class canceled_error : public error {
public:
    canceled_error() : error("rpc call was canceled") {}
};

class stream_closed : public error {
public:
    stream_closed() : error("rpc stream was closed by peer") {}
};

struct no_wait_type {};

// return this from a callback if client does not want to waiting for a reply
extern no_wait_type no_wait;

/// \addtogroup rpc
/// @{

template <typename T>
class optional : public compat::optional<T> {
public:
     using compat::optional<T>::optional;
};

class opt_time_point : public compat::optional<rpc_clock_type::time_point> {
public:
     using compat::optional<rpc_clock_type::time_point>::optional;
     opt_time_point(compat::optional<rpc_clock_type::time_point> time_point) {
         static_cast<compat::optional<rpc_clock_type::time_point>&>(*this) = time_point;
     }
};

/// @}

struct cancellable {
    std::function<void()> cancel_send;
    std::function<void()> cancel_wait;
    cancellable** send_back_pointer = nullptr;
    cancellable** wait_back_pointer = nullptr;
    cancellable() = default;
    cancellable(cancellable&& x) : cancel_send(std::move(x.cancel_send)), cancel_wait(std::move(x.cancel_wait)), send_back_pointer(x.send_back_pointer), wait_back_pointer(x.wait_back_pointer) {
        if (send_back_pointer) {
            *send_back_pointer = this;
            x.send_back_pointer = nullptr;
        }
        if (wait_back_pointer) {
            *wait_back_pointer = this;
            x.wait_back_pointer = nullptr;
        }
    }
    cancellable& operator=(cancellable&& x) {
        if (&x != this) {
            this->~cancellable();
            new (this) cancellable(std::move(x));
        }
        return *this;
    }
    void cancel() {
        if (cancel_send) {
            cancel_send();
        }
        if (cancel_wait) {
            cancel_wait();
        }
    }
    ~cancellable() {
        cancel();
    }
};

struct rcv_buf {
    uint32_t size = 0;
    compat::optional<semaphore_units<>> su;
    compat::variant<std::vector<temporary_buffer<char>>, temporary_buffer<char>> bufs;
    using iterator = std::vector<temporary_buffer<char>>::iterator;
    rcv_buf() {}
    explicit rcv_buf(size_t size_) : size(size_) {}
    explicit rcv_buf(temporary_buffer<char> b) : size(b.size()), bufs(std::move(b)) {};
    explicit rcv_buf(std::vector<temporary_buffer<char>> bufs, size_t size)
        : size(size), bufs(std::move(bufs)) {};
};

struct snd_buf {
    // Preferred, but not required, chunk size.
    static constexpr size_t chunk_size = 128*1024;
    uint32_t size = 0;
    compat::variant<std::vector<temporary_buffer<char>>, temporary_buffer<char>> bufs;
    using iterator = std::vector<temporary_buffer<char>>::iterator;
    snd_buf() {}
    explicit snd_buf(size_t size_);
    explicit snd_buf(temporary_buffer<char> b) : size(b.size()), bufs(std::move(b)) {};

    explicit snd_buf(std::vector<temporary_buffer<char>> bufs, size_t size)
        : size(size), bufs(std::move(bufs)) {};

    temporary_buffer<char>& front();
};

static inline memory_input_stream<rcv_buf::iterator> make_deserializer_stream(rcv_buf& input) {
    auto* b = compat::get_if<temporary_buffer<char>>(&input.bufs);
    if (b) {
        return memory_input_stream<rcv_buf::iterator>(memory_input_stream<rcv_buf::iterator>::simple(b->begin(), b->size()));
    } else {
        auto& ar = compat::get<std::vector<temporary_buffer<char>>>(input.bufs);
        return memory_input_stream<rcv_buf::iterator>(memory_input_stream<rcv_buf::iterator>::fragmented(ar.begin(), input.size));
    }
}

class compressor {
public:
    virtual ~compressor() {}
    // compress data and leave head_space bytes at the beginning of returned buffer
    virtual snd_buf compress(size_t head_space, snd_buf data) = 0;
    // decompress data
    virtual rcv_buf decompress(rcv_buf data) = 0;

    // factory to create compressor for a connection
    class factory {
    public:
        virtual ~factory() {}
        // return feature string that will be sent as part of protocol negotiation
        virtual const sstring& supported() const = 0;
        // negotiate compress algorithm
        virtual std::unique_ptr<compressor> negotiate(sstring feature, bool is_server) const = 0;
    };
};

class connection;

struct connection_id {
    uint64_t id;
    bool operator==(const connection_id& o) const {
        return id == o.id;
    }
    operator bool() const {
        return shard() != 0xffff;
    }
    size_t shard() const {
        return size_t(id & 0xffff);
    }
    constexpr static connection_id make_invalid_id(uint64_t id = 0) {
        return make_id(id, 0xffff);
    }
    constexpr static connection_id make_id(uint64_t id, uint16_t shard) {
        return {id << 16 | shard};
    }
};

constexpr connection_id invalid_connection_id = connection_id::make_invalid_id();

std::ostream& operator<<(std::ostream&, const connection_id&);

using xshard_connection_ptr = lw_shared_ptr<foreign_ptr<shared_ptr<connection>>>;
constexpr size_t max_queued_stream_buffers = 50;
constexpr size_t max_stream_buffers_memory = 100 * 1024;

/// \addtogroup rpc
/// @{

// send data Out...
template<typename... Out>
class sink {
public:
    class impl {
    protected:
        xshard_connection_ptr _con;
        semaphore _sem;
        std::exception_ptr _ex;
        impl(xshard_connection_ptr con) : _con(std::move(con)), _sem(max_stream_buffers_memory) {}
    public:
        virtual ~impl() {};
        virtual future<> operator()(const Out&... args) = 0;
        virtual future<> close() = 0;
        virtual future<> flush() = 0;
        friend sink;
    };

private:
    shared_ptr<impl> _impl;

public:
    sink(shared_ptr<impl> impl) : _impl(std::move(impl)) {}
    future<> operator()(const Out&... args) {
        return _impl->operator()(args...);
    }
    future<> close() {
        return _impl->close();
    }
    // Calling this function makes sure that any data buffered
    // by the stream sink will be flushed to the network.
    // It does not mean the data was received by the corresponding
    // source.
    future<> flush() {
        return _impl->flush();
    }
    connection_id get_id() const;
};

// receive data In...
template<typename... In>
class source {
public:
    class impl {
    protected:
        xshard_connection_ptr _con;
        circular_buffer<foreign_ptr<std::unique_ptr<rcv_buf>>> _bufs;
        impl(xshard_connection_ptr con) : _con(std::move(con)) {
            _bufs.reserve(max_queued_stream_buffers);
        }
    public:
        virtual ~impl() {}
        virtual future<compat::optional<std::tuple<In...>>> operator()() = 0;
        friend source;
    };
private:
    shared_ptr<impl> _impl;

public:
    source(shared_ptr<impl> impl) : _impl(std::move(impl)) {}
    future<compat::optional<std::tuple<In...>>> operator()() {
        return _impl->operator()();
    };
    connection_id get_id() const;
    template<typename Serializer, typename... Out> sink<Out...> make_sink();
};

/// Used to return multiple values in rpc without variadic futures
///
/// If you wish to return multiple values from an rpc procedure, use a
/// signature `future<rpc::tuple<return type list> (argument list)>>`. This
/// will be marshalled by rpc, so you do not need to have your Serializer
/// serialize/deserialize this tuple type. The serialization format is
/// compatible with the deprecated variadic future support, and is compatible
/// with adding new return types in a backwards compatible way provided new
/// parameters are appended only, and wrapped with rpc::optional:
/// `future<rpc::tuple<existing return type list, rpc::optional<new_return_type>>> (argument list)`
///
/// You may also use another tuple type, such as std::tuple. In this case,
/// your Serializer type must recognize your tuple type and provide serialization
/// and deserialization for it.
template <typename... T>
class tuple : public std::tuple<T...> {
public:
    using std::tuple<T...>::tuple;
    tuple(std::tuple<T...>&& x) : std::tuple<T...>(std::move(x)) {}
};

/// @}

#if __cplusplus >= 201703L

template <typename... T>
tuple(T&&...) ->  tuple<T...>;

#endif

} // namespace rpc

}

namespace std {
template<>
struct hash<seastar::rpc::connection_id> {
    size_t operator()(const seastar::rpc::connection_id& id) const {
        size_t h = 0;
        boost::hash_combine(h, std::hash<uint64_t>{}(id.id));
        return h;
    }
};

template <typename... T>
struct tuple_size<seastar::rpc::tuple<T...>> : tuple_size<tuple<T...>> {
};

template <size_t I, typename... T>
struct tuple_element<I, seastar::rpc::tuple<T...>> : tuple_element<I, tuple<T...>> {
};

}
<commit_msg>rpc: Delete __cplusplus check<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/net/api.hh>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>
#include <boost/type.hpp>
#include <seastar/util/std-compat.hh>
#include <seastar/util/variant_utils.hh>
#include <seastar/core/timer.hh>
#include <seastar/core/circular_buffer.hh>
#include <seastar/core/simple-stream.hh>
#include <seastar/core/lowres_clock.hh>
#include <boost/functional/hash.hpp>
#include <seastar/core/sharded.hh>

namespace seastar {

namespace rpc {

using rpc_clock_type = lowres_clock;

// used to tag a type for serializers
template<typename T>
using type = boost::type<T>;

struct stats {
    using counter_type = uint64_t;
    counter_type replied = 0;
    counter_type pending = 0;
    counter_type exception_received = 0;
    counter_type sent_messages = 0;
    counter_type wait_reply = 0;
    counter_type timeout = 0;
};

struct client_info {
    socket_address addr;
    std::unordered_map<sstring, boost::any> user_data;
    template <typename T>
    void attach_auxiliary(const sstring& key, T&& object) {
        user_data.emplace(key, boost::any(std::forward<T>(object)));
    }
    template <typename T>
    T& retrieve_auxiliary(const sstring& key) {
        auto it = user_data.find(key);
        assert(it != user_data.end());
        return boost::any_cast<T&>(it->second);
    }
    template <typename T>
    typename std::add_const<T>::type& retrieve_auxiliary(const sstring& key) const {
        return const_cast<client_info*>(this)->retrieve_auxiliary<typename std::add_const<T>::type>(key);
    }
};

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

class closed_error : public error {
public:
    closed_error() : error("connection is closed") {}
};

class timeout_error : public error {
public:
    timeout_error() : error("rpc call timed out") {}
};

class unknown_verb_error : public error {
public:
    uint64_t type;
    unknown_verb_error(uint64_t type_) : error("unknown verb"), type(type_) {}
};

class unknown_exception_error : public error {
public:
    unknown_exception_error() : error("unknown exception") {}
};

class rpc_protocol_error : public error {
public:
    rpc_protocol_error() : error("rpc protocol exception") {}
};

class canceled_error : public error {
public:
    canceled_error() : error("rpc call was canceled") {}
};

class stream_closed : public error {
public:
    stream_closed() : error("rpc stream was closed by peer") {}
};

struct no_wait_type {};

// return this from a callback if client does not want to waiting for a reply
extern no_wait_type no_wait;

/// \addtogroup rpc
/// @{

template <typename T>
class optional : public compat::optional<T> {
public:
     using compat::optional<T>::optional;
};

class opt_time_point : public compat::optional<rpc_clock_type::time_point> {
public:
     using compat::optional<rpc_clock_type::time_point>::optional;
     opt_time_point(compat::optional<rpc_clock_type::time_point> time_point) {
         static_cast<compat::optional<rpc_clock_type::time_point>&>(*this) = time_point;
     }
};

/// @}

struct cancellable {
    std::function<void()> cancel_send;
    std::function<void()> cancel_wait;
    cancellable** send_back_pointer = nullptr;
    cancellable** wait_back_pointer = nullptr;
    cancellable() = default;
    cancellable(cancellable&& x) : cancel_send(std::move(x.cancel_send)), cancel_wait(std::move(x.cancel_wait)), send_back_pointer(x.send_back_pointer), wait_back_pointer(x.wait_back_pointer) {
        if (send_back_pointer) {
            *send_back_pointer = this;
            x.send_back_pointer = nullptr;
        }
        if (wait_back_pointer) {
            *wait_back_pointer = this;
            x.wait_back_pointer = nullptr;
        }
    }
    cancellable& operator=(cancellable&& x) {
        if (&x != this) {
            this->~cancellable();
            new (this) cancellable(std::move(x));
        }
        return *this;
    }
    void cancel() {
        if (cancel_send) {
            cancel_send();
        }
        if (cancel_wait) {
            cancel_wait();
        }
    }
    ~cancellable() {
        cancel();
    }
};

struct rcv_buf {
    uint32_t size = 0;
    compat::optional<semaphore_units<>> su;
    compat::variant<std::vector<temporary_buffer<char>>, temporary_buffer<char>> bufs;
    using iterator = std::vector<temporary_buffer<char>>::iterator;
    rcv_buf() {}
    explicit rcv_buf(size_t size_) : size(size_) {}
    explicit rcv_buf(temporary_buffer<char> b) : size(b.size()), bufs(std::move(b)) {};
    explicit rcv_buf(std::vector<temporary_buffer<char>> bufs, size_t size)
        : size(size), bufs(std::move(bufs)) {};
};

struct snd_buf {
    // Preferred, but not required, chunk size.
    static constexpr size_t chunk_size = 128*1024;
    uint32_t size = 0;
    compat::variant<std::vector<temporary_buffer<char>>, temporary_buffer<char>> bufs;
    using iterator = std::vector<temporary_buffer<char>>::iterator;
    snd_buf() {}
    explicit snd_buf(size_t size_);
    explicit snd_buf(temporary_buffer<char> b) : size(b.size()), bufs(std::move(b)) {};

    explicit snd_buf(std::vector<temporary_buffer<char>> bufs, size_t size)
        : size(size), bufs(std::move(bufs)) {};

    temporary_buffer<char>& front();
};

static inline memory_input_stream<rcv_buf::iterator> make_deserializer_stream(rcv_buf& input) {
    auto* b = compat::get_if<temporary_buffer<char>>(&input.bufs);
    if (b) {
        return memory_input_stream<rcv_buf::iterator>(memory_input_stream<rcv_buf::iterator>::simple(b->begin(), b->size()));
    } else {
        auto& ar = compat::get<std::vector<temporary_buffer<char>>>(input.bufs);
        return memory_input_stream<rcv_buf::iterator>(memory_input_stream<rcv_buf::iterator>::fragmented(ar.begin(), input.size));
    }
}

class compressor {
public:
    virtual ~compressor() {}
    // compress data and leave head_space bytes at the beginning of returned buffer
    virtual snd_buf compress(size_t head_space, snd_buf data) = 0;
    // decompress data
    virtual rcv_buf decompress(rcv_buf data) = 0;

    // factory to create compressor for a connection
    class factory {
    public:
        virtual ~factory() {}
        // return feature string that will be sent as part of protocol negotiation
        virtual const sstring& supported() const = 0;
        // negotiate compress algorithm
        virtual std::unique_ptr<compressor> negotiate(sstring feature, bool is_server) const = 0;
    };
};

class connection;

struct connection_id {
    uint64_t id;
    bool operator==(const connection_id& o) const {
        return id == o.id;
    }
    operator bool() const {
        return shard() != 0xffff;
    }
    size_t shard() const {
        return size_t(id & 0xffff);
    }
    constexpr static connection_id make_invalid_id(uint64_t id = 0) {
        return make_id(id, 0xffff);
    }
    constexpr static connection_id make_id(uint64_t id, uint16_t shard) {
        return {id << 16 | shard};
    }
};

constexpr connection_id invalid_connection_id = connection_id::make_invalid_id();

std::ostream& operator<<(std::ostream&, const connection_id&);

using xshard_connection_ptr = lw_shared_ptr<foreign_ptr<shared_ptr<connection>>>;
constexpr size_t max_queued_stream_buffers = 50;
constexpr size_t max_stream_buffers_memory = 100 * 1024;

/// \addtogroup rpc
/// @{

// send data Out...
template<typename... Out>
class sink {
public:
    class impl {
    protected:
        xshard_connection_ptr _con;
        semaphore _sem;
        std::exception_ptr _ex;
        impl(xshard_connection_ptr con) : _con(std::move(con)), _sem(max_stream_buffers_memory) {}
    public:
        virtual ~impl() {};
        virtual future<> operator()(const Out&... args) = 0;
        virtual future<> close() = 0;
        virtual future<> flush() = 0;
        friend sink;
    };

private:
    shared_ptr<impl> _impl;

public:
    sink(shared_ptr<impl> impl) : _impl(std::move(impl)) {}
    future<> operator()(const Out&... args) {
        return _impl->operator()(args...);
    }
    future<> close() {
        return _impl->close();
    }
    // Calling this function makes sure that any data buffered
    // by the stream sink will be flushed to the network.
    // It does not mean the data was received by the corresponding
    // source.
    future<> flush() {
        return _impl->flush();
    }
    connection_id get_id() const;
};

// receive data In...
template<typename... In>
class source {
public:
    class impl {
    protected:
        xshard_connection_ptr _con;
        circular_buffer<foreign_ptr<std::unique_ptr<rcv_buf>>> _bufs;
        impl(xshard_connection_ptr con) : _con(std::move(con)) {
            _bufs.reserve(max_queued_stream_buffers);
        }
    public:
        virtual ~impl() {}
        virtual future<compat::optional<std::tuple<In...>>> operator()() = 0;
        friend source;
    };
private:
    shared_ptr<impl> _impl;

public:
    source(shared_ptr<impl> impl) : _impl(std::move(impl)) {}
    future<compat::optional<std::tuple<In...>>> operator()() {
        return _impl->operator()();
    };
    connection_id get_id() const;
    template<typename Serializer, typename... Out> sink<Out...> make_sink();
};

/// Used to return multiple values in rpc without variadic futures
///
/// If you wish to return multiple values from an rpc procedure, use a
/// signature `future<rpc::tuple<return type list> (argument list)>>`. This
/// will be marshalled by rpc, so you do not need to have your Serializer
/// serialize/deserialize this tuple type. The serialization format is
/// compatible with the deprecated variadic future support, and is compatible
/// with adding new return types in a backwards compatible way provided new
/// parameters are appended only, and wrapped with rpc::optional:
/// `future<rpc::tuple<existing return type list, rpc::optional<new_return_type>>> (argument list)`
///
/// You may also use another tuple type, such as std::tuple. In this case,
/// your Serializer type must recognize your tuple type and provide serialization
/// and deserialization for it.
template <typename... T>
class tuple : public std::tuple<T...> {
public:
    using std::tuple<T...>::tuple;
    tuple(std::tuple<T...>&& x) : std::tuple<T...>(std::move(x)) {}
};

/// @}

template <typename... T>
tuple(T&&...) ->  tuple<T...>;

} // namespace rpc

}

namespace std {
template<>
struct hash<seastar::rpc::connection_id> {
    size_t operator()(const seastar::rpc::connection_id& id) const {
        size_t h = 0;
        boost::hash_combine(h, std::hash<uint64_t>{}(id.id));
        return h;
    }
};

template <typename... T>
struct tuple_size<seastar::rpc::tuple<T...>> : tuple_size<tuple<T...>> {
};

template <size_t I, typename... T>
struct tuple_element<I, seastar::rpc::tuple<T...>> : tuple_element<I, tuple<T...>> {
};

}
<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/internal/config.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_CONFIG_HPP
#define VSMC_INTERNAL_CONFIG_HPP

#include <vsmc/internal/compiler.hpp>

#ifndef VSMC_NO_STATIC_ASSERT
#define VSMC_NO_STATIC_ASSERT 0
#endif

#ifndef VSMC_NO_RUNTIME_ASSERT
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_ASSERT 0
#else
#define VSMC_NO_RUNTIME_ASSERT 1
#endif
#endif

#ifndef VSMC_NO_RUNTIME_WARNING
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_WARNING 0
#else
#define VSMC_NO_RUNTIME_WARNING 1
#endif
#endif

/// \brief Turn vSMC runtime assertions into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT_AS_EXCEPTION 0
#endif

/// \brief Turn vSMC runtime warnings into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_WARNING_AS_EXCEPTION
#define VSMC_RUNTIME_WARNING_AS_EXCEPTION 0
#endif

#ifndef VSMC_USE_AES_NI
#define VSMC_USE_AES_NI 0
#endif

#ifndef VSMC_USE_RD_RAND
#define VSMC_USE_RD_RAND 0
#endif

#ifndef VSMC_USE_RD_SEED
#define VSMC_USE_RD_SEED 0
#endif

#ifndef VSMC_USE_CXX11LIB_FUTURE
#define VSMC_USE_CXX11LIB_FUTURE VSMC_HAS_CXX11LIB_FUTURE
#endif

#ifndef VSMC_USE_MPI
#define VSMC_USE_MPI 0
#endif

#ifndef VSMC_USE_OPENCL
#define VSMC_USE_OPENCL 0
#endif

#ifndef VSMC_USE_MKL
#define VSMC_USE_MKL 0
#endif

#ifndef VSMC_USE_MKL_CBLAS
#define VSMC_USE_MKL_CBLAS VSMC_USE_MKL
#endif

#ifndef VSMC_USE_MKL_VML
#define VSMC_USE_MKL_VML VSMC_USE_MKL
#endif

#ifndef VSMC_USE_MKL_VSL
#define VSMC_USE_MKL_VSL VSMC_USE_MKL
#endif

#ifndef VSMC_USE_VECLIB
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_4)
#define VSMC_USE_VECLIB 1
#else
#define VSMC_USE_VECLIB 0
#endif

#ifndef VSMC_USE_VECLIB_CBLAS
#define VSMC_USE_VECLIB_CBLAS VSMC_USE_VECLIB
#endif

#ifndef VSMC_USE_VECLIB_VFORCE
#define VSMC_USE_VECLIB_VFORCE VSMC_USE_VECLIB
#endif

#ifndef VSMC_USE_CILK
#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1210
#define VSMC_USE_CILK 1
#else
#define VSMC_USE_CILK 0
#endif
#endif

#ifndef VSMC_USE_GCD
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_6)
#define VSMC_USE_GCD 1
#else
#define VSMC_USE_GCD 0
#endif
#endif

#ifndef VSMC_USE_GCD_LION
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_7)
#define VSMC_USE_GCD_LION 1
#else
#define VSMC_USE_GCD_LION 0
#endif
#endif

#ifndef VSMC_USE_OMP
#ifdef _OPENMP
#define VSMC_USE_OMP 1
#else
#define VSMC_USE_OMP 0
#endif
#endif

#ifndef VSMC_USE_PPL
#if defined(_MSC_VER) && _MSC_VER >= 1600
#define VSMC_USE_PPL 1
#else
#define VSMC_USE_PPL 0
#endif
#endif

#ifndef VSMC_USE_TBB
#define VSMC_USE_TBB 0
#endif

#ifndef VSMC_USE_HDF5
#define VSMC_USE_HDF5 0
#endif

#endif // VSMC_INTERNAL_CONFIG_HPP
<commit_msg>fix config<commit_after>//============================================================================
// include/vsmc/internal/config.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_CONFIG_HPP
#define VSMC_INTERNAL_CONFIG_HPP

#include <vsmc/internal/compiler.hpp>

#ifndef VSMC_NO_STATIC_ASSERT
#define VSMC_NO_STATIC_ASSERT 0
#endif

#ifndef VSMC_NO_RUNTIME_ASSERT
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_ASSERT 0
#else
#define VSMC_NO_RUNTIME_ASSERT 1
#endif
#endif

#ifndef VSMC_NO_RUNTIME_WARNING
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_WARNING 0
#else
#define VSMC_NO_RUNTIME_WARNING 1
#endif
#endif

/// \brief Turn vSMC runtime assertions into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT_AS_EXCEPTION 0
#endif

/// \brief Turn vSMC runtime warnings into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_WARNING_AS_EXCEPTION
#define VSMC_RUNTIME_WARNING_AS_EXCEPTION 0
#endif

#ifndef VSMC_USE_AES_NI
#define VSMC_USE_AES_NI 0
#endif

#ifndef VSMC_USE_RD_RAND
#define VSMC_USE_RD_RAND 0
#endif

#ifndef VSMC_USE_RD_SEED
#define VSMC_USE_RD_SEED 0
#endif

#ifndef VSMC_USE_CXX11LIB_FUTURE
#define VSMC_USE_CXX11LIB_FUTURE VSMC_HAS_CXX11LIB_FUTURE
#endif

#ifndef VSMC_USE_MPI
#define VSMC_USE_MPI 0
#endif

#ifndef VSMC_USE_OPENCL
#define VSMC_USE_OPENCL 0
#endif

#ifndef VSMC_USE_MKL
#define VSMC_USE_MKL 0
#endif

#ifndef VSMC_USE_MKL_CBLAS
#define VSMC_USE_MKL_CBLAS VSMC_USE_MKL
#endif

#ifndef VSMC_USE_MKL_VML
#define VSMC_USE_MKL_VML VSMC_USE_MKL
#endif

#ifndef VSMC_USE_MKL_VSL
#define VSMC_USE_MKL_VSL VSMC_USE_MKL
#endif

#ifndef VSMC_USE_VECLIB
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_4)
#define VSMC_USE_VECLIB 1
#else
#define VSMC_USE_VECLIB 0
#endif
#endif

#ifndef VSMC_USE_VECLIB_CBLAS
#define VSMC_USE_VECLIB_CBLAS VSMC_USE_VECLIB
#endif

#ifndef VSMC_USE_VECLIB_VFORCE
#define VSMC_USE_VECLIB_VFORCE VSMC_USE_VECLIB
#endif

#ifndef VSMC_USE_CILK
#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1210
#define VSMC_USE_CILK 1
#else
#define VSMC_USE_CILK 0
#endif
#endif

#ifndef VSMC_USE_GCD
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_6)
#define VSMC_USE_GCD 1
#else
#define VSMC_USE_GCD 0
#endif
#endif

#ifndef VSMC_USE_GCD_LION
#if VSMC_MAC_VERSION_MIN_REQUIRED(VSMC_MAC_10_7)
#define VSMC_USE_GCD_LION 1
#else
#define VSMC_USE_GCD_LION 0
#endif
#endif

#ifndef VSMC_USE_OMP
#ifdef _OPENMP
#define VSMC_USE_OMP 1
#else
#define VSMC_USE_OMP 0
#endif
#endif

#ifndef VSMC_USE_PPL
#if defined(_MSC_VER) && _MSC_VER >= 1600
#define VSMC_USE_PPL 1
#else
#define VSMC_USE_PPL 0
#endif
#endif

#ifndef VSMC_USE_TBB
#define VSMC_USE_TBB 0
#endif

#ifndef VSMC_USE_HDF5
#define VSMC_USE_HDF5 0
#endif

#endif // VSMC_INTERNAL_CONFIG_HPP
<|endoftext|>


<commit_before>#include <set>
#include <map>
#include <queue>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <sstream>

#ifdef DEBUG
#include <iostream>
#define DEBUG_PRINT(...) std::cout << __VA_ARGS__ << std::endl
#else
#define DEBUG_PRINT(...)
#endif

// Maximum config file line length
#define LINE_LENGTH 1024

// forward declaring the classes
class Conf;
class CommQueue;
class Throttle;

//---------------------------------------------
// Class for reading in the configuration file
//---------------------------------------------
class Conf {
public:
	Conf(const char *config_fn);
	template<typename T>
		void GetAttr(const std::string &name, T *output) const;

private:
	template<typename T> static void parse(const std::string &str, T *ret);
	template<typename T> static void parse(const std::string &str, std::set<T> *ret);

	// attributes
	std::map<std::string, std::string> attributes;
};

// IMPLEMENTATION OF THE TEMPLATES
template<typename T> void Conf::GetAttr(const std::string &name, T* output) const
{
	auto attr = attributes.find(name);
	if (attr != attributes.end())
		parse(attr->second, output);
	else
		throw std::runtime_error("No such attribute: " + name);
}

// Well, let's try something general first
template<typename T> void Conf::parse(const std::string &str, T *ret)
{
	std::istringstream stream(str);
	stream >> *ret;
}

// ... but we might want to specialize
template<> inline void Conf::parse<std::string>(const std::string &str, std::string *ret)
{
	*ret = str;
}

// For sets we do something completely different
template<typename T> void Conf::parse(const std::string &str, std::set<T> *ret)
{
	std::istringstream stream(str);
	T cur;

	while (stream >> cur)
		ret->insert(cur);
}

//----------------------------------
// Class handling the command queue
//----------------------------------
class CommQueue {
public:
	CommQueue(Throttle *parent, const char *pipe_fn);
	~CommQueue();
	void update();

private:
	// where we write to
	Throttle *Throt;

	// look for input and process
	void processCommand(const std::string &comm);

	// command pipe file descriptor
	int comm_file;

	// commands
	enum Command {
		DEFAULT = 0,
		SET_MAX,
		SET_MIN,
		SET_FREQ,
		RESET
	};

	static const std::map<std::string, Command> translate;
};

//---------------------------------------
// Main class controlling the throttling
//---------------------------------------
class Throttle {
public:
	Throttle(const char *config_fn, const char* pipe_fn);
	void operator()();

	/**
	 * Set new override frequency in MHz or reset (with freq=0).
	 */
	void setOverrideFreq(int freq)
	{
		override_freq = freq*1000;
		stabilize = 0;
	}

	/**
	 * Set minimum temperature in degrees Celsius.
	 */
	void setMinTemp(int temp) { temp_min = temp*1000; }

	/**
	 * Set maximum temperature in degrees Celsius.
	 */
	void setMaxTemp(int temp) { temp_max = temp*1000; }

private:
	void adjust();
	int readTemp() const;
	void writeFreq() const;

	// SETTINGS
	// number of cores
	int cores;

	// files
	std::string temp_fn;
	std::string freq_fn_prefix, freq_fn_suffix;

	// temperature thresholds
	int temp_max, temp_min;

	// frequencies
	std::set<int> freqs;
	int freq;

	// dynamics
	int wait_after_adjust;

	// Set to +wait_after_adjust after increasing frequency, to -wait_after_adjust after decreasing it.
	// Then it is diminished in absolute value after each step of adjusting.
	int stabilize;

	// STATUS & Override mechanics
	CommQueue queue;
	int override_freq;	// 0 = no override
};
<commit_msg>Add header guards for throttle.hpp<commit_after>#ifndef THROTTLE_HPP
#define THROTTLE_HPP

#include <set>
#include <map>
#include <queue>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <sstream>

#ifdef DEBUG
#include <iostream>
#define DEBUG_PRINT(...) std::cout << __VA_ARGS__ << std::endl
#else
#define DEBUG_PRINT(...)
#endif

// Maximum config file line length
#define LINE_LENGTH 1024

// forward declaring the classes
class Conf;
class CommQueue;
class Throttle;

//---------------------------------------------
// Class for reading in the configuration file
//---------------------------------------------
class Conf {
public:
	Conf(const char *config_fn);
	template<typename T>
		void GetAttr(const std::string &name, T *output) const;

private:
	template<typename T> static void parse(const std::string &str, T *ret);
	template<typename T> static void parse(const std::string &str, std::set<T> *ret);

	// attributes
	std::map<std::string, std::string> attributes;
};

// IMPLEMENTATION OF THE TEMPLATES
template<typename T> void Conf::GetAttr(const std::string &name, T* output) const
{
	auto attr = attributes.find(name);
	if (attr != attributes.end())
		parse(attr->second, output);
	else
		throw std::runtime_error("No such attribute: " + name);
}

// Well, let's try something general first
template<typename T> void Conf::parse(const std::string &str, T *ret)
{
	std::istringstream stream(str);
	stream >> *ret;
}

// ... but we might want to specialize
template<> inline void Conf::parse<std::string>(const std::string &str, std::string *ret)
{
	*ret = str;
}

// For sets we do something completely different
template<typename T> void Conf::parse(const std::string &str, std::set<T> *ret)
{
	std::istringstream stream(str);
	T cur;

	while (stream >> cur)
		ret->insert(cur);
}

//----------------------------------
// Class handling the command queue
//----------------------------------
class CommQueue {
public:
	CommQueue(Throttle *parent, const char *pipe_fn);
	~CommQueue();
	void update();

private:
	// where we write to
	Throttle *Throt;

	// look for input and process
	void processCommand(const std::string &comm);

	// command pipe file descriptor
	int comm_file;

	// commands
	enum Command {
		DEFAULT = 0,
		SET_MAX,
		SET_MIN,
		SET_FREQ,
		RESET
	};

	static const std::map<std::string, Command> translate;
};

//---------------------------------------
// Main class controlling the throttling
//---------------------------------------
class Throttle {
public:
	Throttle(const char *config_fn, const char* pipe_fn);
	void operator()();

	/**
	 * Set new override frequency in MHz or reset (with freq=0).
	 */
	void setOverrideFreq(int freq)
	{
		override_freq = freq*1000;
		stabilize = 0;
	}

	/**
	 * Set minimum temperature in degrees Celsius.
	 */
	void setMinTemp(int temp) { temp_min = temp*1000; }

	/**
	 * Set maximum temperature in degrees Celsius.
	 */
	void setMaxTemp(int temp) { temp_max = temp*1000; }

private:
	void adjust();
	int readTemp() const;
	void writeFreq() const;

	// SETTINGS
	// number of cores
	int cores;

	// files
	std::string temp_fn;
	std::string freq_fn_prefix, freq_fn_suffix;

	// temperature thresholds
	int temp_max, temp_min;

	// frequencies
	std::set<int> freqs;
	int freq;

	// dynamics
	int wait_after_adjust;

	// Set to +wait_after_adjust after increasing frequency, to -wait_after_adjust after decreasing it.
	// Then it is diminished in absolute value after each step of adjusting.
	int stabilize;

	// STATUS & Override mechanics
	CommQueue queue;
	int override_freq;	// 0 = no override
};

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h>
#endif

#include <timedata.h>

#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <warnings.h>

static Mutex g_timeoffset_mutex;
static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex) = 0;

/**
 * "Never go to sea with two chronometers; take one or three."
 * Our three time sources are:
 *  - System clock
 *  - Median of other nodes clocks
 *  - The user (asking the user to fix the system clock if the first two disagree)
 */
int64_t GetTimeOffset()
{
    LOCK(g_timeoffset_mutex);
    return nTimeOffset;
}

int64_t GetAdjustedTime()
{
    return GetTime() + GetTimeOffset();
}

static int64_t abs64(int64_t n)
{
    return (n >= 0 ? n : -n);
}

#define SYSCOIN_TIMEDATA_MAX_SAMPLES 200

void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{
    LOCK(g_timeoffset_mutex);
    // Ignore duplicates
    static std::set<CNetAddr> setKnown;
    if (setKnown.size() == SYSCOIN_TIMEDATA_MAX_SAMPLES)
        return;
    if (!setKnown.insert(ip).second)
        return;

    // Add data
    static CMedianFilter<int64_t> vTimeOffsets(SYSCOIN_TIMEDATA_MAX_SAMPLES, 0);
    vTimeOffsets.input(nOffsetSample);
    LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);

    // There is a known issue here (see issue #4521):
    //
    // - The structure vTimeOffsets contains up to 200 elements, after which
    // any new element added to it will not increase its size, replacing the
    // oldest element.
    //
    // - The condition to update nTimeOffset includes checking whether the
    // number of elements in vTimeOffsets is odd, which will never happen after
    // there are 200 elements.
    //
    // But in this case the 'bug' is protective against some attacks, and may
    // actually explain why we've never seen attacks which manipulate the
    // clock offset.
    //
    // So we should hold off on fixing this and clean it up as part of
    // a timing cleanup that strengthens it in a number of other ways.
    //
    if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
    {
        int64_t nMedian = vTimeOffsets.median();
        std::vector<int64_t> vSorted = vTimeOffsets.sorted();
        // Only let other nodes change our time by so much
        if (abs64(nMedian) <= std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
        {
            nTimeOffset = nMedian;
        }
        else
        {
            nTimeOffset = 0;

            static bool fDone;
            if (!fDone)
            {
                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
                bool fMatch = false;
                for (const int64_t nOffset : vSorted)
                    if (nOffset != 0 && abs64(nOffset) < 5 * 60)
                        fMatch = true;

                if (!fMatch)
                {
                    fDone = true;
                    bilingual_str strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), PACKAGE_NAME);
                    SetMiscWarning(strMessage.translated);
                    uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
                }
            }
        }

        if (LogAcceptCategory(BCLog::NET)) {
            for (const int64_t n : vSorted) {
                LogPrint(BCLog::NET, "%+d  ", n); /* Continued */
            }
            LogPrint(BCLog::NET, "|  "); /* Continued */

            LogPrint(BCLog::NET, "nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
        }
    }
}
<commit_msg>refactor: Fix formatting of timedata.cpp<commit_after>// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h>
#endif

#include <timedata.h>

#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <warnings.h>

static Mutex g_timeoffset_mutex;
static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex) = 0;

/**
 * "Never go to sea with two chronometers; take one or three."
 * Our three time sources are:
 *  - System clock
 *  - Median of other nodes clocks
 *  - The user (asking the user to fix the system clock if the first two disagree)
 */
int64_t GetTimeOffset()
{
    LOCK(g_timeoffset_mutex);
    return nTimeOffset;
}

int64_t GetAdjustedTime()
{
    return GetTime() + GetTimeOffset();
}

static int64_t abs64(int64_t n)
{
    return (n >= 0 ? n : -n);
}

#define SYSCOIN_TIMEDATA_MAX_SAMPLES 200

void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{
    LOCK(g_timeoffset_mutex);
    // Ignore duplicates
    static std::set<CNetAddr> setKnown;
    if (setKnown.size() == SYSCOIN_TIMEDATA_MAX_SAMPLES)
        return;
    if (!setKnown.insert(ip).second)
        return;

    // Add data
    static CMedianFilter<int64_t> vTimeOffsets(SYSCOIN_TIMEDATA_MAX_SAMPLES, 0);
    vTimeOffsets.input(nOffsetSample);
    LogPrint(BCLog::NET, "added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample / 60);

    // There is a known issue here (see issue #4521):
    //
    // - The structure vTimeOffsets contains up to 200 elements, after which
    // any new element added to it will not increase its size, replacing the
    // oldest element.
    //
    // - The condition to update nTimeOffset includes checking whether the
    // number of elements in vTimeOffsets is odd, which will never happen after
    // there are 200 elements.
    //
    // But in this case the 'bug' is protective against some attacks, and may
    // actually explain why we've never seen attacks which manipulate the
    // clock offset.
    //
    // So we should hold off on fixing this and clean it up as part of
    // a timing cleanup that strengthens it in a number of other ways.
    //
    if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) {
        int64_t nMedian = vTimeOffsets.median();
        std::vector<int64_t> vSorted = vTimeOffsets.sorted();
        // Only let other nodes change our time by so much
        if (abs64(nMedian) <= std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT))) {
            nTimeOffset = nMedian;
        } else {
            nTimeOffset = 0;

            static bool fDone;
            if (!fDone) {
                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
                bool fMatch = false;
                for (const int64_t nOffset : vSorted) {
                    if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true;
                }

                if (!fMatch) {
                    fDone = true;
                    bilingual_str strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), PACKAGE_NAME);
                    SetMiscWarning(strMessage.translated);
                    uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
                }
            }
        }

        if (LogAcceptCategory(BCLog::NET)) {
            for (const int64_t n : vSorted) {
                LogPrint(BCLog::NET, "%+d  ", n); /* Continued */
            }
            LogPrint(BCLog::NET, "|  "); /* Continued */
            LogPrint(BCLog::NET, "nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset / 60);
        }
    }
}
<|endoftext|>