<commit_before>//
// Aspia Project
// Copyright (C) 2020 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "peer/peer_controller.h"

#include "base/logging.h"
#include "base/task_runner.h"
#include "peer/client_authenticator.h"
#include "proto/router.pb.h"

namespace peer {

namespace {

const std::chrono::seconds kReconnectTimeout{ 15 };

} // namespace

PeerController::PeerController(std::shared_ptr<base::TaskRunner> task_runner)
    : task_runner_(task_runner),
      reconnect_timer_(task_runner)
{
    // TODO
}

PeerController::~PeerController()
{
    // TODO
}

void PeerController::start(const RouterInfo& router_info, Delegate* delegate)
{
    router_info_ = router_info;
    delegate_ = delegate;

    if (!delegate_)
    {
        LOG(LS_ERROR) << "Invalid parameters";
        return;
    }

    LOG(LS_INFO) << "Starting peer controller for router: "
                 << router_info_.address << ":" << router_info_.port;

    connectToRouter();
}

void PeerController::connectTo(peer::PeerId peer_id)
{
    // TODO
}

void PeerController::onConnected()
{
    LOG(LS_INFO) << "Connection to the router is established";

    static const std::chrono::seconds kKeepAliveTime{ 30 };
    static const std::chrono::seconds kKeepAliveInterval{ 3 };

    channel_->setKeepAlive(true, kKeepAliveTime, kKeepAliveInterval);
    channel_->setNoDelay(true);

    authenticator_ = std::make_unique<peer::ClientAuthenticator>(task_runner_);

    authenticator_->setIdentify(proto::IDENTIFY_ANONYMOUS);
    authenticator_->setPeerPublicKey(router_info_.public_key);
    authenticator_->setSessionType(proto::ROUTER_SESSION_ANONIMOUS_PEER);

    authenticator_->start(std::move(channel_),
                          [this](peer::ClientAuthenticator::ErrorCode error_code)
    {
        if (error_code == peer::ClientAuthenticator::ErrorCode::SUCCESS)
        {
            // The authenticator takes the listener on itself, we return the receipt of
            // notifications.
            channel_ = authenticator_->takeChannel();
            channel_->setListener(this);

            LOG(LS_INFO) << "Router connected. Receiving peer ID...";

            delegate_->onRouterConnected();

            proto::PeerToRouter message;
            proto::PeerIdRequest* peer_id_request = message.mutable_peer_id_request();

            if (router_info_.peer_key.empty())
            {
                peer_id_request->set_type(proto::PeerIdRequest::NEW_ID);
            }
            else
            {
                peer_id_request->set_type(proto::PeerIdRequest::EXISTING_ID);
                peer_id_request->set_key(base::toStdString(router_info_.peer_key));
            }

            // Now the session will receive incoming messages.
            channel_->resume();

            // Send peer ID request.
            channel_->send(base::serialize(message));
        }
        else
        {
            LOG(LS_WARNING) << "Authentication failed: "
                            << ClientAuthenticator::errorToString(error_code);
            delayedConnectToRouter();
        }

        // Authenticator is no longer needed.
        task_runner_->deleteSoon(std::move(authenticator_));
    });
}

void PeerController::onDisconnected(base::NetworkChannel::ErrorCode error_code)
{
    LOG(LS_INFO) << "Connection to the router is lost ("
                 << base::NetworkChannel::errorToString(error_code) << ")";

    delegate_->onPeerIdAssigned(kInvalidPeerId, base::ByteArray());
    delegate_->onRouterDisconnected(error_code);
    peer_id_ = kInvalidPeerId;

    delayedConnectToRouter();
}

void PeerController::onMessageReceived(const base::ByteArray& buffer)
{
    proto::RouterToPeer message;

    if (!base::parse(buffer, &message))
    {
        LOG(LS_ERROR) << "Invalid message from router";
        return;
    }

    if (message.has_peer_id_response())
    {
        if (peer_id_ != kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Peer ID already assigned";
            return;
        }

        const proto::PeerIdResponse& peer_id_response = message.peer_id_response();
        if (peer_id_response.peer_id() == kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Invalid peer ID received";
            return;
        }

        LOG(LS_INFO) << "Peer ID received: " << peer_id_response.peer_id();

        router_info_.peer_key = base::fromStdString(peer_id_response.key());
        peer_id_ = peer_id_response.peer_id();

        delegate_->onPeerIdAssigned(peer_id_, router_info_.peer_key);
    }
    else
    {
        if (peer_id_ == kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Request could not be processed (peer ID not received yet)";
            return;
        }

        if (message.has_connection_request())
        {
            LOG(LS_INFO) << "CONNECTION REQUEST";
        }
        else if (message.has_connection_response())
        {
            LOG(LS_INFO) << "CONNECTION RESPONSE";
        }
        else if (message.has_connection_offer())
        {
            LOG(LS_INFO) << "CONNECTION OFFER";
        }
        else
        {
            LOG(LS_WARNING) << "Unhandled message from router";
        }
    }
}

void PeerController::onMessageWritten(size_t /* pending */)
{
    // Nothing
}

void PeerController::connectToRouter()
{
    LOG(LS_INFO) << "Connecting to router...";

    channel_ = std::make_unique<base::NetworkChannel>();
    channel_->setListener(this);
    channel_->connect(router_info_.address, router_info_.port);
}

void PeerController::delayedConnectToRouter()
{
    LOG(LS_INFO) << "Reconnect after " << kReconnectTimeout.count() << " seconds";
    reconnect_timer_.start(kReconnectTimeout, std::bind(&PeerController::connectToRouter, this));
}

} // namespace peer
<commit_msg>Overwrite only not empty key.<commit_after>//
// Aspia Project
// Copyright (C) 2020 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "peer/peer_controller.h"

#include "base/logging.h"
#include "base/task_runner.h"
#include "peer/client_authenticator.h"
#include "proto/router.pb.h"

namespace peer {

namespace {

const std::chrono::seconds kReconnectTimeout{ 15 };

} // namespace

PeerController::PeerController(std::shared_ptr<base::TaskRunner> task_runner)
    : task_runner_(task_runner),
      reconnect_timer_(task_runner)
{
    // TODO
}

PeerController::~PeerController()
{
    // TODO
}

void PeerController::start(const RouterInfo& router_info, Delegate* delegate)
{
    router_info_ = router_info;
    delegate_ = delegate;

    if (!delegate_)
    {
        LOG(LS_ERROR) << "Invalid parameters";
        return;
    }

    LOG(LS_INFO) << "Starting peer controller for router: "
                 << router_info_.address << ":" << router_info_.port;

    connectToRouter();
}

void PeerController::connectTo(peer::PeerId peer_id)
{
    // TODO
}

void PeerController::onConnected()
{
    LOG(LS_INFO) << "Connection to the router is established";

    static const std::chrono::seconds kKeepAliveTime{ 30 };
    static const std::chrono::seconds kKeepAliveInterval{ 3 };

    channel_->setKeepAlive(true, kKeepAliveTime, kKeepAliveInterval);
    channel_->setNoDelay(true);

    authenticator_ = std::make_unique<peer::ClientAuthenticator>(task_runner_);

    authenticator_->setIdentify(proto::IDENTIFY_ANONYMOUS);
    authenticator_->setPeerPublicKey(router_info_.public_key);
    authenticator_->setSessionType(proto::ROUTER_SESSION_ANONIMOUS_PEER);

    authenticator_->start(std::move(channel_),
                          [this](peer::ClientAuthenticator::ErrorCode error_code)
    {
        if (error_code == peer::ClientAuthenticator::ErrorCode::SUCCESS)
        {
            // The authenticator takes the listener on itself, we return the receipt of
            // notifications.
            channel_ = authenticator_->takeChannel();
            channel_->setListener(this);

            LOG(LS_INFO) << "Router connected. Receiving peer ID...";

            delegate_->onRouterConnected();

            proto::PeerToRouter message;
            proto::PeerIdRequest* peer_id_request = message.mutable_peer_id_request();

            if (router_info_.peer_key.empty())
            {
                peer_id_request->set_type(proto::PeerIdRequest::NEW_ID);
            }
            else
            {
                peer_id_request->set_type(proto::PeerIdRequest::EXISTING_ID);
                peer_id_request->set_key(base::toStdString(router_info_.peer_key));
            }

            // Now the session will receive incoming messages.
            channel_->resume();

            // Send peer ID request.
            channel_->send(base::serialize(message));
        }
        else
        {
            LOG(LS_WARNING) << "Authentication failed: "
                            << ClientAuthenticator::errorToString(error_code);
            delayedConnectToRouter();
        }

        // Authenticator is no longer needed.
        task_runner_->deleteSoon(std::move(authenticator_));
    });
}

void PeerController::onDisconnected(base::NetworkChannel::ErrorCode error_code)
{
    LOG(LS_INFO) << "Connection to the router is lost ("
                 << base::NetworkChannel::errorToString(error_code) << ")";

    delegate_->onPeerIdAssigned(kInvalidPeerId, base::ByteArray());
    delegate_->onRouterDisconnected(error_code);
    peer_id_ = kInvalidPeerId;

    delayedConnectToRouter();
}

void PeerController::onMessageReceived(const base::ByteArray& buffer)
{
    proto::RouterToPeer message;

    if (!base::parse(buffer, &message))
    {
        LOG(LS_ERROR) << "Invalid message from router";
        return;
    }

    if (message.has_peer_id_response())
    {
        if (peer_id_ != kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Peer ID already assigned";
            return;
        }

        const proto::PeerIdResponse& peer_id_response = message.peer_id_response();
        if (peer_id_response.peer_id() == kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Invalid peer ID received";
            return;
        }

        LOG(LS_INFO) << "Peer ID received: " << peer_id_response.peer_id();

        base::ByteArray peer_key = base::fromStdString(peer_id_response.key());
        if (!peer_key.empty())
            router_info_.peer_key = base::fromStdString(peer_id_response.key());
        peer_id_ = peer_id_response.peer_id();

        delegate_->onPeerIdAssigned(peer_id_, router_info_.peer_key);
    }
    else
    {
        if (peer_id_ == kInvalidPeerId)
        {
            LOG(LS_ERROR) << "Request could not be processed (peer ID not received yet)";
            return;
        }

        if (message.has_connection_request())
        {
            LOG(LS_INFO) << "CONNECTION REQUEST";
        }
        else if (message.has_connection_response())
        {
            LOG(LS_INFO) << "CONNECTION RESPONSE";
        }
        else if (message.has_connection_offer())
        {
            LOG(LS_INFO) << "CONNECTION OFFER";
        }
        else
        {
            LOG(LS_WARNING) << "Unhandled message from router";
        }
    }
}

void PeerController::onMessageWritten(size_t /* pending */)
{
    // Nothing
}

void PeerController::connectToRouter()
{
    LOG(LS_INFO) << "Connecting to router...";

    channel_ = std::make_unique<base::NetworkChannel>();
    channel_->setListener(this);
    channel_->connect(router_info_.address, router_info_.port);
}

void PeerController::delayedConnectToRouter()
{
    LOG(LS_INFO) << "Reconnect after " << kReconnectTimeout.count() << " seconds";
    reconnect_timer_.start(kReconnectTimeout, std::bind(&PeerController::connectToRouter, this));
}

} // namespace peer
<|endoftext|>


<commit_before>/**
 * \file
 * \brief Scheduler class implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-01-24
 */

#include "distortos/scheduler/Scheduler.hpp"

#include "distortos/SoftwareTimer.hpp"
#include "distortos/scheduler/MainThreadControlBlock.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"
#include "distortos/architecture/InterruptUnmaskingLock.hpp"

#include <cerrno>

namespace distortos
{

namespace scheduler
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Forces unconditional context switch.
 *
 * Temporarily disables any interrupt masking and requests unconditional context switch.
 */

void forceContextSwitch()
{
	architecture::requestContextSwitch();
	architecture::InterruptUnmaskingLock interruptUnmaskingLock;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

Scheduler::Scheduler() :
		currentThreadControlBlock_{},
		mutexControlBlockListAllocatorPool_{},
		threadControlBlockListAllocatorPool_{},
		threadControlBlockListAllocator_{threadControlBlockListAllocatorPool_},
		runnableList_{threadControlBlockListAllocator_, ThreadControlBlock::State::Runnable},
		suspendedList_{threadControlBlockListAllocator_, ThreadControlBlock::State::Suspended},
		softwareTimerControlBlockSupervisor_{},
		contextSwitchCount_{},
		tickCount_{}
{

}

void Scheduler::add(ThreadControlBlock& threadControlBlock)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	addInternal(threadControlBlock);
	maybeRequestContextSwitch();
}

void Scheduler::block(ThreadControlBlockList& container)
{
	block(container, currentThreadControlBlock_);
}

int Scheduler::block(ThreadControlBlockList& container, const ThreadControlBlockListIterator iterator)
{
	{
		architecture::InterruptMaskingLock interruptMaskingLock;

		const auto ret = blockInternal(container, iterator);
		if (ret != 0)
			return ret;

		if (iterator != currentThreadControlBlock_)	// blocked thread is not current thread - no forced switch required
			return 0;
	}

	forceContextSwitch();

	return 0;
}

int Scheduler::blockUntil(ThreadControlBlockList& container, const TickClock::time_point timePoint)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	const auto iterator = currentThreadControlBlock_;
	// This lambda unblocks the thread only if it wasn't already unblocked - this is necessary because double unblock
	// should be avoided (it could mess the order of threads of the same priority). In that case it also sets
	// UnblockReason::Timeout.
	auto softwareTimer = makeSoftwareTimer([this, iterator]()
			{
				if (iterator->get().getList() != &runnableList_)
					unblockInternal(iterator, ThreadControlBlock::UnblockReason::Timeout);
			});
	softwareTimer.start(timePoint);

	block(container);

	const auto unblockReason = currentThreadControlBlock_->get().getUnblockReason();
	return unblockReason == ThreadControlBlock::UnblockReason::UnblockRequest ? 0 : ETIMEDOUT;
}

uint64_t Scheduler::getContextSwitchCount() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return contextSwitchCount_;
}

uint64_t Scheduler::getTickCount() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return tickCount_;
}

void Scheduler::initialize(MainThreadControlBlock& mainThreadControlBlock)
{
	addInternal(mainThreadControlBlock);
	currentThreadControlBlock_ = runnableList_.begin();
}

void Scheduler::maybeRequestContextSwitch() const
{
	if (isContextSwitchRequired() == true)
		architecture::requestContextSwitch();
}

int Scheduler::remove()
{
	{
		architecture::InterruptMaskingLock interruptMaskingLock;
		ThreadControlBlockList terminatedList {threadControlBlockListAllocator_, ThreadControlBlock::State::Terminated};

		const auto ret = blockInternal(terminatedList, currentThreadControlBlock_);
		if (ret != 0)
			return ret;

		terminatedList.begin()->get().terminationHook();
	}

	forceContextSwitch();

	return 0;
}

int Scheduler::resume(const ThreadControlBlockListIterator iterator)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	if (iterator->get().getList() != &suspendedList_)
		return EINVAL;

	unblock(iterator);
	return 0;
}

void Scheduler::suspend()
{
	suspend(currentThreadControlBlock_);
}

int Scheduler::suspend(const ThreadControlBlockListIterator iterator)
{
	return block(suspendedList_, iterator);
}

void* Scheduler::switchContext(void* const stackPointer)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	++contextSwitchCount_;
	getCurrentThreadControlBlock().getStack().setStackPointer(stackPointer);
	currentThreadControlBlock_ = runnableList_.begin();
	return getCurrentThreadControlBlock().getStack().getStackPointer();
}

bool Scheduler::tickInterruptHandler()
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	++tickCount_;

	getCurrentThreadControlBlock().getRoundRobinQuantum().decrement();

	// if the object is on the "runnable" list, it uses SchedulingPolicy::RoundRobin and it used its round-robin
	// quantum, then do the "rotation": move current thread to the end of same-priority group to implement round-robin
	// scheduling
	if (getCurrentThreadControlBlock().getList() == &runnableList_ &&
			getCurrentThreadControlBlock().getSchedulingPolicy() == SchedulingPolicy::RoundRobin &&
			getCurrentThreadControlBlock().getRoundRobinQuantum().isZero() == true)
	{
		getCurrentThreadControlBlock().getRoundRobinQuantum().reset();
		runnableList_.sortedSplice(runnableList_, currentThreadControlBlock_);
	}

	softwareTimerControlBlockSupervisor_.tickInterruptHandler(TickClock::time_point{TickClock::duration{tickCount_}});

	return isContextSwitchRequired();
}

void Scheduler::unblock(const ThreadControlBlockListIterator iterator)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	unblockInternal(iterator);
	maybeRequestContextSwitch();
}

void Scheduler::yield()
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	runnableList_.sortedSplice(runnableList_, currentThreadControlBlock_);
	maybeRequestContextSwitch();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void Scheduler::addInternal(ThreadControlBlock& threadControlBlock)
{
	threadControlBlockListAllocatorPool_.feed(threadControlBlock.getLink());
	runnableList_.sortedEmplace(threadControlBlock);
}

int Scheduler::blockInternal(ThreadControlBlockList& container, const ThreadControlBlockListIterator iterator)
{
	if (iterator->get().getList() != &runnableList_)
		return EINVAL;

	container.sortedSplice(runnableList_, iterator);

	return 0;
}

bool Scheduler::isContextSwitchRequired() const
{
	if (getCurrentThreadControlBlock().getList() != &runnableList_)
		return true;

	if (runnableList_.begin() != currentThreadControlBlock_)	// is there a higher-priority thread available?
		return true;

	return false;
}

void Scheduler::unblockInternal(const ThreadControlBlockListIterator iterator,
		const ThreadControlBlock::UnblockReason unblockReason)
{
	runnableList_.sortedSplice(*iterator->get().getList(), iterator);
	iterator->get().getRoundRobinQuantum().reset();
	iterator->get().setUnblockReason(unblockReason);
}

}	// namespace scheduler

}	// namespace distortos
<commit_msg>Scheduler::unblockInternal(): call ThreadControlBlock::unblockHook() instead of calling RoundRobinQuantum::reset() and ThreadControlBlock::setUnblockReason()<commit_after>/**
 * \file
 * \brief Scheduler class implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-02-01
 */

#include "distortos/scheduler/Scheduler.hpp"

#include "distortos/SoftwareTimer.hpp"
#include "distortos/scheduler/MainThreadControlBlock.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"
#include "distortos/architecture/InterruptUnmaskingLock.hpp"

#include <cerrno>

namespace distortos
{

namespace scheduler
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Forces unconditional context switch.
 *
 * Temporarily disables any interrupt masking and requests unconditional context switch.
 */

void forceContextSwitch()
{
	architecture::requestContextSwitch();
	architecture::InterruptUnmaskingLock interruptUnmaskingLock;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

Scheduler::Scheduler() :
		currentThreadControlBlock_{},
		mutexControlBlockListAllocatorPool_{},
		threadControlBlockListAllocatorPool_{},
		threadControlBlockListAllocator_{threadControlBlockListAllocatorPool_},
		runnableList_{threadControlBlockListAllocator_, ThreadControlBlock::State::Runnable},
		suspendedList_{threadControlBlockListAllocator_, ThreadControlBlock::State::Suspended},
		softwareTimerControlBlockSupervisor_{},
		contextSwitchCount_{},
		tickCount_{}
{

}

void Scheduler::add(ThreadControlBlock& threadControlBlock)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	addInternal(threadControlBlock);
	maybeRequestContextSwitch();
}

void Scheduler::block(ThreadControlBlockList& container)
{
	block(container, currentThreadControlBlock_);
}

int Scheduler::block(ThreadControlBlockList& container, const ThreadControlBlockListIterator iterator)
{
	{
		architecture::InterruptMaskingLock interruptMaskingLock;

		const auto ret = blockInternal(container, iterator);
		if (ret != 0)
			return ret;

		if (iterator != currentThreadControlBlock_)	// blocked thread is not current thread - no forced switch required
			return 0;
	}

	forceContextSwitch();

	return 0;
}

int Scheduler::blockUntil(ThreadControlBlockList& container, const TickClock::time_point timePoint)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	const auto iterator = currentThreadControlBlock_;
	// This lambda unblocks the thread only if it wasn't already unblocked - this is necessary because double unblock
	// should be avoided (it could mess the order of threads of the same priority). In that case it also sets
	// UnblockReason::Timeout.
	auto softwareTimer = makeSoftwareTimer([this, iterator]()
			{
				if (iterator->get().getList() != &runnableList_)
					unblockInternal(iterator, ThreadControlBlock::UnblockReason::Timeout);
			});
	softwareTimer.start(timePoint);

	block(container);

	const auto unblockReason = currentThreadControlBlock_->get().getUnblockReason();
	return unblockReason == ThreadControlBlock::UnblockReason::UnblockRequest ? 0 : ETIMEDOUT;
}

uint64_t Scheduler::getContextSwitchCount() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return contextSwitchCount_;
}

uint64_t Scheduler::getTickCount() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return tickCount_;
}

void Scheduler::initialize(MainThreadControlBlock& mainThreadControlBlock)
{
	addInternal(mainThreadControlBlock);
	currentThreadControlBlock_ = runnableList_.begin();
}

void Scheduler::maybeRequestContextSwitch() const
{
	if (isContextSwitchRequired() == true)
		architecture::requestContextSwitch();
}

int Scheduler::remove()
{
	{
		architecture::InterruptMaskingLock interruptMaskingLock;
		ThreadControlBlockList terminatedList {threadControlBlockListAllocator_, ThreadControlBlock::State::Terminated};

		const auto ret = blockInternal(terminatedList, currentThreadControlBlock_);
		if (ret != 0)
			return ret;

		terminatedList.begin()->get().terminationHook();
	}

	forceContextSwitch();

	return 0;
}

int Scheduler::resume(const ThreadControlBlockListIterator iterator)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	if (iterator->get().getList() != &suspendedList_)
		return EINVAL;

	unblock(iterator);
	return 0;
}

void Scheduler::suspend()
{
	suspend(currentThreadControlBlock_);
}

int Scheduler::suspend(const ThreadControlBlockListIterator iterator)
{
	return block(suspendedList_, iterator);
}

void* Scheduler::switchContext(void* const stackPointer)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	++contextSwitchCount_;
	getCurrentThreadControlBlock().getStack().setStackPointer(stackPointer);
	currentThreadControlBlock_ = runnableList_.begin();
	return getCurrentThreadControlBlock().getStack().getStackPointer();
}

bool Scheduler::tickInterruptHandler()
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	++tickCount_;

	getCurrentThreadControlBlock().getRoundRobinQuantum().decrement();

	// if the object is on the "runnable" list, it uses SchedulingPolicy::RoundRobin and it used its round-robin
	// quantum, then do the "rotation": move current thread to the end of same-priority group to implement round-robin
	// scheduling
	if (getCurrentThreadControlBlock().getList() == &runnableList_ &&
			getCurrentThreadControlBlock().getSchedulingPolicy() == SchedulingPolicy::RoundRobin &&
			getCurrentThreadControlBlock().getRoundRobinQuantum().isZero() == true)
	{
		getCurrentThreadControlBlock().getRoundRobinQuantum().reset();
		runnableList_.sortedSplice(runnableList_, currentThreadControlBlock_);
	}

	softwareTimerControlBlockSupervisor_.tickInterruptHandler(TickClock::time_point{TickClock::duration{tickCount_}});

	return isContextSwitchRequired();
}

void Scheduler::unblock(const ThreadControlBlockListIterator iterator)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	unblockInternal(iterator);
	maybeRequestContextSwitch();
}

void Scheduler::yield()
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	runnableList_.sortedSplice(runnableList_, currentThreadControlBlock_);
	maybeRequestContextSwitch();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void Scheduler::addInternal(ThreadControlBlock& threadControlBlock)
{
	threadControlBlockListAllocatorPool_.feed(threadControlBlock.getLink());
	runnableList_.sortedEmplace(threadControlBlock);
}

int Scheduler::blockInternal(ThreadControlBlockList& container, const ThreadControlBlockListIterator iterator)
{
	if (iterator->get().getList() != &runnableList_)
		return EINVAL;

	container.sortedSplice(runnableList_, iterator);

	return 0;
}

bool Scheduler::isContextSwitchRequired() const
{
	if (getCurrentThreadControlBlock().getList() != &runnableList_)
		return true;

	if (runnableList_.begin() != currentThreadControlBlock_)	// is there a higher-priority thread available?
		return true;

	return false;
}

void Scheduler::unblockInternal(const ThreadControlBlockListIterator iterator,
		const ThreadControlBlock::UnblockReason unblockReason)
{
	runnableList_.sortedSplice(*iterator->get().getList(), iterator);
	iterator->get().unblockHook(unblockReason);
}

}	// namespace scheduler

}	// namespace distortos
<|endoftext|>


<commit_before>//
//  NSolver::setup_system.cpp
//
//  Created by Lei Qiao on 15/8/9.
//  A work based on deal.II tutorial step-33.
//

#include <NSolver/solver/NSolver.h>

namespace NSFEMSolver
{
  using namespace dealii;

  // @sect4{NSolver::setup_system}
  //
  // The following (easy) function is called each time the mesh is
  // changed. All it does is to resize the Trilinos matrix according to a
  // sparsity pattern that we generate as in all the previous tutorial
  // programs.
  template <int dim>
  void NSolver<dim>::setup_system()
  {
    dof_handler.clear();
    dof_handler.distribute_dofs (fe);

    locally_owned_dofs.clear();
    locally_owned_dofs = dof_handler.locally_owned_dofs();

    locally_relevant_dofs.clear();
    DoFTools::extract_locally_relevant_dofs (dof_handler,
                                             locally_relevant_dofs);

    if (parameters->output_sparsity_pattern)
      {
        ++n_sparsity_pattern_out;
        TrilinosWrappers::SparsityPattern sparsity_pattern (locally_owned_dofs,
                                                            mpi_communicator);
        DoFTools::make_sparsity_pattern (dof_handler,
                                         sparsity_pattern,
                                         /*const ConstraintMatrix constraints = */ ConstraintMatrix(),
                                         /*const bool keep_constrained_dofs = */ true,
                                         Utilities::MPI::this_mpi_process (mpi_communicator));
        sparsity_pattern.compress();

        const std::string file_name = "sparsity_pattern."
                                      + Utilities::int_to_string (n_sparsity_pattern_out,4)
                                      + ".origin";
        std::ofstream out (file_name.c_str());
        sparsity_pattern.print_gnuplot (out);
      }

    switch (parameters->renumber_dofs)
      {
      case Parameters::AllParameters<dim>::None :
      {
        break;
      }
      case Parameters::AllParameters<dim>::RCM :
      {
        DoFRenumbering::Cuthill_McKee (dof_handler,
                                       /* reversed_numbering = */ true);
        break;
      }
      case Parameters::AllParameters<dim>::RCM_WithStartPoint :
      {
        std::vector<types::global_dof_index> dof_indices (fe.dofs_per_cell);
        Point<dim> target_point;
        for (unsigned int id=0; id<dim; ++id)
          {
            target_point[id] = parameters->renumber_start_point[id];
          }

        typename DoFHandler<dim>::active_cell_iterator
        cell = dof_handler.begin_active(),
        endc = dof_handler.end();
        unsigned int cell_index (0);
        for (; cell!=endc; ++cell, ++cell_index)
          if (cell->is_locally_owned())
            {
              if (target_point.distance (cell->center()) < 0.01)
                {
                  cell->get_dof_indices (dof_indices);
                  break;
                }
            }

        DoFRenumbering::Cuthill_McKee (dof_handler,
                                       /* reversed_numbering = */ true,
                                       /* use_constraints = */    false ,
                                       /* starting_indices */     dof_indices);
        break;
      }
      default:
      {
        Assert (false, ExcNotImplemented());
        break;
      }
      }

    TrilinosWrappers::SparsityPattern sparsity_pattern (locally_owned_dofs,
                                                        mpi_communicator);
    DoFTools::make_sparsity_pattern (dof_handler,
                                     sparsity_pattern,
                                     /*const ConstraintMatrix constraints = */ ConstraintMatrix(),
                                     /*const bool keep_constrained_dofs = */ true,
                                     Utilities::MPI::this_mpi_process (mpi_communicator));
    sparsity_pattern.compress();
    if (parameters->output_sparsity_pattern &&
        parameters->renumber_dofs != Parameters::AllParameters<dim>::None)
      {
        const std::string file_name = "sparsity_pattern."
                                      + Utilities::int_to_string (n_sparsity_pattern_out,4)
                                      + ".renumbered";
        std::ofstream out (file_name.c_str());
        sparsity_pattern.print_gnuplot (out);
      }
    system_matrix.reinit (sparsity_pattern);

    // Initialize vectors
    locally_owned_solution.reinit (locally_owned_dofs, mpi_communicator);
    current_solution.reinit (locally_relevant_dofs, mpi_communicator);

    // const bool fast = true means leave its content untouched.
    old_solution.reinit (current_solution, /*const bool fast = */ true);
    old_old_solution.reinit (current_solution, true);
    predictor.reinit (locally_owned_solution, true);

    right_hand_side.reinit (locally_owned_solution, true);
    newton_update.reinit (locally_owned_solution, true);

    residual_for_output.reinit (current_solution, true);

    entropy_viscosity.reinit (triangulation.n_active_cells());
    cellSize_viscosity.reinit (triangulation.n_active_cells());
    refinement_indicators.reinit (triangulation.n_active_cells());
  }

#include "NSolver.inst"
}
<commit_msg>Renumbering DoFs immediately after distribute_dofs, then do other following things<commit_after>//
//  NSolver::setup_system.cpp
//
//  Created by Lei Qiao on 15/8/9.
//  A work based on deal.II tutorial step-33.
//

#include <NSolver/solver/NSolver.h>

namespace NSFEMSolver
{
  using namespace dealii;

  // @sect4{NSolver::setup_system}
  //
  // The following (easy) function is called each time the mesh is
  // changed. All it does is to resize the Trilinos matrix according to a
  // sparsity pattern that we generate as in all the previous tutorial
  // programs.
  template <int dim>
  void NSolver<dim>::setup_system()
  {
    dof_handler.clear();
    dof_handler.distribute_dofs (fe);

    if (parameters->output_sparsity_pattern)
      {
        ++n_sparsity_pattern_out;
        TrilinosWrappers::SparsityPattern sparsity_pattern (locally_owned_dofs,
                                                            mpi_communicator);
        DoFTools::make_sparsity_pattern (dof_handler,
                                         sparsity_pattern,
                                         /*const ConstraintMatrix constraints = */ ConstraintMatrix(),
                                         /*const bool keep_constrained_dofs = */ true,
                                         Utilities::MPI::this_mpi_process (mpi_communicator));
        sparsity_pattern.compress();

        const std::string file_name = "sparsity_pattern."
                                      + Utilities::int_to_string (n_sparsity_pattern_out,4)
                                      + ".origin";
        std::ofstream out (file_name.c_str());
        sparsity_pattern.print_gnuplot (out);
      }

    switch (parameters->renumber_dofs)
      {
      case Parameters::AllParameters<dim>::None :
      {
        break;
      }
      case Parameters::AllParameters<dim>::RCM :
      {
        DoFRenumbering::Cuthill_McKee (dof_handler,
                                       /* reversed_numbering = */ true);
        break;
      }
      case Parameters::AllParameters<dim>::RCM_WithStartPoint :
      {
        std::vector<types::global_dof_index> dof_indices (fe.dofs_per_cell);
        Point<dim> target_point;
        for (unsigned int id=0; id<dim; ++id)
          {
            target_point[id] = parameters->renumber_start_point[id];
          }

        typename DoFHandler<dim>::active_cell_iterator
        cell = dof_handler.begin_active(),
        endc = dof_handler.end();
        unsigned int cell_index (0);
        for (; cell!=endc; ++cell, ++cell_index)
          if (cell->is_locally_owned())
            {
              if (target_point.distance (cell->center()) < 0.01)
                {
                  cell->get_dof_indices (dof_indices);
                  break;
                }
            }

        DoFRenumbering::Cuthill_McKee (dof_handler,
                                       /* reversed_numbering = */ true,
                                       /* use_constraints = */    false ,
                                       /* starting_indices */     dof_indices);
        break;
      }
      default:
      {
        Assert (false, ExcNotImplemented());
        break;
      }
      }

    locally_owned_dofs.clear();
    locally_owned_dofs = dof_handler.locally_owned_dofs();

    locally_relevant_dofs.clear();
    DoFTools::extract_locally_relevant_dofs (dof_handler,
                                             locally_relevant_dofs);

    TrilinosWrappers::SparsityPattern sparsity_pattern (locally_owned_dofs,
                                                        mpi_communicator);
    DoFTools::make_sparsity_pattern (dof_handler,
                                     sparsity_pattern,
                                     /*const ConstraintMatrix constraints = */ ConstraintMatrix(),
                                     /*const bool keep_constrained_dofs = */ true,
                                     Utilities::MPI::this_mpi_process (mpi_communicator));
    sparsity_pattern.compress();
    if (parameters->output_sparsity_pattern &&
        parameters->renumber_dofs != Parameters::AllParameters<dim>::None)
      {
        const std::string file_name = "sparsity_pattern."
                                      + Utilities::int_to_string (n_sparsity_pattern_out,4)
                                      + ".renumbered";
        std::ofstream out (file_name.c_str());
        sparsity_pattern.print_gnuplot (out);
      }
    system_matrix.reinit (sparsity_pattern);

    // Initialize vectors
    locally_owned_solution.reinit (locally_owned_dofs, mpi_communicator);
    current_solution.reinit (locally_relevant_dofs, mpi_communicator);

    // const bool fast = true means leave its content untouched.
    old_solution.reinit (current_solution, /*const bool fast = */ true);
    old_old_solution.reinit (current_solution, true);
    predictor.reinit (locally_owned_solution, true);

    right_hand_side.reinit (locally_owned_solution, true);
    newton_update.reinit (locally_owned_solution, true);

    residual_for_output.reinit (current_solution, true);

    entropy_viscosity.reinit (triangulation.n_active_cells());
    cellSize_viscosity.reinit (triangulation.n_active_cells());
    refinement_indicators.reinit (triangulation.n_active_cells());
  }

#include "NSolver.inst"
}
<|endoftext|>


<commit_before>#include "gui/qrworkspace.h"

#include <QtCore/qmap.h>
#include <QtCore/qdebug.h>
#include <QtWidgets/qwidget.h>
#include <QtWidgets/qscrollarea.h>
#include <QtWidgets/qtabbar.h>

#include "gui/qrworkspacewidget.h"

NS_CHAOS_BASE_BEGIN

class QrWorkspacePrivate{
    QR_DECLARE_PUBLIC(QrWorkspace)

public:
    static QrWorkspace* qInstance;

    int lastIndex = -1;
    QMap<QrWorkspaceWidget*, QScrollArea*> existedTabWidgets;

public:
    QrWorkspacePrivate(QrWorkspace *q);

public:
    static QrWorkspacePrivate* dInstance();
    QrWorkspaceWidget* getWorkspaceWidget(int index);
};

QrWorkspace* QrWorkspacePrivate::qInstance = nullptr;

QrWorkspacePrivate::QrWorkspacePrivate(QrWorkspace *q)
    : q_ptr(q) {
    qInstance = q;
}

QrWorkspacePrivate *QrWorkspacePrivate::dInstance(){
    Q_ASSERT(nullptr != QrWorkspacePrivate::qInstance);
    return QrWorkspacePrivate::qInstance->d_func();
}

QrWorkspaceWidget *QrWorkspacePrivate::getWorkspaceWidget(int index)
{
    Q_Q(QrWorkspace);
    return qobject_cast<QrWorkspaceWidget*>(
                qobject_cast<QScrollArea*>(q->widget(index))->widget());
}

NS_CHAOS_BASE_END

USING_NS_CHAOS_BASE;

QrWorkspace::QrWorkspace(QWidget *parent)
    :QTabWidget(parent), d_ptr(new QrWorkspacePrivate(this))
{
    tabBar()->setObjectName("workspace_tabbar");
    setTabsClosable(true);

    connect(this, &QrWorkspace::tabCloseRequested, [this](int index){
        Q_D(QrWorkspace);
        QrWorkspaceWidget *workspaceWidget = d->getWorkspaceWidget(index);
        if(! workspaceWidget->closeRequested()) {
            qDebug() << "workspace widget reject to close.";
            return;
        }
        d->existedTabWidgets.remove(workspaceWidget);
        removeTab(index);
    });
    connect(this, &QrWorkspace::currentChanged, [this](int index){
        Q_D(QrWorkspace);
        QrWorkspaceWidget *workspaceWidget = d->getWorkspaceWidget(index);
        workspaceWidget->switchFrom(d->lastIndex);
        d->lastIndex = index;
    });
}

int QrWorkspace::appendTab(QrWorkspaceWidget *widget, QString label, bool autoExpanding /*= true*/)
{
    if (nullptr == widget) {
        qWarning() << "widget append to tag is null.";
        return -1;
    }

    auto q = QrWorkspacePrivate::qInstance;
    Q_ASSERT(nullptr != q);
    auto d = QrWorkspacePrivate::dInstance();
    if (d->existedTabWidgets.contains(widget)) {
        qInfo() << label << " widget is exist. show previous widget.";
        auto preIndex = q->indexOf(d->existedTabWidgets[widget]);
        q->setTabText(preIndex, label);
        q->setCurrentIndex(preIndex);

        d->lastIndex = preIndex;

        return preIndex;
    }

    if(autoExpanding) {
        widget->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
    }

    auto wrapWidget = new QScrollArea();
    wrapWidget->setWidget (widget);
    wrapWidget->setWidgetResizable(true);
    d->existedTabWidgets[widget] = wrapWidget;

    auto tabIndex = q->addTab(wrapWidget, label);
    q->setCurrentIndex(tabIndex);

    d->lastIndex = tabIndex;

    return tabIndex;
}

<commit_msg>fix crash bug<commit_after>#include "gui/qrworkspace.h"

#include <QtCore/qmap.h>
#include <QtCore/qdebug.h>
#include <QtWidgets/qwidget.h>
#include <QtWidgets/qscrollarea.h>
#include <QtWidgets/qtabbar.h>

#include "gui/qrworkspacewidget.h"

NS_CHAOS_BASE_BEGIN

class QrWorkspacePrivate{
    QR_DECLARE_PUBLIC(QrWorkspace)

public:
    static QrWorkspace* qInstance;

    int lastIndex = -1;
    QMap<QrWorkspaceWidget*, QScrollArea*> existedTabWidgets;

public:
    QrWorkspacePrivate(QrWorkspace *q);

public:
    static QrWorkspacePrivate* dInstance();
    QrWorkspaceWidget* getWorkspaceWidget(int index);
};

QrWorkspace* QrWorkspacePrivate::qInstance = nullptr;

QrWorkspacePrivate::QrWorkspacePrivate(QrWorkspace *q)
    : q_ptr(q) {
    qInstance = q;
}

QrWorkspacePrivate *QrWorkspacePrivate::dInstance(){
    Q_ASSERT(nullptr != QrWorkspacePrivate::qInstance);
    return QrWorkspacePrivate::qInstance->d_func();
}

QrWorkspaceWidget *QrWorkspacePrivate::getWorkspaceWidget(int index)
{
    Q_Q(QrWorkspace);
    QScrollArea* wrapWidget = qobject_cast<QScrollArea*>(q->widget(index));
    if(nullptr == wrapWidget) {
        qDebug() << "wrap widget is nullptr";
        return nullptr;
    }

    return qobject_cast<QrWorkspaceWidget*>(wrapWidget->widget());
}

NS_CHAOS_BASE_END

USING_NS_CHAOS_BASE;

QrWorkspace::QrWorkspace(QWidget *parent)
    :QTabWidget(parent), d_ptr(new QrWorkspacePrivate(this))
{
    tabBar()->setObjectName("workspace_tabbar");
    setTabsClosable(true);

    connect(this, &QrWorkspace::tabCloseRequested, [this](int index){
        Q_D(QrWorkspace);
        QrWorkspaceWidget *workspaceWidget = d->getWorkspaceWidget(index);
        if(nullptr == workspaceWidget) {
            qDebug() << "workspace widget is nullptr.";
            return;
        }
        if(! workspaceWidget->closeRequested()) {
            qDebug() << "workspace widget reject to close.";
            return;
        }
        d->existedTabWidgets.remove(workspaceWidget);
        removeTab(index);
    });
    connect(this, &QrWorkspace::currentChanged, [this](int index){
        Q_D(QrWorkspace);
        QrWorkspaceWidget *workspaceWidget = d->getWorkspaceWidget(index);
        if(nullptr != workspaceWidget) {
            workspaceWidget->switchFrom(d->lastIndex);
        } else {
            qDebug() << "workspace widget is nullptr.";
        }
        d->lastIndex = index;
    });
}

int QrWorkspace::appendTab(QrWorkspaceWidget *widget, QString label, bool autoExpanding /*= true*/)
{
    if (nullptr == widget) {
        qWarning() << "widget append to tag is null.";
        return -1;
    }

    auto q = QrWorkspacePrivate::qInstance;
    Q_ASSERT(nullptr != q);
    auto d = QrWorkspacePrivate::dInstance();
    if (d->existedTabWidgets.contains(widget)) {
        qInfo() << label << " widget is exist. show previous widget.";
        auto preIndex = q->indexOf(d->existedTabWidgets[widget]);
        q->setTabText(preIndex, label);
        q->setCurrentIndex(preIndex);

        d->lastIndex = preIndex;

        return preIndex;
    }

    if(autoExpanding) {
        widget->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
    }

    auto wrapWidget = new QScrollArea(q);
    wrapWidget->setWidget (widget);
    wrapWidget->setWidgetResizable(true);
    d->existedTabWidgets[widget] = wrapWidget;

    auto tabIndex = q->addTab(wrapWidget, label);
    q->setCurrentIndex(tabIndex);

    d->lastIndex = tabIndex;

    return tabIndex;
}

<|endoftext|>


<commit_before>#ifndef RBX_STATE_HPP
#define RBX_STATE_HPP

namespace rubinius {
  class VM;
  class VMJIT;
  class ManagedThread;
  class VMThreadState;
  class SharedState;

  class State {
    VM* vm_;
    VMJIT* vm_jit_;
    SharedState& shared_;

  public:
    State(VM* vm)
      : vm_(vm)
      , vm_jit_(&vm->vm_jit_)
      , shared_(vm->shared)
    {}

    VM* vm() {
      return vm_;
    }

    ManagedThread* thread() {
      return static_cast<ManagedThread*>(vm_);
    }

    Object* raise_exception(Exception* exc) {
      vm_->thread_state()->raise_exception(exc);
      return 0;
    }

    void set_vm(VM* vm) {
      vm_ = vm;
    }

    void set_call_frame(CallFrame* cf) {
      vm_->set_call_frame(cf);
    }

    Globals& globals() {
      return shared_.globals;
    }

    Symbol* symbol(const char* str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(std::string str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(String* str) {
      return vm_->symbol(str);
    }

    uint32_t hash_seed() {
      return shared_.hash_seed;
    }

    template <class T>
      T* new_object(Class *cls) {
        return static_cast<T*>(vm_->new_object_typed(cls, sizeof(T), T::type));
      }

    template <class T>
      T* new_object_dirty(Class *cls) {
        return static_cast<T*>(vm_->new_object_typed_dirty(cls, sizeof(T), T::type));
      }

    VMThreadState* thread_state() {
      return vm_->thread_state();
    }

    ObjectMemory* memory() {
      return shared_.memory();
    }

    SharedState& shared() {
      return shared_;
    }

    bool detect_stack_condition(void* end) {
      return vm_->detect_stack_condition(end);
    }

    bool check_local_interrupts() {
      return vm_jit_->check_local_interrupts_;
    }

    bool check_async(CallFrame* call_frame) {
      state->set_call_frame(state);
      if(vm_->check_local_interrupts()) {
        return process_async(call_frame);
      }
      return true;
    }

    void raise_stack_error(CallFrame* call_frame);

    bool check_stack(CallFrame* call_frame, void* end) {
      // @TODO assumes stack growth direction
      if(unlikely(vm_->detect_stack_condition(end))) {
        raise_stack_error(call_frame);
        return false;
      }
      return true;
    }

    bool process_async(CallFrame* call_frame);
    void check_exception(CallFrame* call_frame);
    bool check_interrupts(GCToken gct, CallFrame* call_frame, void* end);

    gc::Slab& local_slab() {
      return vm_->local_slab();
    }

    bool stop_the_world() WARN_UNUSED {
      return shared_.stop_the_world(vm_);
    };

    void restart_world() {
      shared_.restart_world(vm_);
    }

    void gc_independent(GCToken gct) {
      shared_.gc_independent(vm_);
    }

    void gc_dependent() {
      shared_.gc_dependent(vm_);
    }

    void checkpoint(GCToken gct, CallFrame* call_frame) {
      vm_->set_call_frame(call_frame);
      gc_checkpoint(gct, call_frame);
      shared_.checkpoint(vm_);
    }

    void gc_checkpoint(GCToken gct, CallFrame* frame) {
      if(unlikely(shared_.check_gc_p())) {
        vm_->collect_maybe(gct, frame);
      }
    }

    void lock(GCToken gct) {
      gc_independent(gct);
      vm_->lock(vm_);
      gc_dependent();
    }

    void unlock() {
      vm_->unlock(vm_);
    }

    Object* park(GCToken gct, CallFrame* call_frame);

    Object* park_timed(GCToken gct, CallFrame* call_frame, struct timespec* ts);
  };
}

#endif
<commit_msg>Properly fix the call_frame setting<commit_after>#ifndef RBX_STATE_HPP
#define RBX_STATE_HPP

namespace rubinius {
  class VM;
  class VMJIT;
  class ManagedThread;
  class VMThreadState;
  class SharedState;

  class State {
    VM* vm_;
    VMJIT* vm_jit_;
    SharedState& shared_;

  public:
    State(VM* vm)
      : vm_(vm)
      , vm_jit_(&vm->vm_jit_)
      , shared_(vm->shared)
    {}

    VM* vm() {
      return vm_;
    }

    ManagedThread* thread() {
      return static_cast<ManagedThread*>(vm_);
    }

    Object* raise_exception(Exception* exc) {
      vm_->thread_state()->raise_exception(exc);
      return 0;
    }

    void set_vm(VM* vm) {
      vm_ = vm;
    }

    void set_call_frame(CallFrame* cf) {
      vm_->set_call_frame(cf);
    }

    Globals& globals() {
      return shared_.globals;
    }

    Symbol* symbol(const char* str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(std::string str) {
      return vm_->symbol(str);
    }

    Symbol* symbol(String* str) {
      return vm_->symbol(str);
    }

    uint32_t hash_seed() {
      return shared_.hash_seed;
    }

    template <class T>
      T* new_object(Class *cls) {
        return static_cast<T*>(vm_->new_object_typed(cls, sizeof(T), T::type));
      }

    template <class T>
      T* new_object_dirty(Class *cls) {
        return static_cast<T*>(vm_->new_object_typed_dirty(cls, sizeof(T), T::type));
      }

    VMThreadState* thread_state() {
      return vm_->thread_state();
    }

    ObjectMemory* memory() {
      return shared_.memory();
    }

    SharedState& shared() {
      return shared_;
    }

    bool detect_stack_condition(void* end) {
      return vm_->detect_stack_condition(end);
    }

    bool check_local_interrupts() {
      return vm_jit_->check_local_interrupts_;
    }

    bool check_async(CallFrame* call_frame) {
      set_call_frame(call_frame);
      if(vm_->check_local_interrupts()) {
        return process_async(call_frame);
      }
      return true;
    }

    void raise_stack_error(CallFrame* call_frame);

    bool check_stack(CallFrame* call_frame, void* end) {
      // @TODO assumes stack growth direction
      if(unlikely(vm_->detect_stack_condition(end))) {
        raise_stack_error(call_frame);
        return false;
      }
      return true;
    }

    bool process_async(CallFrame* call_frame);
    void check_exception(CallFrame* call_frame);
    bool check_interrupts(GCToken gct, CallFrame* call_frame, void* end);

    gc::Slab& local_slab() {
      return vm_->local_slab();
    }

    bool stop_the_world() WARN_UNUSED {
      return shared_.stop_the_world(vm_);
    };

    void restart_world() {
      shared_.restart_world(vm_);
    }

    void gc_independent(GCToken gct) {
      shared_.gc_independent(vm_);
    }

    void gc_dependent() {
      shared_.gc_dependent(vm_);
    }

    void checkpoint(GCToken gct, CallFrame* call_frame) {
      vm_->set_call_frame(call_frame);
      gc_checkpoint(gct, call_frame);
      shared_.checkpoint(vm_);
    }

    void gc_checkpoint(GCToken gct, CallFrame* frame) {
      if(unlikely(shared_.check_gc_p())) {
        vm_->collect_maybe(gct, frame);
      }
    }

    void lock(GCToken gct) {
      gc_independent(gct);
      vm_->lock(vm_);
      gc_dependent();
    }

    void unlock() {
      vm_->unlock(vm_);
    }

    Object* park(GCToken gct, CallFrame* call_frame);

    Object* park_timed(GCToken gct, CallFrame* call_frame, struct timespec* ts);
  };
}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT)
#ident "$Id: event.cc,v 1.3 2001/12/29 23:59:06 steve Exp $"
#endif

# include  "event.h"
# include  "compile.h"
# include  "vthread.h"
# include  "schedule.h"

# include  <string.h>
# include  <assert.h>
# include  <stdlib.h>
#ifdef HAVE_MALLOC_H
# include  <malloc.h>
#endif

event_functor_s::event_functor_s(edge_t e)
      : edge(e), threads(0)
{}

event_functor_s::~event_functor_s()
{}

/*
 * Receive a value into an event functor, whether an edge or event/or.
 * Detect edges, if any, then schedule awakened threads.
 */
void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
{
      old_ival = ival;
      put(ptr, val);
	/* Only go through the effort if there is someone interested
	   in the results... */
      if (threads || out) {

	    bool edge_p = true;

	      /* If there is an edge detect lookup table, then use the
		 out input and new input to detect whether this is the
		 requested edge. If there is no edge table, then any
		 set is a match. */
	    if (edge) {

		  unsigned pp = ipoint_port(ptr);

		  unsigned oval = (old_ival >> 2*pp) & 3;
		  unsigned nval = (ival     >> 2*pp) & 3;

		  unsigned val = (oval << 2) | nval;
		  edge_p = ((edge>>val) & 1) != 0;
	    }

	      /* If we detect an edge, then schedule any threads that
		 are attached to this event, then propagate the
		 positive detect to the output.

		 Note that only other events (notably event/or
		 functors) can be connected to event outputs. */

	    if (edge_p) {
		  vthread_t tmp = threads;
		  threads = 0;
		  vthread_schedule_list(tmp);

		  if (out) {
			functor_set(out, 0, St0, true);
		  }
		    // only one output?  Why not propagate?
		    //schedule_assign(out, 0, 0);
	    }
      }
}

/*
**  Create an event functor
**  edge:  compile_event(label, type, argc, argv)
**  or:    compile_event(label, NULL, argc, argv)
**  name:  compile_event(label, name, NULL, NULL)
*/

void compile_event(char*label, char*type,
		   unsigned argc, struct symb_s*argv)
{
      event_functor_s::edge_t edge = vvp_edge_none;

      if (argc && type) {
	    if (strcmp(type,"posedge") == 0)
		  edge = vvp_edge_posedge;
	    else if (strcmp(type,"negedge") == 0)
		  edge = vvp_edge_negedge;
	    else if (strcmp(type,"edge") == 0)
		  edge = vvp_edge_anyedge;

	    assert(argc <= 4 || edge == vvp_edge_none);
      }

      if (!argc && type) {
	    // "type" is the name of the named event
      }

      free(type);

      functor_t obj = new event_functor_s(edge);

      vvp_ipoint_t fdx = functor_allocate(1);
      functor_define(fdx, obj);
      define_functor_symbol(label, fdx);
      free(label);

	/* Run through the arguments looking for the functors that are
	   connected to my input ports. For each source functor that I
	   find, connect the output of that functor to the indexed
	   input by inserting myself (complete with the port number in
	   the vvp_ipoint_t) into the list that the source heads.

	   If the source functor is not declared yet, then don't do
	   the link yet. Save the reference to be resolved later. */

      if (edge != vvp_edge_none)
	    inputs_connect(fdx, argc, argv);
      else
	    // Are we sure that we have those .event/or
	    // drivers exclusively?
	    for (unsigned i=0; i<argc; i++) {
		  inputs_connect(fdx, 1, argv+i);
	    }

      free(argv);
}

/*
 * $Log: event.cc,v $
 * Revision 1.3  2001/12/29 23:59:06  steve
 *  push events through event/or lists.
 *
 * Revision 1.2  2001/11/16 04:22:27  steve
 *  include stdlib.h for portability.
 *
 * Revision 1.1  2001/11/06 03:07:22  steve
 *  Code rearrange. (Stephan Boettcher)
 *
 */
<commit_msg> Spelling in comment.<commit_after>/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT)
#ident "$Id: event.cc,v 1.4 2002/01/24 04:17:46 steve Exp $"
#endif

# include  "event.h"
# include  "compile.h"
# include  "vthread.h"
# include  "schedule.h"

# include  <string.h>
# include  <assert.h>
# include  <stdlib.h>
#ifdef HAVE_MALLOC_H
# include  <malloc.h>
#endif

event_functor_s::event_functor_s(edge_t e)
      : edge(e), threads(0)
{}

event_functor_s::~event_functor_s()
{}

/*
 * Receive a value into an event functor, whether an edge or event/or.
 * Detect edges, if any, then schedule awakened threads.
 */
void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
{
      old_ival = ival;
      put(ptr, val);
	/* Only go through the effort if there is someone interested
	   in the results... */
      if (threads || out) {

	    bool edge_p = true;

	      /* If there is an edge detect lookup table, then use the
		 old input and new input to detect whether this is the
		 requested edge. If there is no edge table, then any
		 set is a match. */
	    if (edge) {

		  unsigned pp = ipoint_port(ptr);

		  unsigned oval = (old_ival >> 2*pp) & 3;
		  unsigned nval = (ival     >> 2*pp) & 3;

		  unsigned val = (oval << 2) | nval;
		  edge_p = ((edge>>val) & 1) != 0;
	    }

	      /* If we detect an edge, then schedule any threads that
		 are attached to this event, then propagate the
		 positive detect to the output.

		 Note that only other events (notably event/or
		 functors) can be connected to event outputs. */

	    if (edge_p) {
		  vthread_t tmp = threads;
		  threads = 0;
		  vthread_schedule_list(tmp);

		  if (out) {
			functor_set(out, 0, St0, true);
		  }
		    // only one output?  Why not propagate?
		    //schedule_assign(out, 0, 0);
	    }
      }
}

/*
**  Create an event functor
**  edge:  compile_event(label, type, argc, argv)
**  or:    compile_event(label, NULL, argc, argv)
**  name:  compile_event(label, name, NULL, NULL)
*/

void compile_event(char*label, char*type,
		   unsigned argc, struct symb_s*argv)
{
      event_functor_s::edge_t edge = vvp_edge_none;

      if (argc && type) {
	    if (strcmp(type,"posedge") == 0)
		  edge = vvp_edge_posedge;
	    else if (strcmp(type,"negedge") == 0)
		  edge = vvp_edge_negedge;
	    else if (strcmp(type,"edge") == 0)
		  edge = vvp_edge_anyedge;

	    assert(argc <= 4 || edge == vvp_edge_none);
      }

      if (!argc && type) {
	    // "type" is the name of the named event
      }

      free(type);

      functor_t obj = new event_functor_s(edge);

      vvp_ipoint_t fdx = functor_allocate(1);
      functor_define(fdx, obj);
      define_functor_symbol(label, fdx);
      free(label);

	/* Run through the arguments looking for the functors that are
	   connected to my input ports. For each source functor that I
	   find, connect the output of that functor to the indexed
	   input by inserting myself (complete with the port number in
	   the vvp_ipoint_t) into the list that the source heads.

	   If the source functor is not declared yet, then don't do
	   the link yet. Save the reference to be resolved later. */

      if (edge != vvp_edge_none)
	    inputs_connect(fdx, argc, argv);
      else
	    // Are we sure that we have those .event/or
	    // drivers exclusively?
	    for (unsigned i=0; i<argc; i++) {
		  inputs_connect(fdx, 1, argv+i);
	    }

      free(argv);
}

/*
 * $Log: event.cc,v $
 * Revision 1.4  2002/01/24 04:17:46  steve
 *  Spelling in comment.
 *
 * Revision 1.3  2001/12/29 23:59:06  steve
 *  push events through event/or lists.
 *
 * Revision 1.2  2001/11/16 04:22:27  steve
 *  include stdlib.h for portability.
 *
 * Revision 1.1  2001/11/06 03:07:22  steve
 *  Code rearrange. (Stephan Boettcher)
 *
 */
<|endoftext|>


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

#include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"

#include <map>

#include "base/lazy_instance.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/tab_contents/web_drag_bookmark_handler_gtk.h"
#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
#include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h"
#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/base/gtk/focus_store_gtk.h"
#include "ui/base/gtk/gtk_floating_container.h"

static base::LazyInstance<std::map<
    content::WebContents*, ChromeWebContentsViewDelegateGtk*> >
        g_instances = LAZY_INSTANCE_INITIALIZER;

ChromeWebContentsViewDelegateGtk* ChromeWebContentsViewDelegateGtk::GetFor(
    content::WebContents* web_contents) {
  if (!g_instances.Get().count(web_contents))
    return 0;
  return g_instances.Get()[web_contents];
}

ChromeWebContentsViewDelegateGtk::ChromeWebContentsViewDelegateGtk(
    content::WebContents* web_contents)
    : floating_(gtk_floating_container_new()),
      constrained_window_(NULL),
      web_contents_(web_contents),
      expanded_container_(NULL),
      focus_store_(NULL) {
  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-view");
  g_signal_connect(floating_.get(), "set-floating-position",
                   G_CALLBACK(OnSetFloatingPositionThunk), this);
  DCHECK_EQ(g_instances.Get().count(web_contents), 0u);
  g_instances.Get()[web_contents] = this;
}

ChromeWebContentsViewDelegateGtk::~ChromeWebContentsViewDelegateGtk() {
  floating_.Destroy();
  DCHECK_EQ(g_instances.Get().count(web_contents_), 1u);
  g_instances.Get().erase(web_contents_);
}

void ChromeWebContentsViewDelegateGtk::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window_ == NULL);

  constrained_window_ = constrained_window;
  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
                                      constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window == constrained_window_);

  constrained_window_ = NULL;
  gtk_container_remove(GTK_CONTAINER(floating_.get()),
                       constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::Initialize(
    GtkWidget* expanded_container, ui::FocusStoreGtk* focus_store) {
  expanded_container_ = expanded_container;
  focus_store_ = focus_store;
  // We install a chrome specific handler to intercept bookmark drags for the
  // bookmark manager/extension API.
  bookmark_handler_gtk_.reset(new WebDragBookmarkHandlerGtk);

  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_container);
  gtk_widget_show(floating_.get());
}

gfx::NativeView ChromeWebContentsViewDelegateGtk::GetNativeView() const {
  return floating_.get();
}

void ChromeWebContentsViewDelegateGtk::Focus() {
  if (!constrained_window_) {
    GtkWidget* widget = web_contents_->GetView()->GetContentNativeView();
    if (widget)
      gtk_widget_grab_focus(widget);
  }
}

gboolean ChromeWebContentsViewDelegateGtk::OnNativeViewFocusEvent(
    GtkWidget* widget,
    GtkDirectionType type,
    gboolean* return_value) {
  // If we are showing a constrained window, don't allow the native view to take
  // focus.
  if (constrained_window_) {
    // If we return false, it will revert to the default handler, which will
    // take focus. We don't want that. But if we return true, the event will
    // stop being propagated, leaving focus wherever it is currently. That is
    // also bad. So we return false to let the default handler run, but take
    // focus first so as to trick it into thinking the view was already focused
    // and allowing the event to propagate.
    gtk_widget_grab_focus(widget);
    *return_value = FALSE;
    return TRUE;
  }

  // Let the default WebContentsViewGtk::OnFocus() behaviour run.
  return FALSE;
}

void ChromeWebContentsViewDelegateGtk::ShowContextMenu(
    const content::ContextMenuParams& params,
    content::ContextMenuSourceType type) {
  // Find out the RenderWidgetHostView that corresponds to the render widget on
  // which this context menu is showed, so that we can retrieve the last mouse
  // down event on the render widget and use it as the timestamp of the
  // activation event to show the context menu.
  content::RenderWidgetHostView* view = NULL;
  if (params.custom_context.render_widget_id !=
      content::CustomContextMenuContext::kCurrentRenderWidget) {
    content::RenderWidgetHost* host =
        web_contents_->GetRenderProcessHost()->GetRenderWidgetHostByID(
            params.custom_context.render_widget_id);
    if (!host) {
      NOTREACHED();
      return;
    }
    view = host->GetView();
  } else {
    view = web_contents_->GetRenderWidgetHostView();
  }

  context_menu_.reset(
      new RenderViewContextMenuGtk(web_contents_, params, view));
  context_menu_->Init();

  gfx::Rect bounds;
  web_contents_->GetView()->GetContainerBounds(&bounds);
  gfx::Point point = bounds.origin();
  point.Offset(params.x, params.y);
  context_menu_->Popup(point);
}

content::WebDragDestDelegate*
    ChromeWebContentsViewDelegateGtk::GetDragDestDelegate() {
  return bookmark_handler_gtk_.get();
}

void ChromeWebContentsViewDelegateGtk::OnSetFloatingPosition(
    GtkWidget* floating_container, GtkAllocation* allocation) {
  if (!constrained_window_)
    return;

  // Place each ConstrainedWindow in the center of the view.
  GtkWidget* widget = constrained_window_->widget();
  DCHECK(gtk_widget_get_parent(widget) == floating_.get());

  GtkRequisition requisition;
  gtk_widget_size_request(widget, &requisition);

  GValue value = { 0, };
  g_value_init(&value, G_TYPE_INT);

  int child_x = std::max((allocation->width - requisition.width) / 2, 0);
  g_value_set_int(&value, child_x);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "x", &value);

  int child_y = std::max((allocation->height - requisition.height) / 2, 0);
  g_value_set_int(&value, child_y);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "y", &value);
  g_value_unset(&value);
}

namespace chrome {

content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
    content::WebContents* web_contents) {
  return new ChromeWebContentsViewDelegateGtk(web_contents);
}

}  // namespace chrome
<commit_msg>Clean up ChromeWebContentsViewDelegateGtk.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"

#include <map>

#include "base/lazy_instance.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/tab_contents/web_drag_bookmark_handler_gtk.h"
#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
#include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h"
#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/base/gtk/focus_store_gtk.h"
#include "ui/base/gtk/gtk_floating_container.h"

namespace {

const char kViewDelegateUserDataKey[] = "ChromeWebContentsViewDelegateGtk";

class ViewDelegateUserData : public base::SupportsUserData::Data {
 public:
  explicit ViewDelegateUserData(ChromeWebContentsViewDelegateGtk* view_delegate)
      : view_delegate_(view_delegate) {}
  virtual ~ViewDelegateUserData() {}
  ChromeWebContentsViewDelegateGtk* view_delegate() { return view_delegate_; }

 private:
  ChromeWebContentsViewDelegateGtk* view_delegate_;  // unowned
};

}  // namespace

ChromeWebContentsViewDelegateGtk* ChromeWebContentsViewDelegateGtk::GetFor(
    content::WebContents* web_contents) {
  ViewDelegateUserData* user_data = static_cast<ViewDelegateUserData*>(
      web_contents->GetUserData(&kViewDelegateUserDataKey));

  return user_data ? user_data->view_delegate() : NULL;
}

ChromeWebContentsViewDelegateGtk::ChromeWebContentsViewDelegateGtk(
    content::WebContents* web_contents)
    : floating_(gtk_floating_container_new()),
      constrained_window_(NULL),
      web_contents_(web_contents),
      expanded_container_(NULL),
      focus_store_(NULL) {
  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-view");
  g_signal_connect(floating_.get(), "set-floating-position",
                   G_CALLBACK(OnSetFloatingPositionThunk), this);

  // Stash this in the WebContents.
  web_contents->SetUserData(&kViewDelegateUserDataKey,
                            new ViewDelegateUserData(this));
}

ChromeWebContentsViewDelegateGtk::~ChromeWebContentsViewDelegateGtk() {
  floating_.Destroy();
}

void ChromeWebContentsViewDelegateGtk::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window_ == NULL);

  constrained_window_ = constrained_window;
  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
                                      constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window == constrained_window_);

  constrained_window_ = NULL;
  gtk_container_remove(GTK_CONTAINER(floating_.get()),
                       constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::Initialize(
    GtkWidget* expanded_container, ui::FocusStoreGtk* focus_store) {
  expanded_container_ = expanded_container;
  focus_store_ = focus_store;
  // We install a chrome specific handler to intercept bookmark drags for the
  // bookmark manager/extension API.
  bookmark_handler_gtk_.reset(new WebDragBookmarkHandlerGtk);

  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_container);
  gtk_widget_show(floating_.get());
}

gfx::NativeView ChromeWebContentsViewDelegateGtk::GetNativeView() const {
  return floating_.get();
}

void ChromeWebContentsViewDelegateGtk::Focus() {
  if (!constrained_window_) {
    GtkWidget* widget = web_contents_->GetView()->GetContentNativeView();
    if (widget)
      gtk_widget_grab_focus(widget);
  }
}

gboolean ChromeWebContentsViewDelegateGtk::OnNativeViewFocusEvent(
    GtkWidget* widget,
    GtkDirectionType type,
    gboolean* return_value) {
  // If we are showing a constrained window, don't allow the native view to take
  // focus.
  if (constrained_window_) {
    // If we return false, it will revert to the default handler, which will
    // take focus. We don't want that. But if we return true, the event will
    // stop being propagated, leaving focus wherever it is currently. That is
    // also bad. So we return false to let the default handler run, but take
    // focus first so as to trick it into thinking the view was already focused
    // and allowing the event to propagate.
    gtk_widget_grab_focus(widget);
    *return_value = FALSE;
    return TRUE;
  }

  // Let the default WebContentsViewGtk::OnFocus() behaviour run.
  return FALSE;
}

void ChromeWebContentsViewDelegateGtk::ShowContextMenu(
    const content::ContextMenuParams& params,
    content::ContextMenuSourceType type) {
  // Find out the RenderWidgetHostView that corresponds to the render widget on
  // which this context menu is showed, so that we can retrieve the last mouse
  // down event on the render widget and use it as the timestamp of the
  // activation event to show the context menu.
  content::RenderWidgetHostView* view = NULL;
  if (params.custom_context.render_widget_id !=
      content::CustomContextMenuContext::kCurrentRenderWidget) {
    content::RenderWidgetHost* host =
        web_contents_->GetRenderProcessHost()->GetRenderWidgetHostByID(
            params.custom_context.render_widget_id);
    if (!host) {
      NOTREACHED();
      return;
    }
    view = host->GetView();
  } else {
    view = web_contents_->GetRenderWidgetHostView();
  }

  context_menu_.reset(
      new RenderViewContextMenuGtk(web_contents_, params, view));
  context_menu_->Init();

  gfx::Rect bounds;
  web_contents_->GetView()->GetContainerBounds(&bounds);
  gfx::Point point = bounds.origin();
  point.Offset(params.x, params.y);
  context_menu_->Popup(point);
}

content::WebDragDestDelegate*
    ChromeWebContentsViewDelegateGtk::GetDragDestDelegate() {
  return bookmark_handler_gtk_.get();
}

void ChromeWebContentsViewDelegateGtk::OnSetFloatingPosition(
    GtkWidget* floating_container, GtkAllocation* allocation) {
  if (!constrained_window_)
    return;

  // Place each ConstrainedWindow in the center of the view.
  GtkWidget* widget = constrained_window_->widget();
  DCHECK(gtk_widget_get_parent(widget) == floating_.get());

  GtkRequisition requisition;
  gtk_widget_size_request(widget, &requisition);

  GValue value = { 0, };
  g_value_init(&value, G_TYPE_INT);

  int child_x = std::max((allocation->width - requisition.width) / 2, 0);
  g_value_set_int(&value, child_x);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "x", &value);

  int child_y = std::max((allocation->height - requisition.height) / 2, 0);
  g_value_set_int(&value, child_y);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "y", &value);
  g_value_unset(&value);
}

namespace chrome {

content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
    content::WebContents* web_contents) {
  return new ChromeWebContentsViewDelegateGtk(web_contents);
}

}  // namespace chrome
<|endoftext|>


<commit_before>// bdls_osutil.cpp                                                    -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#include <bdls_osutil.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(bdls_osutil_cpp, "$Id$ $CSID$")

#include <bdls_processutil.h>

#include <bsl_cstring.h>
#include <bsl_sstream.h>

#include <bslmf_assert.h>

#include <bsls_platform.h>

#ifdef BSLS_PLATFORM_OS_WINDOWS
# include <bsl_limits.h>

# include "windows.h"
# include "VersionHelpers.h"
#else
# include <unistd.h>
# include <sys/utsname.h>
#endif

namespace BloombergLP {

                            // --------------------
                            // struct bdls::OsUtil
                            // --------------------

// CLASS METHODS
#ifdef BSLS_PLATFORM_OS_WINDOWS

namespace bdls {
int OsUtil::getOsInfo(bsl::string *osName,
                      bsl::string *osVersion,
                      bsl::string *osPatch)
{
    BSLS_ASSERT(osName);
    BSLS_ASSERT(osVersion);
    BSLS_ASSERT(osPatch);

    *osName = "Windows";

    // On Windows, 'WORD' means a 16-bit unsigned int.

    WORD major = 0;
    WORD minor = 0;
    WORD servicePackMajor = 0;

    const WORD maxWord = bsl::numeric_limits<WORD>::max();

    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (major >= maxWord) {
            return -1;                                                // RETURN
	}
        ++major;
    }
    --major;
    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (minor >= maxWord) {
            return -1;                                                // RETURN
	}
        ++minor;
    }
    --minor;
    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (servicePackMajor >= maxWord) {
            return -1;                                                // RETURN
	}
        ++servicePackMajor;
    }
    --servicePackMajor;

    // Os version
    bsl::ostringstream version;
    version << major << '.' << minor;
    *osVersion = version.str();
    version.str("");

    // Service pack number
    if (servicePackMajor) {
        version << "Service Pack " << servicePackMajor << ".0";
    }
    *osPatch = version.str();

    return 0;
}
}  // close package namespace

#elif defined(BSLS_PLATFORM_OS_UNIX)

namespace bdls {
int OsUtil::getOsInfo(bsl::string *osName,
                      bsl::string *osVersion,
                      bsl::string *osPatch)
{
    BSLS_ASSERT(osName);
    BSLS_ASSERT(osVersion);
    BSLS_ASSERT(osPatch);

    struct utsname unameInfo;
    if (-1 == uname(&unameInfo)) {
        return -1;                                                    // RETURN
    }
    *osName = unameInfo.sysname;
    *osVersion = unameInfo.release;
    *osPatch = unameInfo.version;
    return 0;
}
}  // close package namespace

#else

BSLMF_ASSERT("Unsupported operating system", false);

#endif
}  // close enterprise namespace

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
<commit_msg>bdls_osutil: #idef 2 imps, for pre & post Vista compiles<commit_after>// bdls_osutil.cpp                                                    -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#include <bdls_osutil.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(bdls_osutil_cpp, "$Id$ $CSID$")

#include <bdls_processutil.h>

#include <bslmf_assert.h>
#include <bsls_platform.h>

#include <bsl_cstring.h>
#include <bsl_sstream.h>

#ifdef BSLS_PLATFORM_OS_WINDOWS
# undef u_VISTA_OR_LATER
# if 6 <= BSLS_PLATFORM_OS_VER_MAJOR
#   define u_VISTA_OR_LATER 1
# endif

# include <windows.h>
# ifdef u_VISTA_OR_LATER
#   include <bsl_limits.h>
#   include "VersionHelpers.h"
# else
#   include <process.h>
# endif
#else
# include <unistd.h>
# include <sys/utsname.h>
#endif

namespace BloombergLP {

                            // --------------------
                            // struct bdls::OsUtil
                            // --------------------

// CLASS METHODS
#ifdef BSLS_PLATFORM_OS_WINDOWS

namespace bdls {
int OsUtil::getOsInfo(bsl::string *osName,
                      bsl::string *osVersion,
                      bsl::string *osPatch)
{
    BSLS_ASSERT(osName);
    BSLS_ASSERT(osVersion);
    BSLS_ASSERT(osPatch);

    *osName = "Windows";

#ifdef u_VISTA_OR_LATER
    // On Windows, 'WORD' means a 16-bit unsigned int.

    WORD major = 0;
    WORD minor = 0;
    WORD servicePackMajor = 0;

    const WORD maxWord = bsl::numeric_limits<WORD>::max();

    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (major >= maxWord) {
            return -1;                                                // RETURN
	}
        ++major;
    }
    --major;
    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (minor >= maxWord) {
            return -1;                                                // RETURN
	}
        ++minor;
    }
    --minor;
    while (IsWindowsVersionOrGreater(major, minor, servicePackMajor)) {
        if (servicePackMajor >= maxWord) {
            return -1;                                                // RETURN
	}
        ++servicePackMajor;
    }
    --servicePackMajor;

    // Os version

    bsl::ostringstream version;
    version << major << '.' << minor;
    *osVersion = version.str();
    version.str("");

    // Service pack number

    if (servicePackMajor) {
        // Note that we are incapable of detecting any 'servicePackMinor'
        // version other than 0.  But it seems rational that if Microsoft had
        // any plans for non-zero 'servicePackMinor' version at or after
        // Vista, they would have made 'IsWindowsVersionOrGreater' take 4 args
        // instead of 3.

        version << "Service Pack " << servicePackMajor << ".0";
    }
    *osPatch = version.str();

#else

    OSVERSIONINFOEX osvi;

    bsl::memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

    if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
        return -1;
    }

    // Os version

    bsl::ostringstream version;
    version << osvi.dwMajorVersion << '.' << osvi.dwMinorVersion;
    *osVersion = version.str();

    version.clear();
    version.str("");

    // Service pack number

    if (osvi.wServicePackMajor) {
        version << "Service Pack " << osvi.wServicePackMajor << '.'
                << osvi.wServicePackMinor;
    }
    *osPatch = version.str();

#endif

    return 0;
}
}  // close package namespace

#elif defined(BSLS_PLATFORM_OS_UNIX)

namespace bdls {
int OsUtil::getOsInfo(bsl::string *osName,
                      bsl::string *osVersion,
                      bsl::string *osPatch)
{
    BSLS_ASSERT(osName);
    BSLS_ASSERT(osVersion);
    BSLS_ASSERT(osPatch);

    struct utsname unameInfo;
    if (-1 == uname(&unameInfo)) {
        return -1;                                                    // RETURN
    }
    *osName = unameInfo.sysname;
    *osVersion = unameInfo.release;
    *osPatch = unameInfo.version;
    return 0;
}
}  // close package namespace

#else

BSLMF_ASSERT("Unsupported operating system", false);

#endif
}  // close enterprise namespace

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


<commit_before>#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/mls.h>

int
 main (int argc, char** argv)
{
  // Load input file into a PointCloud<T> with an appropriate type
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
  sensor_msgs::PointCloud2 cloud_blob;
  // Load bun0.pcd -- should be available with the PCL archive in test
  pcl::io::loadPCDFile ("bun0.pcd", cloud_blob);
  pcl::fromROSMsg (cloud_blob, *cloud);

  // Create a KD-Tree
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  tree->setInputCloud (cloud);

  // Output has the same type as the input one, it will be only smoothed
  pcl::PointCloud<pcl::PointXYZ> mls_points;

  // Init object (second point type is for the normals, even if unused)
  pcl::MovingLeastSquares<pcl::PointXYZ, pcl::Normal> mls;

  // Optionally, a pointer to a cloud can be provided, to be set by MLS
  pcl::PointCloud<pcl::Normal>::Ptr mls_normals (new pcl::PointCloud<pcl::Normal> ());
  mls.setOutputNormals (mls_normals);

  // Set parameters
  mls.setInputCloud (cloud);
  mls.setPolynomialFit (true);
  mls.setSearchMethod (tree);
  mls.setSearchRadius (0.03);

  // Reconstruct
  mls.reconstruct (mls_points);

  // Concatenate fields for saving
  pcl::PointCloud<pcl::PointNormal> mls_cloud;
  pcl::concatenateFields (mls_points, *mls_normals, mls_cloud);

  // Save output
  pcl::io::savePCDFile ("bun0-mls.pcd", mls_cloud);
}
<commit_msg>* fixed issue #441 where the resampling tutorial was setting the input twice: once in the tutorial code, and once inside the @MovingLeastSquares@ class (thanks Peter!)<commit_after>#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/mls.h>

int
 main (int argc, char** argv)
{
  // Load input file into a PointCloud<T> with an appropriate type
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
  sensor_msgs::PointCloud2 cloud_blob;
  // Load bun0.pcd -- should be available with the PCL archive in test
  pcl::io::loadPCDFile ("bun0.pcd", cloud_blob);
  pcl::fromROSMsg (cloud_blob, *cloud);

  // Create a KD-Tree
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);

  // Output has the same type as the input one, it will be only smoothed
  pcl::PointCloud<pcl::PointXYZ> mls_points;

  // Init object (second point type is for the normals, even if unused)
  pcl::MovingLeastSquares<pcl::PointXYZ, pcl::Normal> mls;

  // Optionally, a pointer to a cloud can be provided, to be set by MLS
  pcl::PointCloud<pcl::Normal>::Ptr mls_normals (new pcl::PointCloud<pcl::Normal> ());
  mls.setOutputNormals (mls_normals);

  // Set parameters
  mls.setInputCloud (cloud);
  mls.setPolynomialFit (true);
  mls.setSearchMethod (tree);
  mls.setSearchRadius (0.03);

  // Reconstruct
  mls.reconstruct (mls_points);

  // Concatenate fields for saving
  pcl::PointCloud<pcl::PointNormal> mls_cloud;
  pcl::concatenateFields (mls_points, *mls_normals, mls_cloud);

  // Save output
  pcl::io::savePCDFile ("bun0-mls.pcd", mls_cloud);
}
<|endoftext|>


<commit_before>#define _CRT_SECURE_NO_WARNINGS
#include"../main/IOfunction.h"
#include"../main/memoryfunction.h"
#include<unordered_map>
#include<queue>
#include<string>
#include<iostream>
using namespace std;

struct product{
	int pid;
	double sim;
	product(int _id, double _sim) {
		pid = _id;
		sim = _sim;
	}
};
struct compare{
	bool operator()(product &a, product &b) {
		return a.sim > b.sim;
	}
};
class ProductSim{
	unordered_map<string, int> labels;
	priority_queue<product, vector<product>, compare> Q;
	int K = 20;
	vector<string> nodelabels;
	DIR *dir = NULL;
	struct dirent *ent;
	vector<string> filenames;
	int productnum;
public:
	ProductSim(int num){
		productnum = num;
		nodelabels.resize(num);
	}
	~ProductSim() {
		filenames.clear();
		if (ent != NULL) {
			free(ent);
			ent = NULL;
		}
	}
	void readNodeLabel(string filename) {
		ifstream infile(filename);
		if (infile.is_open() == false) {
			cout << "could not open the filename" << endl;
			exit(4);
		}
		int idx;
		string s;
		string strLine;
		while (!infile.eof()) {
			getline(infile, strLine);
			std::size_t found = strLine.find_last_of("\t");
			s =  str.substr(0,found);
			idx = stoi(str.substr(found + 1));
			labels[s] = idx;
			nodelabels[idx] = s;
		}
		infile.close();
	}

	void listfileinDir(string dirname) {
		if ((dir = opendir(dirname.c_str())) != NULL) {
			/* print all the files and directories within directory */
			while ((ent = readdir(dir)) != NULL) {
				if (ent->d_name[0] != '.'){
					filenames.push_back(dirname+"/"+ent->d_name);
				}
			}
			closedir(dir);
		}
		else {
			/* could not open directory */
			perror("could not open directory");
			exit(EXIT_FAILURE);
		}
	}

	void computesim(string productname) {
		if (this->labels.find(productname) == labels.end()) {
			cout << "the product does not exit in our data" << endl;
			exit(4);
		}
		else {
			int idx = labels[productname];
			SparseMatrix Z;
			Z.Initmemory(productnum);
			Z.setcolumnnum(20);
			FILE *rfile = NULL;
			for (int t = 0; t < filenames.size(); t++) {
				rfile = fopen(filenames[t].c_str(), "r");
				if (rfile == NULL) {
					cout << "could not open file to read" << endl;
					exit(4);
				}
				Readcommunity(Z, productnum, rfile);
				for (int j = 0; j < productnum; j++) {
					if (j != idx) {
						double sim = Z.Rowdotproduct2(idx, j);
						product a(j, sim);
						if (Q.size() < K) {
							Q.push(a);
						}
						else if (sim >= Q.top().sim) {
							Q.pop();
							Q.push(a);
						}
					}
				}
				//output the similar products;
				while (!Q.empty()) {
					product o = Q.top();
					cout << t << "\t" << nodelabels[o.pid] << "\t" << o.sim << endl;
					Q.pop();
				}

				//release the memory of Z;
				Z.clear();
			}
			Z.deletemem();
		}
	}
};

int main (int argc, char *argv[]) {
	if (argc < 1) {
		cout << "Usage " << argv[0];
		cout << "[#product] [embedding-file-name] [node-label-file-name] [product-name]" << endl;
		exit(4);
	}
	int v = atoi(argv[1]);
	ProductSim a(v);
	string dirname(argv[2]);
	string labelname(argv[3]);
	string productname(argv[4]);
	Initmemory();
	InitIOmemory();
	filebuffer = new char[BYTE_TO_READ];
	a.listfileinDir(dirname);
	a.readNodeLabel(labelname);
	a.computesim(productname);
	releaseIOmemory();
	releaseblockmemory();
	return 0;
}
<commit_msg>rename<commit_after>#define _CRT_SECURE_NO_WARNINGS
#include"../main/IOfunction.h"
#include"../main/memoryfunction.h"
#include<unordered_map>
#include<queue>
#include<string>
#include<iostream>
using namespace std;

struct product{
	int pid;
	double sim;
	product(int _id, double _sim) {
		pid = _id;
		sim = _sim;
	}
};
struct compare{
	bool operator()(product &a, product &b) {
		return a.sim > b.sim;
	}
};
class ProductSim{
	unordered_map<string, int> labels;
	priority_queue<product, vector<product>, compare> Q;
	int K = 20;
	vector<string> nodelabels;
	DIR *dir = NULL;
	struct dirent *ent;
	vector<string> filenames;
	int productnum;
public:
	ProductSim(int num){
		productnum = num;
		nodelabels.resize(num);
	}
	~ProductSim() {
		filenames.clear();
		if (ent != NULL) {
			free(ent);
			ent = NULL;
		}
	}
	void readNodeLabel(string filename) {
		ifstream infile(filename);
		if (infile.is_open() == false) {
			cout << "could not open the filename" << endl;
			exit(4);
		}
		int idx;
		string s;
		string strLine;
		while (!infile.eof()) {
			getline(infile, strLine);
			std::size_t found = strLine.find_last_of("\t");
			s =  strLine.substr(0,found);
			idx = stoi(strLine.substr(found + 1));
			labels[s] = idx;
			nodelabels[idx] = s;
		}
		infile.close();
	}

	void listfileinDir(string dirname) {
		if ((dir = opendir(dirname.c_str())) != NULL) {
			/* print all the files and directories within directory */
			while ((ent = readdir(dir)) != NULL) {
				if (ent->d_name[0] != '.'){
					filenames.push_back(dirname+"/"+ent->d_name);
				}
			}
			closedir(dir);
		}
		else {
			/* could not open directory */
			perror("could not open directory");
			exit(EXIT_FAILURE);
		}
	}

	void computesim(string productname) {
		if (this->labels.find(productname) == labels.end()) {
			cout << "the product does not exit in our data" << endl;
			exit(4);
		}
		else {
			int idx = labels[productname];
			SparseMatrix Z;
			Z.Initmemory(productnum);
			Z.setcolumnnum(20);
			FILE *rfile = NULL;
			for (int t = 0; t < filenames.size(); t++) {
				rfile = fopen(filenames[t].c_str(), "r");
				if (rfile == NULL) {
					cout << "could not open file to read" << endl;
					exit(4);
				}
				Readcommunity(Z, productnum, rfile);
				for (int j = 0; j < productnum; j++) {
					if (j != idx) {
						double sim = Z.Rowdotproduct2(idx, j);
						product a(j, sim);
						if (Q.size() < K) {
							Q.push(a);
						}
						else if (sim >= Q.top().sim) {
							Q.pop();
							Q.push(a);
						}
					}
				}
				//output the similar products;
				while (!Q.empty()) {
					product o = Q.top();
					cout << t << "\t" << nodelabels[o.pid] << "\t" << o.sim << endl;
					Q.pop();
				}

				//release the memory of Z;
				Z.clear();
			}
			Z.deletemem();
		}
	}
};

int main (int argc, char *argv[]) {
	if (argc < 1) {
		cout << "Usage " << argv[0];
		cout << "[#product] [embedding-file-name] [node-label-file-name] [product-name]" << endl;
		exit(4);
	}
	int v = atoi(argv[1]);
	ProductSim a(v);
	string dirname(argv[2]);
	string labelname(argv[3]);
	string productname(argv[4]);
	Initmemory();
	InitIOmemory();
	filebuffer = new char[BYTE_TO_READ];
	a.listfileinDir(dirname);
	a.readNodeLabel(labelname);
	a.computesim(productname);
	releaseIOmemory();
	releaseblockmemory();
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>various improvements in signals<commit_after><|endoftext|>